Das Bestandsmodell
Alles in der Lagerhälfte von Stockly ruht auf einer Zeilenform. Ist sie einmal verstanden, hören die Endpunkte auf, wie eine willkürliche Liste auszusehen.
Eine Menge, ein Ort
Abschnitt betitelt „Eine Menge, ein Ort“Eine Menge lebt in p2lab_stockly_warehouse_stock, mit dem Schlüssel Lager + Lagerplatz + Produkt:
| Feld | Bedeutung |
|---|---|
warehouseId | welcher Standort sie hält |
binLocationId | welcher Lagerplatz innerhalb dieses Standorts |
productId | welcher Artikel |
stock | wie viele körperlich da sind |
reserved | wie viele davon eine Bestellung bereits beansprucht hat |
So etwas wie Bestand ohne Lagerplatz gibt es nicht. Ware, die „nirgendwo” abgelegt wird, landet auf dem
unassigned-Lagerplatz des Lagers, einer echten Zeile mit echter Id, beim ersten Gebrauch angelegt. Jeder
API-Aufruf, der binLocationId: null entgegennimmt, löst das auf diesen Lagerplatz auf, bevor er irgendetwas
tut, und deshalb entnimmt eine Entnahme aus „keinem Lagerplatz” genau der Stelle, an die ein null-Zugang sie
gelegt hat.
reserved ist ein Zwischenspeicher. Die Wahrheitsquelle dessen, was eine Bestellung beansprucht hat, ist
p2lab_stockly_reservation_line, eine Zeile je Bestellposition und Lagerplatz. reserved zu schreiben, ohne die
Zeilen zu schreiben, bringt die beiden aus dem Gleichschritt, und die Integritätsprüfung hat genau dafür einen
Befund.
Lagerplatzrollen
Abschnitt betitelt „Lagerplatzrollen“Ein Lagerplatz ohne Rolle ist ein gewöhnlicher Lagerplatz, die einzige Art, auf die die Einlagerung zielt. Die fünf Rollen unten sind Puffer, höchstens einer je Art und Lager:
| Rolle | Hält | Zählt als verfügbar |
|---|---|---|
receiving | Ware aus einem Wareneingang zu einer Bestellung, vor der geführten Einlagerung | ja — sie ist im Gebäude |
quarantine | unter Qualitätskontrolle angenommene Ware, die auf die Prüfung wartet | nein |
transit | für eine ausgehende Umlagerung zusammengeführte Ware | nein |
returns | Ware zurück vom Kunden, die auf eine Entscheidung wartet | nein |
unassigned | Buchbestand, der nie körperlich platziert wurde | ja |
Einer davon ist für gewöhnliche Aufrufer verschlossen. Der transit-Lagerplatz füllt sich, wenn eine
Umlagerung versendet wird, und leert sich, wenn sie ankommt oder storniert wird; ein add, remove oder move,
das ihn als eines der beiden Enden benennt, wird abgelehnt, denn eine von Hand dort abgelegte Einheit ließe die
Umlagerung stranden, die die Ware für ihre hält.
returns ist mit Absicht nicht derselbe Pool wie quarantine, und der Unterschied zählt für eine Integration:
Ware in returns ist nicht verkäuflich. Ein Listener, der eine angenommene Retoure als „Bestand ist zurück”
behandelt, wird überverkaufen; die Verfügbarkeit ändert sich erst, wenn jemand die Einheiten zurück in die
Lagerung entscheidet.
Was woraus abgeleitet wird
Abschnitt betitelt „Was woraus abgeleitet wird“product.stock = SUM(stock - reserved) über jeden Lagerplatz, dessen Rolle als verfügbar zähltproduct.stock ist eine Ausgabe. Stockly berechnet sie nach jedem Vorgang neu und überschreibt, was es dort
vorfindet. Sie von außen zu schreiben ist kein Integrationsweg; es ist der Fehlerfall, den der
Wächter für externe Änderungen abfangen soll.
Das Journal arbeitet andersherum: p2lab_stockly_warehouse_stock_movement ist append-only. Nichts bearbeitet
eine Bewegungszeile; eine Korrektur ist eine neue Zeile mit eigenem Typ. Das ist es, was die Historie
beantwortbar macht: Die Frage, warum ein Lagerplatz vier hält, hat eine Antwort aus Zeilen, nicht aus dem
aktuellen Wert.
Eine Bewegung trägt beide Enden und beide Stände:
| Gruppe | Felder |
|---|---|
| Was | type, quantity, productId, batchId, lotId, batchNumber, expiresAt |
| Von | sourceWarehouseId, sourceBinLocationId, sourceBinLpCode |
| Nach | targetWarehouseId, targetBinLocationId, targetBinLpCode |
| Vorher / nachher | sourceStockBefore, sourceStockAfter, sourceReservedBefore, sourceReservedAfter, targetStockBefore, targetStockAfter |
| Warum | comment, event, reasonCode, meta, userId, userName |
| Welcher Beleg | orderId, orderLineItemId, purchaseOrderId, purchaseOrderItemId, transferId, operationId, importId |
Die Richtung steckt in den Enden, nie im Vorzeichen: Ein Zugang hat keine Quelle, ein Abgang kein Ziel, eine
Umlagerung beides. quantity ist immer positiv.
Chargen, Lots, Platzierungen und Ladungsträger
Abschnitt betitelt „Chargen, Lots, Platzierungen und Ladungsträger“Vier Namen, die ähnlich klingen und verschiedene Fragen beantworten:
| Entität | Beantwortet |
|---|---|
p2lab_stockly_warehouse_stock_batch | wie viel von der Menge dieses Lagerplatzes welche Lotnummer und welches Ablaufdatum trägt — die operative Wahrheit, gegen die die Entnahme zieht |
p2lab_stockly_stock_lot | die Identität eines Lots im ganzen Netz |
p2lab_stockly_stock_lot_placement | wo dieses Lot derzeit sitzt und auf welchem Ladungsträger |
p2lab_stockly_handling_unit | ein Ladungsträger: eine Palette oder ein Karton, auf dem Ware reist und der in einem anderen verschachtelt sein kann |
Chargen entscheiden, was eine Entnahme verbraucht. Lots und Platzierungen sind ein daneben gepflegtes Spiegelbild, und das ist es, was ein Lot mit einer Abfrage über Lagerplätze und Lager hinweg verfolgen lässt. Ein Vorgang schreibt beides; von einem Aufrufer verlangt es niemand.
Die Entitäten, auf denen dieses Modell beruht
Abschnitt betitelt „Die Entitäten, auf denen dieses Modell beruht“| Entität | Hält |
|---|---|
p2lab_stockly_warehouse | einen Standort: seinen Code, seine Richtlinien |
p2lab_stockly_warehouse_bin_location | einen Lagerplatz: Code, Koordinaten, Kapazität, Rolle |
p2lab_stockly_warehouse_stock | die Mengenzeile von oben |
p2lab_stockly_warehouse_stock_batch | die Lot-Aufteilung einer solchen Zeile |
p2lab_stockly_warehouse_stock_movement | das Journal |
p2lab_stockly_handling_unit | Ladungsträger |
p2lab_stockly_stock_lot / …_stock_lot_placement | Lot-Identität und wo es sitzt |
p2lab_stockly_reservation_line | was eine Bestellung beansprucht hat, je Lagerplatz |
p2lab_stockly_order_allocation | was einer Bestellung geschuldet wird und woher es bezogen wird |
p2lab_stockly_external_stock_incident | fremde Schreibvorgänge auf product.stock, die der Wächter abgefangen hat |
Es sind gewöhnliche Shopware-Entitäten, /api/search/p2lab-stockly-warehouse-stock und Verwandte funktionieren
also genau wie überall sonst.
- Bestand in einen Lagerplatz legen — die vier Schreib-Endpunkte
- Bestand lesen — die Abfragen, die es bereits gibt
- Bewegungsverlauf — dasselbe Journal, wie der Mitarbeiter es sieht