Gegenstands-Verwaltung (Non-Food) neben Lebensmitteln

Die Kategorie bestimmt die Verwaltungsart (food/object). Gegenstaende:
Menge je Lagerort statt Chargen/MHD, Umlagern (ohne Grund) und Entfernen
mit Pflicht-Grund samt Entnahme-Statistik. Beliebig viele eigene Felder
je Kategorie (vererbt an Unterkategorien), "gekauft bei" ueber eine
verwaltbare Shop-Liste und ein Produktlink. Barcode-Lookup zusaetzlich
ueber Open Products Facts.

Der Lebensmittel-Teil (Chargen/MHD/FEFO) bleibt unveraendert. Umgesetzt in
Backend (FastAPI, +Tests gruen), Web (React) und iOS (SwiftUI).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-25 15:33:56 +02:00
parent 580afcc133
commit 5b952524d7
29 changed files with 3116 additions and 115 deletions

View File

@@ -152,6 +152,10 @@ export const api = {
checkIn: (body) => request("/stock/checkin", { method: "POST", body }),
checkInBatch: (body) => request("/stock/checkin/batch", { method: "POST", body }),
checkOut: (body) => request("/stock/checkout", { method: "POST", body }),
// Gegenstände: umlagern (ohne Grund) und entfernen (Grund Pflicht)
relocateStock: (body) => request("/stock/relocate", { method: "POST", body }),
removeStock: (body) => request("/stock/remove", { method: "POST", body }),
productRemovals: (id) => request(`/products/${id}/removals`),
listLots: (productId) =>
request(`/lots${productId ? `?product_id=${productId}` : ""}`),
updateLot: (id, body) => request(`/lots/${id}`, { method: "PATCH", body }),
@@ -187,11 +191,27 @@ export const api = {
createLocation: (body) => request("/locations", { method: "POST", body }),
deleteLocation: (id) => request(`/locations/${id}`, { method: "DELETE" }),
// Kategorien: reine Ordnungshilfe, verschachtelbar (siehe Gruppen fuer Bestaende)
// Kategorien: Ordnungshilfe + Verwaltungsart (food/object), verschachtelbar
listCategories: () => request("/categories"),
createCategory: (body) => request("/categories", { method: "POST", body }),
updateCategory: (id, body) => request(`/categories/${id}`, { method: "PATCH", body }),
deleteCategory: (id) => request(`/categories/${id}`, { method: "DELETE" }),
// Effektive (vererbte) Felder einer Kategorie für das Artikelformular.
categoryFields: (id) => request(`/categories/${id}/fields`),
// Selbst definierte Felder je Kategorie
listFieldDefinitions: (categoryId) =>
request(`/field-definitions${categoryId != null ? `?category_id=${categoryId}` : ""}`),
createFieldDefinition: (body) => request("/field-definitions", { method: "POST", body }),
updateFieldDefinition: (id, body) =>
request(`/field-definitions/${id}`, { method: "PATCH", body }),
deleteFieldDefinition: (id) => request(`/field-definitions/${id}`, { method: "DELETE" }),
// Shops / Bezugsquellen (nur für Gegenstände)
listShops: () => request("/shops"),
createShop: (body) => request("/shops", { method: "POST", body }),
updateShop: (id, body) => request(`/shops/${id}`, { method: "PATCH", body }),
deleteShop: (id) => request(`/shops/${id}`, { method: "DELETE" }),
// Gebinde (Einzahl/Mehrzahl): "Glas" -> "Gläser"
listPackageTypes: () => request("/package-types"),