diff --git a/src/components/article/boxes/ArticleViewLists.jsx b/src/components/article/boxes/ArticleViewLists.jsx
index fe93ed0..448df3f 100644
--- a/src/components/article/boxes/ArticleViewLists.jsx
+++ b/src/components/article/boxes/ArticleViewLists.jsx
@@ -45,7 +45,7 @@ import {
alpha,
} from '../../../colors';
-function getVariantDetails(child, allArticles, defaultTaxRate) {
+function getVariantDetails(child, allArticles, defaultTaxRate, parentArticle) {
const cached = child?.sku ? getArticle(child.sku) : null;
const fromIndex = !cached && child?.sku
? (allArticles || []).find((a) => a.sku === child.sku)
@@ -56,14 +56,30 @@ function getVariantDetails(child, allArticles, defaultTaxRate) {
const gross = getArticleGross(merged, defaultTaxRate);
const priceDisplay = gross != null && Number.isFinite(gross) ? formatPrice(gross) : null;
- // 2. Stock & Unit
+ // 2. Stock tracking
+ const rawTrack =
+ merged.track_stock ??
+ merged.trackStock ??
+ child?.trackStock ??
+ child?.track_stock ??
+ parentArticle?.track_stock ??
+ parentArticle?.trackStock;
+
+ const trackStock =
+ rawTrack !== undefined
+ ? rawTrack !== false && rawTrack !== 0 && rawTrack !== '0'
+ : true;
+
+ // 3. Stock & Unit
let stockVal = null;
- if (Array.isArray(merged.warehouses) && merged.warehouses.length > 0) {
- stockVal = merged.warehouses.reduce((sum, wh) => sum + (Number(wh.stock) || 0), 0);
- } else if (merged.stock != null && !Number.isNaN(Number(merged.stock))) {
- stockVal = Number(merged.stock);
- } else if (child?.stock != null && !Number.isNaN(Number(child.stock))) {
- stockVal = Number(child.stock);
+ if (trackStock) {
+ if (Array.isArray(merged.warehouses) && merged.warehouses.length > 0) {
+ stockVal = merged.warehouses.reduce((sum, wh) => sum + (Number(wh.stock) || 0), 0);
+ } else if (merged.stock != null && !Number.isNaN(Number(merged.stock))) {
+ stockVal = Number(merged.stock);
+ } else if (child?.stock != null && !Number.isNaN(Number(child.stock))) {
+ stockVal = Number(child.stock);
+ }
}
const rawUnit =
@@ -76,9 +92,9 @@ function getVariantDetails(child, allArticles, defaultTaxRate) {
rawUnit && !['stk', 'stück', 'pc', 'stk.'].includes(rawUnit.trim().toLowerCase())
? ` ${rawUnit}`
: '';
- const stockDisplay = stockVal != null ? `${formatStock(stockVal)}${unit}` : null;
+ const stockDisplay = trackStock && stockVal != null ? `${formatStock(stockVal)}${unit}` : null;
- // 3. EAN(s)
+ // 4. EAN(s)
const eanCandidates = [];
const rawEans = merged.eans ?? child?.eans;
if (Array.isArray(rawEans)) {
@@ -103,6 +119,7 @@ function getVariantDetails(child, allArticles, defaultTaxRate) {
stockDisplay,
primaryEan,
allEans: eanCandidates,
+ trackStock,
};
}
@@ -199,7 +216,7 @@ export default class ArticleViewLists extends PureComponent {
if (!this._cancelled && parent?.children) {
this.ensureChildren(parent.children);
}
- }).catch(() => {});
+ }).catch(() => { });
}
void this.loadAllArticles();
@@ -220,7 +237,7 @@ export default class ArticleViewLists extends PureComponent {
if (!this._cancelled && parent?.children) {
this.ensureChildren(parent.children);
}
- }).catch(() => {});
+ }).catch(() => { });
} else {
const parent = getArticle(this.props.article.parentSku);
if (parent?.children) {
@@ -268,7 +285,7 @@ export default class ArticleViewLists extends PureComponent {
if (!Array.isArray(children)) return;
for (const child of children) {
if (child?.sku && !getArticle(child.sku)) {
- void artikelAutomat.actions.loadArticle(child.sku).catch(() => {});
+ void artikelAutomat.actions.loadArticle(child.sku).catch(() => { });
}
}
}
@@ -393,30 +410,41 @@ export default class ArticleViewLists extends PureComponent {
const { selectedChildValueId, newChildText, isCustomChildValue, busy } = this.state;
if (busy || !article?.sku) return;
+ const val = newChildText.trim();
const payload = {};
- if (isCustomChildValue) {
- const val = newChildText.trim();
- if (!val) return;
+
+ if (val && (isCustomChildValue || !selectedChildValueId)) {
+ payload.value = val;
+ } else if (selectedChildValueId) {
+ payload.attributeValueId = Number(selectedChildValueId);
+ } else if (val) {
payload.value = val;
} else {
- if (!selectedChildValueId) return;
- payload.attributeValueId = Number(selectedChildValueId);
+ return;
}
this.setState({ busy: true });
try {
const api = this.getApi();
- await api.addChild(article.sku, payload);
+ const res = await api.addChild(article.sku, payload);
if (this._cancelled) return;
+ if (res?.sku) {
+ void artikelAutomat.actions.loadArticle(res.sku).catch(() => { });
+ }
+
await artikelAutomat.actions.reloadArticle(article.sku);
if (this._cancelled) return;
+ void articleIndexAutomat.actions.reload().catch(() => { });
+ void companyAutomat.actions.loadAttributes?.().catch?.(() => { });
+
enqueueSnackbar('Variante erfolgreich angelegt.', { variant: 'success' });
this.setState({
busy: false,
selectedChildValueId: '',
newChildText: '',
+ isCustomChildValue: false,
});
} catch (err) {
if (this._cancelled) return;
@@ -491,17 +519,17 @@ export default class ArticleViewLists extends PureComponent {
const nextItems =
existingIndex >= 0
? currentItems.map((item, idx) =>
- idx === existingIndex ? { ...item, count: item.count + count } : item
- )
+ idx === existingIndex ? { ...item, count: item.count + count } : item
+ )
: [
- ...currentItems,
- {
- articleId: stuecklisteTargetArticle.id,
- sku: stuecklisteTargetArticle.sku,
- count,
- sort: currentItems.length,
- },
- ];
+ ...currentItems,
+ {
+ articleId: stuecklisteTargetArticle.id,
+ sku: stuecklisteTargetArticle.sku,
+ count,
+ sort: currentItems.length,
+ },
+ ];
this.setState({ busy: true });
try {
@@ -615,20 +643,20 @@ export default class ArticleViewLists extends PureComponent {
const nextOptions =
existingIndex >= 0
? currentOptions.map((opt, idx) =>
- idx === existingIndex
- ? { ...opt, count: opt.count + count, mandated: Boolean(optionMandated) }
- : opt
- )
+ idx === existingIndex
+ ? { ...opt, count: opt.count + count, mandated: Boolean(optionMandated) }
+ : opt
+ )
: [
- ...currentOptions,
- {
- articleId: optionTargetArticle.id,
- sku: optionTargetArticle.sku,
- count,
- sort: currentOptions.length,
- mandated: Boolean(optionMandated),
- },
- ];
+ ...currentOptions,
+ {
+ articleId: optionTargetArticle.id,
+ sku: optionTargetArticle.sku,
+ count,
+ sort: currentOptions.length,
+ mandated: Boolean(optionMandated),
+ },
+ ];
this.setState({ busy: true });
try {
@@ -834,70 +862,70 @@ export default class ArticleViewLists extends PureComponent {
}}
>
{stuecklisteItems.map((item) => (
-
+
+
+
+
+ {item.name || item.sku}
+
+
+ {item.sku}
+
+
+
+
+ this.handleRemoveStuecklisteItem(item.sku)}
sx={{
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'space-between',
- px: 1,
- py: 0.4,
- borderRadius: 1,
- bgcolor: 'background.paper',
- border: '1px solid',
- borderColor: 'divider',
+ p: 0.25,
+ color: 'text.secondary',
+ '&:hover': { color: 'error.main' },
}}
>
-
-
-
-
- {item.name || item.sku}
-
-
- {item.sku}
-
-
-
-
- this.handleRemoveStuecklisteItem(item.sku)}
- sx={{
- p: 0.25,
- color: 'text.secondary',
- '&:hover': { color: 'error.main' },
- }}
- >
-
-
-
- ))
+
+
+
+ ))
}
@@ -1044,81 +1072,81 @@ export default class ArticleViewLists extends PureComponent {
}}
>
{optionsItems.map((opt) => (
-
-
-
-
-
+
+
+
+
+ {opt.name || opt.sku}
+
+
+
- {opt.name || opt.sku}
-
-
-
- {opt.sku}
-
- {opt.mandated ? (
-
- ) : null}
-
+ {opt.sku}
+
+ {opt.mandated ? (
+
+ ) : null}
-
- this.handleRemoveOption(opt.sku)}
- sx={{
- p: 0.25,
- color: 'text.secondary',
- '&:hover': { color: 'error.main' },
- }}
- >
-
-
- ))
+
+ this.handleRemoveOption(opt.sku)}
+ sx={{
+ p: 0.25,
+ color: 'text.secondary',
+ '&:hover': { color: 'error.main' },
+ }}
+ >
+
+
+
+ ))
}
@@ -1211,14 +1239,14 @@ export default class ArticleViewLists extends PureComponent {
const siblings = hasSelf
? childrenList
: [
- ...childrenList,
- {
- id: articleData.id,
- sku: articleData.sku,
- name: articleData.name,
- attributeValue: variationValue,
- },
- ];
+ ...childrenList,
+ {
+ id: articleData.id,
+ sku: articleData.sku,
+ name: articleData.name,
+ attributeValue: variationValue,
+ },
+ ];
return (
@@ -1348,7 +1376,8 @@ export default class ArticleViewLists extends PureComponent {
stockDisplay,
primaryEan,
allEans,
- } = getVariantDetails(sibling, allArticles, defaultTaxRate);
+ trackStock,
+ } = getVariantDetails(sibling, allArticles, defaultTaxRate, parentArticle);
return (
0 ? 'success.dark' : 'error.main',
+ color: !trackStock || stockVal == null ? 'text.disabled' : stockVal > 0 ? 'success.dark' : 'error.main',
whiteSpace: 'nowrap',
}}
>
@@ -1584,7 +1613,7 @@ export default class ArticleViewLists extends PureComponent {
sx={{
fontSize: '0.74rem',
fontWeight: 600,
- color: stockVal == null ? 'text.disabled' : stockVal > 0 ? 'success.dark' : 'error.main',
+ color: !trackStock || stockVal == null ? 'text.disabled' : stockVal > 0 ? 'success.dark' : 'error.main',
whiteSpace: 'nowrap',
}}
>
@@ -1908,11 +1937,7 @@ export default class ArticleViewLists extends PureComponent {
Varianten:
- {children.length === 0 ? (
-
- Noch keine Varianten angelegt.
-
- ) : (
+ {children.length === 0 ? null : (
{children.map((child) => {
const defaultTaxRate = this.state.company?.taxrate ?? companyAutomat.state.current?.taxrate ?? 19;
@@ -1922,7 +1947,8 @@ export default class ArticleViewLists extends PureComponent {
stockDisplay,
primaryEan,
allEans,
- } = getVariantDetails(child, allArticles, defaultTaxRate);
+ trackStock,
+ } = getVariantDetails(child, allArticles, defaultTaxRate, articleData);
return (
0 ? 'success.dark' : 'error.main',
+ color: !trackStock || stockVal == null ? 'text.disabled' : stockVal > 0 ? 'success.dark' : 'error.main',
whiteSpace: 'nowrap',
}}
>
@@ -2077,7 +2103,6 @@ export default class ArticleViewLists extends PureComponent {
size="small"
disabled={busy}
onClick={() => this.handleOpenRemoveDialog(child)}
- title="Variante entfernen"
sx={{
p: 0.35,
color: 'text.secondary',
@@ -2098,7 +2123,6 @@ export default class ArticleViewLists extends PureComponent {
{isCustomChildValue || availableParentValues.length === 0 ? (
this.setState({ newChildText: e.target.value })}
@@ -2143,34 +2167,31 @@ export default class ArticleViewLists extends PureComponent {
)}
-
-
-
- {busy ? : }
-
-
-
+
+ {busy ? : }
+
{/* Toggle custom value / predefined value if values exist */}
@@ -2205,16 +2226,16 @@ export default class ArticleViewLists extends PureComponent {
)}
{isStueckliste ||
- hasOptions ||
- activeCreatorMode === 'stueckliste' ||
- activeCreatorMode === 'options'
+ hasOptions ||
+ activeCreatorMode === 'stueckliste' ||
+ activeCreatorMode === 'options'
? this.renderCompoundManager(
- isStueckliste,
- hasOptions,
- stuecklisteItems,
- optionsItems,
- selectableOtherArticles
- )
+ isStueckliste,
+ hasOptions,
+ stuecklisteItems,
+ optionsItems,
+ selectableOtherArticles
+ )
: this.renderStandardView(selectableAttributes, assignedAttributeIds)}
@@ -2293,11 +2314,11 @@ export default class ArticleViewLists extends PureComponent {
{confirmClearType === 'stueckliste'
? (hasOptions
- ? 'Möchten Sie alle Komponenten aus dieser Stückliste entfernen? Die Optionen bleiben dabei erhalten.'
- : 'Möchten Sie alle Komponenten aus dieser Stückliste entfernen und den Artikel wieder als Standard-Artikel führen?')
+ ? 'Möchten Sie alle Komponenten aus dieser Stückliste entfernen? Die Optionen bleiben dabei erhalten.'
+ : 'Möchten Sie alle Komponenten aus dieser Stückliste entfernen und den Artikel wieder als Standard-Artikel führen?')
: (isStueckliste
- ? 'Möchten Sie alle Optionen von diesem Artikel entfernen? Die Stückliste bleibt dabei erhalten.'
- : 'Möchten Sie alle Optionen von diesem Artikel entfernen und ihn wieder als Standard-Artikel führen?')}
+ ? 'Möchten Sie alle Optionen von diesem Artikel entfernen? Die Stückliste bleibt dabei erhalten.'
+ : 'Möchten Sie alle Optionen von diesem Artikel entfernen und ihn wieder als Standard-Artikel führen?')}