Web: Mindestbestand nur fuer Charge-Artikel (Lebensmittel + Verbrauchsgegenstand)
Menge je Lagerort und Einzelstuecke haben keinen Mindestbestand mehr: die "Mindestbestand (Stueck)"-Felder und der je-Lagerort-Block fallen im Formular weg (Gruppe fuer Menge bleibt), Alt-Werte werden beim Speichern geleert. Die Mindestbestaende-Seite und der "+ hinzufuegen"-Dialog zeigen nur noch Charge-Artikel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,9 @@ import { fmt } from "../units";
|
|||||||
// echte Einheit um. dispFactor = Basiseinheiten je Anzeigeeinheit.
|
// echte Einheit um. dispFactor = Basiseinheiten je Anzeigeeinheit.
|
||||||
const dispFactor = (p) => (p.unit_factor && p.unit_factor > 0 ? p.unit_factor : 1);
|
const dispFactor = (p) => (p.unit_factor && p.unit_factor > 0 ? p.unit_factor : 1);
|
||||||
const dispLabel = (p) => (p.unit_name || "Stück");
|
const dispLabel = (p) => (p.unit_name || "Stück");
|
||||||
|
// Mindestbestand gibt es nur bei Charge-Artikeln: Lebensmittel und
|
||||||
|
// Verbrauchsgegenstände (bulk). „Menge je Lagerort" und Einzelstücke nicht.
|
||||||
|
const canHaveMin = (p) => p.tracking !== "object" || p.bulk === true;
|
||||||
// Artikeleinheit (Packung, sonst Anzeigeeinheit): nur noch nötig, um die je-Lagerort-
|
// Artikeleinheit (Packung, sonst Anzeigeeinheit): nur noch nötig, um die je-Lagerort-
|
||||||
// Mindestbestände umzurechnen, die in Artikeleinheiten gespeichert sind.
|
// 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 articleUnit = (p) => (p.package_size && p.package_size > 0 ? p.package_size : (p.unit_factor || 1));
|
||||||
@@ -50,7 +53,7 @@ export default function MinStock() {
|
|||||||
|
|
||||||
const rows = useMemo(() => {
|
const rows = useMemo(() => {
|
||||||
const out = [];
|
const out = [];
|
||||||
for (const p of products) {
|
for (const p of products.filter(canHaveMin)) {
|
||||||
out.push({
|
out.push({
|
||||||
key: `p:${p.id}:global`, kind: "product", scope: "global", entity: p,
|
key: `p:${p.id}:global`, kind: "product", scope: "global", entity: p,
|
||||||
name: p.name, catId: p.category_id, ort: "(Gesamt)",
|
name: p.name, catId: p.category_id, ort: "(Gesamt)",
|
||||||
@@ -235,7 +238,7 @@ export default function MinStock() {
|
|||||||
<select value={draft.targetId} onChange={(e) => setDraft({ ...draft, targetId: e.target.value })}>
|
<select value={draft.targetId} onChange={(e) => setDraft({ ...draft, targetId: e.target.value })}>
|
||||||
<option value="">– wählen –</option>
|
<option value="">– wählen –</option>
|
||||||
{(draft.kind === "product"
|
{(draft.kind === "product"
|
||||||
? [...products].sort((a, b) => a.name.localeCompare(b.name, "de"))
|
? products.filter(canHaveMin).sort((a, b) => a.name.localeCompare(b.name, "de"))
|
||||||
: [...groups].sort((a, b) => a.name.localeCompare(b.name, "de"))
|
: [...groups].sort((a, b) => a.name.localeCompare(b.name, "de"))
|
||||||
).map((t) => (
|
).map((t) => (
|
||||||
<option key={t.id} value={t.id}>
|
<option key={t.id} value={t.id}>
|
||||||
|
|||||||
@@ -477,16 +477,19 @@ export default function ProductForm() {
|
|||||||
...(isObject ? { field_values: fieldPayload } : {}),
|
...(isObject ? { field_values: fieldPayload } : {}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Gegenstand ohne Charge: Menge je Lagerort oder Einzelstücke. Mindestbestand
|
// Gegenstand ohne Charge: Menge je Lagerort oder Einzelstücke. Diese haben
|
||||||
// in Stück (kein Einheit-Dropdown), gleiche Umrechnung liefert die Stückzahl.
|
// KEINEN Mindestbestand (den gibt es nur bei Lebensmitteln/Verbrauchs-
|
||||||
// Menge-Gegenstände dürfen (wie Verbrauchsgegenstände) in eine Gruppe.
|
// gegenständen) – etwaige Alt-Werte werden beim Speichern geleert. Gruppen
|
||||||
|
// sind weiter erlaubt (Menge je Lagerort).
|
||||||
return {
|
return {
|
||||||
...base,
|
...base,
|
||||||
individual: form.individual,
|
individual: form.individual,
|
||||||
bulk: false,
|
bulk: false,
|
||||||
group_id: form.group_id === "" ? null : Number(form.group_id),
|
group_id: form.group_id === "" ? null : Number(form.group_id),
|
||||||
field_values: fieldPayload,
|
field_values: fieldPayload,
|
||||||
...minStock,
|
min_stock: null,
|
||||||
|
min_stock_unit_id: null,
|
||||||
|
min_stock_in_packages: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,15 +858,10 @@ export default function ProductForm() {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{objMode !== "bulk" && (
|
{/* Menge je Lagerort darf gruppiert werden – aber ohne Mindestbestand
|
||||||
<div className="row">
|
(den gibt es nur bei Lebensmitteln/Verbrauchsgegenständen). */}
|
||||||
<label className="grow" style={{ maxWidth: 300 }}>
|
|
||||||
Mindestbestand (Stück)
|
|
||||||
<input type="number" step="any" min="0" value={form.min_stock}
|
|
||||||
onChange={(e) => set("min_stock", e.target.value)} disabled={readOnly}
|
|
||||||
placeholder="z.B. 3" />
|
|
||||||
</label>
|
|
||||||
{objMode === "count" && (
|
{objMode === "count" && (
|
||||||
|
<div className="row">
|
||||||
<label className="grow" style={{ maxWidth: 300 }}>
|
<label className="grow" style={{ maxWidth: 300 }}>
|
||||||
<span className="tip" title="Zählt Bestände mehrerer Gegenstände zusammen (in Stück).">
|
<span className="tip" title="Zählt Bestände mehrerer Gegenstände zusammen (in Stück).">
|
||||||
Gruppe
|
Gruppe
|
||||||
@@ -874,29 +872,6 @@ export default function ProductForm() {
|
|||||||
{groups.map((g) => <option key={g.id} value={g.id}>{g.name}</option>)}
|
{groups.map((g) => <option key={g.id} value={g.id}>{g.name}</option>)}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{objMode !== "bulk" && !isNew && product && isAdmin && (
|
|
||||||
<div style={{ marginTop: "var(--sp-2)", marginBottom: "var(--sp-4)" }}>
|
|
||||||
<div className="card-head" style={{ marginBottom: "var(--sp-1)" }}>
|
|
||||||
<Icon name="location" size={16} />
|
|
||||||
<h3 style={{ margin: 0 }}>Mindestbestand je Lagerort</h3>
|
|
||||||
</div>
|
|
||||||
<p className="muted small mt-0">
|
|
||||||
Bedarf je Lagerort (z.B. Ferienhaus, Zuhause), zusätzlich zum Gesamt-Mindestbestand. Menge in Stück.
|
|
||||||
</p>
|
|
||||||
<LocationMinStock
|
|
||||||
locations={locations}
|
|
||||||
initial={product.location_min_stocks || []}
|
|
||||||
unitLabel="Stück"
|
|
||||||
onError={(m) => toast(m, "warn")}
|
|
||||||
onSave={async (list) => {
|
|
||||||
const updated = await api.setProductLocationMinStock(product.id, list);
|
|
||||||
setProduct(updated);
|
|
||||||
toast("Bedarfe je Lagerort gespeichert.");
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{form.category_id !== "" && (
|
{form.category_id !== "" && (
|
||||||
|
|||||||
Reference in New Issue
Block a user