User Manual
Help Center/User Manual/OMS ↔ WMS: inventory source, push, ship-back, and tracking sync

OMS ↔ WMS: inventory source, push, ship-back, and tracking sync

Last updated 2026-10-13

How the two apps talk: inventory source resolution, idempotent push-to-WMS, WMS ship callbacks, and channel tracking sync.

In wms_sync mode, OMS and WMS form a closed loop: OMS reads WMS inventory, pushes orders down as outbound shipments, WMS executes picking/packing/shipping, then ships callbacks flow back up to OMS. This article maps each link.

Inventory source resolution#

  • oms_inventory_source_configs holds the tenant default (warehouse_id NULL) plus per-warehouse overrides; resolveInventorySource picks the effective mode per order.
  • In wms_sync mode the OMS inventory ledger is frozen read-only — ATP checks read WMS qty_available instead.

Push down: order → WMS outbound shipment#

  • push-to-wms converts lines one by one into wms_order_lines. Because item_id is already the wms_items id, no SKU mapping is needed.
  • The outbound shipment is created in commit status, which locks inventory via lockInventoryForCommit. On success the OMS order moves to released.
  • One OMS order can split into several shipments (split_index / split_total); the detail page lists all of them, keeping the first for backward compatibility.

Ship-back: WMS → OMS#

  • When WMS ships an outbound shipment, the ship hook accumulates fulfilled_qty on the matching OMS lines and fills in line-level tracking/carrier (split shipments accumulate across multiple ships).
  • The order-level status is derived from all lines: all shipped → fulfilled, otherwise partial_fulfilled; order-level tracking/carrier/shipped_at are filled in (existing values are not overwritten).
  • Each ship also writes a shipped event into oms_wms_status_events with the tracking number and shipped lines, feeding the WMS timeline and channel sync.

Tracking sync back to sales channels#

  • On ship, OMS fires a fire-and-forget tracking sync to the sales channel (e.g. Shopify fulfillments; split shipments map to line items via channel_line_item_id). A failed sync never blocks the ship response.
  • Sync status lands on tracking_sync_status (synced / failed / skipped) with append-only logs; retry-tracking-sync retries the latest failure, optionally for one split.
  • Only the shipped event triggers a sync; delivered does not.
Line status on the order detail page is derived, not stored: fulfilled_qty = 0 → pending; partial → partial; fulfilled_qty ≥ ordered_qty → fulfilled.