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:
Scarriffle
2026-07-27 12:15:25 +02:00
parent 6e48cd0a7a
commit d518b4aa23
23 changed files with 507 additions and 220 deletions

View File

@@ -237,7 +237,7 @@ export default function CheckIn() {
best_before:
(precision === "month" ? fromMonthInput(l.best_before) : l.best_before) || null,
best_before_precision: precision,
location_id: locationId === "" ? null : Number(locationId),
location_id: locationId === "" ? null : locationId,
}));
if (payloadLines.length === 0) {
setError("Bitte mindestens eine Menge angeben.");

View File

@@ -26,7 +26,7 @@ export default function LocationResolve() {
<div>
<div className="page-head">
<div>
<h1>Lagerort {name || `#${id}`}</h1>
<h1>Lagerort {name || id}</h1>
<div className="sub">
{error || "Diesen QR-Code in der App scannen (Ort zuordnen), um Einzelstücke hier einzuordnen."}
</div>

View File

@@ -30,7 +30,7 @@ export default function Locations() {
e.preventDefault();
setError(null);
try {
await api.createLocation({ name, parent_id: parentId === "" ? null : Number(parentId) });
await api.createLocation({ name, parent_id: parentId === "" ? null : parentId });
setName("");
// Übergeordneten Ort absichtlich stehen lassen beim Anlegen vieler Orte
// unter demselben Elternteil spart das jedes Mal die Neuauswahl.
@@ -56,7 +56,7 @@ export default function Locations() {
try {
await api.updateLocation(editId, {
name: editName.trim(),
parent_id: editParent == null ? null : Number(editParent),
parent_id: editParent == null ? null : editParent,
});
setEditId(null);
load();
@@ -141,7 +141,7 @@ export default function Locations() {
<label className="grow">
Übergeordneter Lagerort (optional)
<CategorySelect
value={parentId === "" ? null : Number(parentId)}
value={parentId === "" ? null : parentId}
nodes={ordered}
rootLabel=" keiner (oberste Ebene) "
onChange={(id) => setParentId(id == null ? "" : String(id))}