Lagerorte per 10-Zeichen-Code statt fortlaufender ID; iOS-Einlagern ohne Kamerazwang
Lagerort-IDs sind jetzt ein zufaelliger 10-Zeichen-Code (wie die Einzelstueck-UIDs) statt einer fortlaufenden Zahl - so kollidiert die Stammdaten-Sicherung zwischen zwei Instanzen praktisch nie mehr, und der Code ist zugleich der Inhalt des QR /l/<code>. Alle Fremdschluessel (lots, movements, items, Mindestbestaende, parent_id) ziehen mit; die Umstellung laeuft einmalig und transaktional beim Serverstart (_migrate_locations_to_code) und rollt bei Fehlern komplett zurueck. Vor dem Deploy ein DB-Backup machen. iOS-Einlagern oeffnet nicht mehr sofort die Kamera, sondern ein Formular mit Artikelsuche; die Kamera kommt erst per Button. Im Formular laesst sich der Lagerort zusaetzlich per /l/-QR scannen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,7 @@ export default function Einzelstuecke({ product, locations, shops, isAdmin, onCh
|
||||
const cents = centsFrom(addForm.price);
|
||||
const created = await api.createItems(product.id, {
|
||||
count: Number(addForm.count) || 1,
|
||||
location_id: addForm.location_id === "" ? null : Number(addForm.location_id),
|
||||
location_id: addForm.location_id === "" ? null : addForm.location_id,
|
||||
shop_id: shopId,
|
||||
acquired_on: addForm.acquired_on || null,
|
||||
warranty_until: addForm.warranty_until || null,
|
||||
@@ -269,7 +269,7 @@ export default function Einzelstuecke({ product, locations, shops, isAdmin, onCh
|
||||
<td data-label="Lagerort">
|
||||
{isAdmin ? (
|
||||
<select value={it.location_id ?? ""} style={{ marginTop: 0, minWidth: 120 }}
|
||||
onChange={(e) => patchItem(it, { location_id: e.target.value === "" ? null : Number(e.target.value) })}>
|
||||
onChange={(e) => patchItem(it, { location_id: e.target.value === "" ? null : e.target.value })}>
|
||||
<option value="">– ohne –</option>
|
||||
{locations.map((l) => <option key={l.id} value={l.id}>{l.name}</option>)}
|
||||
</select>
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function LocationMinStock({ locations, initial = [], unitLabel =
|
||||
try {
|
||||
const list = rows
|
||||
.filter((r) => r.location_id !== "" && Number(r.min_stock) > 0)
|
||||
.map((r) => ({ location_id: Number(r.location_id), min_stock: Number(r.min_stock) }));
|
||||
.map((r) => ({ location_id: r.location_id, min_stock: Number(r.min_stock) }));
|
||||
await onSave(list);
|
||||
setOk(true);
|
||||
} catch (err) {
|
||||
|
||||
@@ -56,7 +56,7 @@ export default function ObjektBestand({ product, lots, locations, isAdmin, onCha
|
||||
product_id: product.id,
|
||||
quantity: menge,
|
||||
unit: einheit,
|
||||
location_id: addForm.location_id === "" ? null : Number(addForm.location_id),
|
||||
location_id: addForm.location_id === "" ? null : addForm.location_id,
|
||||
});
|
||||
setAddForm({ location_id: addForm.location_id, quantity: "" });
|
||||
await nachAktion();
|
||||
@@ -93,8 +93,8 @@ export default function ObjektBestand({ product, lots, locations, isAdmin, onCha
|
||||
await api.relocateStock({
|
||||
product_id: product.id,
|
||||
quantity: menge,
|
||||
from_location_id: move.from === "" ? null : Number(move.from),
|
||||
to_location_id: move.to === "" ? null : Number(move.to),
|
||||
from_location_id: move.from === "" ? null : move.from,
|
||||
to_location_id: move.to === "" ? null : move.to,
|
||||
});
|
||||
setMove(null);
|
||||
toast("Umgelagert.");
|
||||
@@ -110,7 +110,7 @@ export default function ObjektBestand({ product, lots, locations, isAdmin, onCha
|
||||
await api.removeStock({
|
||||
product_id: product.id,
|
||||
quantity: menge,
|
||||
location_id: remove.location_id === "" ? null : Number(remove.location_id),
|
||||
location_id: remove.location_id === "" ? null : remove.location_id,
|
||||
reason: remove.reason,
|
||||
note: remove.note || null,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user