Ein-/Auslagern nutzt die Artikeleinheit (Gebinde) statt fest "Packung"

- buildUnitOptions verwendet product.package_label als Beschriftung der
  Gebinde-Option (Wert bleibt intern "package").
- Beim Auswaehlen eines Artikels ist das Gebinde vorbelegt, wenn eine
  Packungsgroesse hinterlegt ist.
- Auslagern: Chargen-Dropdown und Hinweis zeigen die Menge in der Artikeleinheit
  (z.B. "MHD 2026-12-23 - 1 Glas") statt in der Basiseinheit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-22 13:46:14 +02:00
parent e67bdb32c4
commit 0bc141a1be
3 changed files with 16 additions and 5 deletions

View File

@@ -44,7 +44,8 @@ export default function CheckIn() {
setResults([]); setResults([]);
resetLookup(); resetLookup();
const opts = buildUnitOptions(p, units); const opts = buildUnitOptions(p, units);
setUnit(p.unit_name || (opts[0] && opts[0].value) || ""); // Gibt es ein Gebinde (Glas, Packung, …), ist das die naheliegende Eingabe.
setUnit(p.package_size ? "package" : (p.unit_name || (opts[0] && opts[0].value) || ""));
setLines([emptyLine()]); setLines([emptyLine()]);
setLocationId(""); setLocationId("");
} }

View File

@@ -29,7 +29,8 @@ export default function CheckOut() {
setLotId(""); setLotId("");
setQuantity(""); setQuantity("");
const opts = buildUnitOptions(p, units); const opts = buildUnitOptions(p, units);
setUnit(p.unit_name || (opts[0] && opts[0].value) || ""); // Gibt es ein Gebinde (Glas, Packung, …), ist das die naheliegende Eingabe.
setUnit(p.package_size ? "package" : (p.unit_name || (opts[0] && opts[0].value) || ""));
try { try {
setLots(await api.listLots(p.id)); setLots(await api.listLots(p.id));
} catch { setLots([]); } } catch { setLots([]); }
@@ -88,6 +89,14 @@ export default function CheckOut() {
const unitOpts = product ? buildUnitOptions(product, units) : []; const unitOpts = product ? buildUnitOptions(product, units) : [];
const selectedLot = lots.find((l) => String(l.id) === String(lotId)) || null; const selectedLot = lots.find((l) => String(l.id) === String(lotId)) || null;
const baseShort = product ? unitShort(product.base_unit) : ""; const baseShort = product ? unitShort(product.base_unit) : "";
const pkgSize = product?.package_size || 0;
const pkgLabel = product?.package_label || "Packung";
// Chargenmenge in der Artikeleinheit (Gebinde), sonst in der Produkteinheit.
function lotAmount(q) {
if (pkgSize > 0) return `${fmt(q / pkgSize)} ${pkgLabel}`;
return `${fmt(q / (product?.unit_factor || 1))} ${product?.unit_name || baseShort}`;
}
return ( return (
<div> <div>
@@ -150,7 +159,7 @@ export default function CheckOut() {
<option value="">Automatisch zuerst ablaufende zuerst (FEFO)</option> <option value="">Automatisch zuerst ablaufende zuerst (FEFO)</option>
{lots.map((l) => ( {lots.map((l) => (
<option key={l.id} value={l.id}> <option key={l.id} value={l.id}>
{l.best_before ? `MHD ${l.best_before}` : "ohne MHD"} · {fmt(l.quantity)} {baseShort} {l.best_before ? `MHD ${l.best_before}` : "ohne MHD"} · {lotAmount(l.quantity)}
{isExpired(l.best_before) ? " · abgelaufen" : ""} {isExpired(l.best_before) ? " · abgelaufen" : ""}
</option> </option>
))} ))}
@@ -160,7 +169,7 @@ export default function CheckOut() {
{selectedLot && ( {selectedLot && (
<div className={`alert ${isExpired(selectedLot.best_before) ? "error" : "info"}`}> <div className={`alert ${isExpired(selectedLot.best_before) ? "error" : "info"}`}>
<Icon name="alert" size={16} /> <Icon name="alert" size={16} />
Gewählte Charge: {fmt(selectedLot.quantity)} {baseShort} Gewählte Charge: {lotAmount(selectedLot.quantity)}
{selectedLot.best_before ? ` · MHD ${selectedLot.best_before}` : " · ohne MHD"} {selectedLot.best_before ? ` · MHD ${selectedLot.best_before}` : " · ohne MHD"}
{isExpired(selectedLot.best_before) ? " (abgelaufen)" : ""} {isExpired(selectedLot.best_before) ? " (abgelaufen)" : ""}
</div> </div>

View File

@@ -76,9 +76,10 @@ export function buildUnitOptions(product, units) {
.filter((u) => u.kind === product.kind) .filter((u) => u.kind === product.kind)
.map((u) => ({ value: u.name, label: u.name })); .map((u) => ({ value: u.name, label: u.name }));
if (product.package_size) { if (product.package_size) {
// Bezeichnung des Gebindes je Artikel (Glas, Tüte, …); Wert bleibt "package".
opts.push({ opts.push({
value: "package", value: "package",
label: `Packung (${fmt(product.package_size)} ${unitShort(product.base_unit)})`, label: `${product.package_label || "Packung"} (${fmt(product.package_size)} ${unitShort(product.base_unit)})`,
}); });
} }
return opts; return opts;