diff --git a/src/components/article/ArticleView.jsx b/src/components/article/ArticleView.jsx
index 20fe1b6..91a2e3f 100644
--- a/src/components/article/ArticleView.jsx
+++ b/src/components/article/ArticleView.jsx
@@ -101,7 +101,7 @@ class ArticleView extends PureComponent {
article={article}
/>
-
+
diff --git a/src/components/article/boxes/ArticleViewStock.jsx b/src/components/article/boxes/ArticleViewStock.jsx
index 6a4da4c..c7093ea 100644
--- a/src/components/article/boxes/ArticleViewStock.jsx
+++ b/src/components/article/boxes/ArticleViewStock.jsx
@@ -4,11 +4,13 @@ import Typography from '@mui/material/Typography';
import WarehouseIcon from '@mui/icons-material/Warehouse';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined';
+import ShoppingCartOutlinedIcon from '@mui/icons-material/ShoppingCartOutlined';
import Tooltip from '@mui/material/Tooltip';
import { PanelTile } from 'dashgui/panels';
import { formatStock } from '../searchFormat';
import ArticleStockAdjustDialog from '../ArticleStockAdjustDialog';
import artikelAutomat, { getArticle } from '../../../automats/artikelAutomat';
+import { router } from '../../../appRouter';
import {
GREEN_PANEL,
PETROL_PANEL,
@@ -96,6 +98,58 @@ function extractIncoming(articleData, isParent) {
return items;
}
+function extractUndeliveredOrders(articleData, isParent) {
+ const items = [];
+
+ const collect = (article, variantInfo = null) => {
+ if (!article) return;
+
+ if (Array.isArray(article.undeliveredOrders)) {
+ for (const ord of article.undeliveredOrders) {
+ const amount = Number(ord?.amount) || 0;
+ if (amount > 0) {
+ items.push({
+ orderId: ord.orderId,
+ orderNumber: ord.orderNumber || (ord.orderId ? `A-${ord.orderId}` : null),
+ date: ord.date || null,
+ customerName: ord.customerName || null,
+ amount,
+ variantSku: variantInfo?.sku || null,
+ variantName: variantInfo?.name || null,
+ });
+ }
+ }
+ }
+ };
+
+ collect(articleData);
+
+ if (isParent) {
+ const children = Array.isArray(articleData?.children) ? articleData.children : [];
+ for (const child of children) {
+ const fullChild = getArticle(child.sku) || child;
+ collect(fullChild, {
+ sku: fullChild.sku || child.sku,
+ name: fullChild.name || child.name,
+ });
+ }
+ }
+
+ items.sort((a, b) => {
+ if (a.date && b.date) {
+ const diff = new Date(a.date).getTime() - new Date(b.date).getTime();
+ if (diff !== 0) return diff;
+ } else if (a.date) {
+ return -1;
+ } else if (b.date) {
+ return 1;
+ }
+ return (Number(a.orderId) || 0) - (Number(b.orderId) || 0);
+ });
+
+ return items;
+}
+
export default class ArticleViewStock extends PureComponent {
constructor(props) {
super(props);
@@ -104,6 +158,17 @@ export default class ArticleViewStock extends PureComponent {
};
this.handleOpenAdjust = this.handleOpenAdjust.bind(this);
this.handleCloseAdjust = this.handleCloseAdjust.bind(this);
+ this.handleOpenOrder = this.handleOpenOrder.bind(this);
+ }
+
+ handleOpenOrder(orderId, event) {
+ if (!orderId) return;
+ if (event?.metaKey || event?.ctrlKey) {
+ window.open(`/auftrag/bestellung/${orderId}`, '_blank');
+ return;
+ }
+ const nav = this.props.navigate || router.navigate;
+ void nav(`/auftrag/bestellung/${orderId}`);
}
componentDidMount() {
@@ -205,6 +270,10 @@ export default class ArticleViewStock extends PureComponent {
const totalIncoming = incomingItems.reduce((sum, inc) => sum + inc.amount, 0);
const hasIncoming = totalIncoming > 0;
+ const undeliveredOrders = extractUndeliveredOrders(articleData, isParent);
+ const totalUndelivered = undeliveredOrders.reduce((sum, ord) => sum + ord.amount, 0);
+ const hasUndelivered = totalUndelivered > 0;
+
return (
<>
- 0 ? 'text.primary' : 'text.secondary',
- }}
- >
- {formatStock(totalStock)}
-
- {unit ? (
+
0 ? 'text.primary' : 'text.secondary',
+ }}
>
- {unit}
+ {formatStock(totalStock)}
- ) : null}
+ {unit ? (
+
+ {unit}
+
+ ) : null}
+
) : (
@@ -374,8 +444,8 @@ export default class ArticleViewStock extends PureComponent {
)}
- {/* Bottom section: Per-warehouse breakdown & incoming shipments */}
- {hasWarehouses || hasIncoming ? (
+ {/* Bottom section: Per-warehouse breakdown, incoming shipments & open orders */}
+ {hasWarehouses || hasIncoming || hasUndelivered ? (
{incomingItems.map((inc, idx) => {
const dateLabel = inc.date ? formatDate(inc.date) : null;
- const label = [
+ const labelParts = [
+ inc.variantName,
inc.supplierName || 'Lieferant',
dateLabel,
- ]
- .filter(Boolean)
- .join(' – ');
+ ].filter(Boolean);
+ const label = labelParts.join(' – ');
return (
) : null}
+
+ {/* Undelivered / Open Customer Orders */}
+ {hasUndelivered ? (
+ <>
+ {undeliveredOrders.map((ord, idx) => {
+ const dateLabel = ord.date ? formatDate(ord.date) : null;
+ const orderLabel = ord.orderNumber || (ord.orderId ? `Auftrag #${ord.orderId}` : 'Auftrag');
+ const labelParts = [
+ ord.variantName,
+ orderLabel,
+ ord.customerName,
+ dateLabel,
+ ].filter(Boolean);
+ const label = labelParts.join(' – ');
+ const tooltipText = ord.orderId
+ ? `Auftrag ${orderLabel}${ord.customerName ? ` (${ord.customerName})` : ''} öffnen`
+ : label;
+
+ return (
+ this.handleOpenOrder(ord.orderId, e)}
+ title={tooltipText}
+ sx={{
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ py: 0.35,
+ px: 0.75,
+ borderRadius: 1,
+ backgroundColor: VEIL_PANEL,
+ cursor: ord.orderId ? 'pointer' : 'default',
+ transition: 'background-color 0.15s ease',
+ '&:hover': ord.orderId ? {
+ backgroundColor: TINT_ROW_HOVER,
+ } : undefined,
+ }}
+ >
+
+
+
+ {label}
+
+
+
+
+ -{formatStock(ord.amount)}
+
+
+ );
+ })}
+ >
+ ) : null}
) : null}