Bestandssynchronisation
Wie Flowkom BestandsĂ€nderungen zu Shopify und Amazon pusht â und wie der Sync gegen Silent-Failures abgesichert ist.
Diese Seite ist fĂŒr Admins und Power-User, die Sync-Drift analysieren oder Logs interpretieren wollen. FĂŒr regulĂ€re Nutzung ist sie nicht relevant.
Ăberblick
Flowkom ist die Source-of-Truth fĂŒr BestĂ€nde. Drei Dinge Ă€ndern den verfĂŒgbaren Bestand:
- Physischer Stock-Change â Wareneingang, Versand, Umlagerung, manuelle Buchung
- Reservierung â Eine Bestellung im Status
offen,in Bearbeitungodergepicktreserviert ihre Positionen - Bundle-Cascade â Wenn ein Bundle-Bestand sich Ă€ndert, Ă€ndert sich auch der seiner Komponenten (und umgekehrt)
Jede dieser Ănderungen muss zu allen verbundenen Plattformen propagiert werden â sonst ĂŒberverkauft Shopify oder Amazon Bestand, der eigentlich anderswo reserviert ist.
Architektur
Reservierungs-Modell
Eine Bestellposition zĂ€hlt als reserviert, solange ihr ĂŒbergeordneter Auftrag in einem dieser Status ist:
| Status | Reserviert? | Bedeutung |
|---|---|---|
open | â | Auftrag importiert, noch nicht in Bearbeitung |
in_progress | â | In Pickliste eingeplant |
picked | â | Gepickt, wartet auf Versand |
shipped | â | Versendet â Bestand wurde abgebucht |
completed | â | Abgeschlossen |
cancelled | â | Storniert â Bestand ist wieder frei |
Beim Push zu Shopify rechnet Flowkom: available = physischer_stock â reserviert. Amazon erhĂ€lt den gleichen Wert pro FBM-Listing.
Was triggert einen Sync?
Es gibt zwei parallele Mechanismen, die das Produkt in die Sync-Queue schreiben:
1. DB-Trigger (primÀr)
Direkt in der PostgreSQL-Transaktion. Kann nicht silent failen â wenn der Trigger fehlschlĂ€gt, schlĂ€gt auch der Order-Insert/-Update fehl.
| Trigger | Wann | Was wird enqueued |
|---|---|---|
trg_inventory_queue_on_line_item | INSERT/DELETE/UPDATE OF (product_id, quantity) auf order_line_items | betroffenes Produkt, sofern Order in Reservierungs-Status |
trg_inventory_queue_on_order_status | UPDATE OF status auf orders, Ăbergang in/aus Reservierungs-Set | alle Line-Items der Order |
trg_inventory_queue_on_order_delete | BEFORE DELETE auf orders mit Reservierungs-Status | alle Line-Items vor CASCADE |
Schreibt source = 'reservation' in inventory_sync_queue.
Trigger gibt es nur fĂŒr die Shopify-Queue. Die Amazon-Queue (amazon_inventory_dirty_queue) wird vom App-Layer befĂŒllt, weil sie pro Eintrag ĂŒber amazon_listings, bundle_items und amazon_fba_inventory filtern muss â zu komplex fĂŒr reinen SQL-Trigger.
2. App-Layer-Hooks (Defense-in-Depth)
In allen Order-Lifecycle-Routen wird zusĂ€tzlich ein Helper aufgerufen, der beide Queues fĂŒllt: Shopify (ĂŒber markProductsDirty) und Amazon (ĂŒber enqueueAmazonDirtyBatch). Beide haben einen internen Retry mit 500 ms Backoff.
Wenn der DB-Trigger und der App-Hook beide feuern, fĂ€ngt das ON CONFLICT (workspace_id, product_id)-Constraint die doppelte Schreibung auf â idempotent.
Reconciliation: Safety-Sync
Selbst wenn beide oben genannten Mechanismen versagen, fÀngt ein Voll-Abgleich alle Drift ein:
- Shopify:
inventory-safety-synclÀuft pro Integration alle 60 Minuten und pusht alle gemappten Produkte komplett neu. Reservierungen werden frisch ausorder_line_itemsberechnet und abgezogen. - Amazon:
amazon-inventory-safety-sync(Status: separate Baustelle) macht Analoges.
Das Intervall ist pro Integration konfigurierbar via integrations.settings.safety_sync_interval_minutes.
Drift-Diagnose
Wenn Shopify einen falschen Bestand zeigt:
- Queue-Eintrag prĂŒfen â
select * from inventory_sync_queue where product_id = '...'. Wenn leer: Trigger und App-Hook haben nicht gegriffen. - Letzten Push prĂŒfen â
select * from integration_sync_logs where sync_type='inventory_push' order by created_at desc limit 5. - Reservierungen prĂŒfen â
select oli.product_id, oli.quantity, o.status from order_line_items oli join orders o on o.id=oli.order_id where oli.product_id='...' and o.status in ('open','in_progress','picked'). - Logs nach
[PROJ-265]-Marker filtern â alle Hook-Failures sind damit getaggt. - Backup-Trigger â manuell
select mark_product_dirty(workspace_id, product_id, 'manual')aufrufen, dann den Sync abwarten.
Quellen
- Spec:
features/PROJ-265-inventory-queue-db-triggers.md(DB-Trigger + HĂ€rtung) - Spec:
features/PROJ-235-inventory-sync-reliability.md(App-Hook-Verdrahtung) - Spec:
features/PROJ-55-bestandssync-wms-to-shop.md(Shopify-Sync-Engine) - Spec:
features/PROJ-64-amazon-fbm-bestandssync.md(Amazon-FBM-Sync-Engine)