Web: Mindestbestaende in echter Einheit statt Packung
"1 Packung" ist nichtssagend (kann 500 g, 1 kg oder 25 ml sein). Die Seite zeigt und bearbeitet Produkt-Mindestbestaende jetzt in der Anzeigeeinheit des Artikels (Gramm/Milliliter/Stueck): global (Basiseinheiten) und je Lagerort (Artikel- einheiten) werden dafuer umgerechnet. Rigatoni zeigt jetzt z.B. "500 Gramm". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,14 +8,15 @@ import { categoryInfoMap } from "../categoryPath";
|
||||
import { locationPathById } from "../locationPath";
|
||||
import { fmt } from "../units";
|
||||
|
||||
// Artikeleinheit eines Produkts (Gebinde oder Produkteinheit) – wie in der Produktliste.
|
||||
// Wichtig: Zahl (articleUnit) und Bezeichnung (articleLabel) müssen zusammenpassen –
|
||||
// bei vorhandener Packungsgröße also „Packung" und NICHT die Basiseinheit, sonst steht
|
||||
// z.B. „1 Gramm" statt „1 Packung" (500 g) da.
|
||||
// Anzeigeeinheit eines Produkts: die im Formular gewählte Einheit (Gramm,
|
||||
// Milliliter, Stück) – NICHT die Packung. „1 Packung" ist nichtssagend, weil eine
|
||||
// Packung 500 g, 1 kg oder 25 ml sein kann; deshalb rechnen wir alles in die
|
||||
// echte Einheit um. dispFactor = Basiseinheiten je Anzeigeeinheit.
|
||||
const dispFactor = (p) => (p.unit_factor && p.unit_factor > 0 ? p.unit_factor : 1);
|
||||
const dispLabel = (p) => (p.unit_name || "Stück");
|
||||
// Artikeleinheit (Packung, sonst Anzeigeeinheit): nur noch nötig, um die je-Lagerort-
|
||||
// Mindestbestände umzurechnen, die in Artikeleinheiten gespeichert sind.
|
||||
const articleUnit = (p) => (p.package_size && p.package_size > 0 ? p.package_size : (p.unit_factor || 1));
|
||||
const articleLabel = (p) => (
|
||||
p.package_size && p.package_size > 0 ? (p.package_label || "Packung") : (p.unit_name || "Stück")
|
||||
);
|
||||
|
||||
/**
|
||||
* Zentrale Liste aller Mindestbestände: je Produkt/Gruppe der Gesamt-Wert und die
|
||||
@@ -53,15 +54,19 @@ export default function MinStock() {
|
||||
out.push({
|
||||
key: `p:${p.id}:global`, kind: "product", scope: "global", entity: p,
|
||||
name: p.name, catId: p.category_id, ort: "(Gesamt)",
|
||||
soll: p.min_stock_display, unit: p.min_stock_unit_label || articleLabel(p),
|
||||
bestand: p.stock / articleUnit(p), bestandUnit: articleLabel(p),
|
||||
// Alles in der Anzeigeeinheit (Gramm/Milliliter/Stück): min_stock ist in
|
||||
// Basiseinheiten gespeichert.
|
||||
soll: p.min_stock != null ? p.min_stock / dispFactor(p) : null,
|
||||
unit: dispLabel(p),
|
||||
bestand: p.stock / dispFactor(p), bestandUnit: dispLabel(p),
|
||||
});
|
||||
for (const l of (p.location_min_stocks || [])) {
|
||||
out.push({
|
||||
key: `p:${p.id}:${l.location_id}`, kind: "product", scope: "loc", entity: p,
|
||||
locId: l.location_id, name: p.name, catId: p.category_id,
|
||||
ort: locationPathById(l.location_id, locations) || "?",
|
||||
soll: l.min_stock, unit: articleLabel(p), bestand: null,
|
||||
// je-Lagerort ist in Artikeleinheiten gespeichert → in Anzeigeeinheit umrechnen.
|
||||
soll: (l.min_stock * articleUnit(p)) / dispFactor(p), unit: dispLabel(p), bestand: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -96,20 +101,17 @@ export default function MinStock() {
|
||||
try {
|
||||
if (row.kind === "product" && row.scope === "global") {
|
||||
const p = row.entity;
|
||||
// Faktor aus dem bestehenden Wert ableiten (erhält die erfasste Einheit);
|
||||
// ohne bestehenden Wert in Artikeleinheiten setzen.
|
||||
if (p.min_stock != null && p.min_stock_display) {
|
||||
const faktor = p.min_stock / p.min_stock_display;
|
||||
await api.updateProduct(p.id, { min_stock: num == null ? null : Math.round(num * faktor) });
|
||||
} else {
|
||||
// Eingabe in der Anzeigeeinheit → Basiseinheiten speichern.
|
||||
await api.updateProduct(p.id, {
|
||||
min_stock: num == null ? null : Math.round(num * articleUnit(p)),
|
||||
min_stock_in_packages: (p.package_size || 0) > 0,
|
||||
min_stock_unit_id: null,
|
||||
min_stock: num == null ? null : Math.round(num * dispFactor(p)),
|
||||
min_stock_in_packages: false,
|
||||
min_stock_unit_id: p.display_unit_id ?? null,
|
||||
});
|
||||
}
|
||||
} else if (row.kind === "product" && row.scope === "loc") {
|
||||
await api.setProductLocationMinStock(row.entity.id, mergeLoc(row.entity.location_min_stocks, row.locId, num));
|
||||
const p = row.entity;
|
||||
// Eingabe in der Anzeigeeinheit → Artikeleinheiten (so gespeichert).
|
||||
const artikel = num == null ? null : (num * dispFactor(p)) / articleUnit(p);
|
||||
await api.setProductLocationMinStock(p.id, mergeLoc(p.location_min_stocks, row.locId, artikel));
|
||||
} else if (row.kind === "group" && row.scope === "global") {
|
||||
await api.updateGroup(row.entity.id, { min_stock: num });
|
||||
} else if (row.kind === "group" && row.scope === "loc") {
|
||||
@@ -124,7 +126,7 @@ export default function MinStock() {
|
||||
? products.find((p) => String(p.id) === String(draft.targetId))
|
||||
: groups.find((g) => String(g.id) === String(draft.targetId));
|
||||
const draftUnit = draft.kind === "product"
|
||||
? (draftTarget ? articleLabel(draftTarget) : "")
|
||||
? (draftTarget ? dispLabel(draftTarget) : "")
|
||||
: (draftTarget ? (draftTarget.min_stock_unit_name || "Stück") : "");
|
||||
|
||||
function resetAdd() {
|
||||
@@ -143,15 +145,16 @@ export default function MinStock() {
|
||||
if (draft.kind === "product") {
|
||||
const p = draftTarget;
|
||||
if (draft.scope === "global") {
|
||||
// Menge in der Artikeleinheit erfasst → in Basiseinheiten speichern,
|
||||
// wie beim Inline-Editieren ohne bestehenden Wert.
|
||||
// Menge in der Anzeigeeinheit erfasst → in Basiseinheiten speichern.
|
||||
await api.updateProduct(p.id, {
|
||||
min_stock: Math.round(num * articleUnit(p)),
|
||||
min_stock_in_packages: (p.package_size || 0) > 0,
|
||||
min_stock_unit_id: null,
|
||||
min_stock: Math.round(num * dispFactor(p)),
|
||||
min_stock_in_packages: false,
|
||||
min_stock_unit_id: p.display_unit_id ?? null,
|
||||
});
|
||||
} else {
|
||||
await api.setProductLocationMinStock(p.id, mergeLoc(p.location_min_stocks, draft.locId, num));
|
||||
// Anzeigeeinheit → Artikeleinheiten (so gespeichert).
|
||||
const artikel = (num * dispFactor(p)) / articleUnit(p);
|
||||
await api.setProductLocationMinStock(p.id, mergeLoc(p.location_min_stocks, draft.locId, artikel));
|
||||
}
|
||||
} else {
|
||||
const g = draftTarget;
|
||||
|
||||
Reference in New Issue
Block a user