Skip to content

Inbound and Inventory

theGreenGuy edited this page Jun 8, 2026 · 5 revisions

Inbound & Inventory

Real-time stock is a projection of the append-only transaction log. Nothing writes stock.qty directly — movements are events, and the inventory service applies them.

The two working vertical slices

Goods-in → stock

POST /api/txlog/events {GoodsReceived}  ─►  outbox relay  ─►  txlog.stream (Kafka)  ─►  inventory projection  ─►  stock

Line transactions (all order types)

POST /api/orders/{id}/lines/{lineNo}/transactions
   ─► order-management appends GoodsReceived / Picked / StockAdjusted to txlog (via its outbox)
   ─► relay ─► txlog.stream ─► inventory projection moves stock.qty

INBOUND = receipts (+), OUTBOUND = picks (−), COUNT / ADJUSTMENT = signed adjustments. The actor is recorded on every transaction (authenticated when security is on).

txlog — system of record

  • POST /api/txlog/events writes the immutable event and an outbox row in one transaction; a scheduled relay publishes to txlog.stream in global position order.
  • GET /api/txlog/events?afterPosition= is the global replay feed used to (re)build read models — and to stream confirmations back to the host (see Host Integration).
  • UPDATE/DELETE on the event table are blocked by a trigger.

inventory — durable projection

  • Consumes txlog.stream; movement events (GoodsReceived, PutawayCompleted/StockMoved, Picked, StockAdjusted, StockStatusChanged) move stock.qty (per warehouse × SKU × batch × location × HU × status) and advance a projection cursor.
  • Idempotent: every applied event is recorded in a processed_event inbox keyed on eventId, so redelivery/replay is a no-op and the read model can be rebuilt from the log.
  • Serves SKU-wide and location-scoped availability/reservations (ATP) used by allocation.
  • Per-location occupancy (POST /api/inventory/locations/occupied, body { "locationIds": [...] }{ "occupiedLocationIds": [...] }): the subset of the given locations that physically hold any stock row or handling unit. Slotting put-away uses it to exclude occupied slots from its candidate set before scoring (see Slotting and Replenishment).
  • Batch/lot & serial instances are created at goods-in (ADR 0001).

Handling unit registry

Physical HU instances (barcode, type, location, status) are managed via /api/inventory/handling-units (CRUD). Type and location are set at registration and are not editable through the registry — the PUT /{id} endpoint preserves the existing huTypeId and locationId from the stored record regardless of what is sent in the request body. Changing an HU's type or moving it to a different location can only happen through a controlled process (e.g. a maintenance or QA work cycle). The registry UI enforces this by disabling the Type and Location dropdowns when editing an existing HU.

Stock Overview screen — Mark for counting

The Stock Overview screen lists current stock rows (SKU × location × HU × status). Each row has a Mark for counting button that creates an ad-hoc BLIND count task scoped to that location and SKU without leaving the screen:

  • Calls POST /api/counting/tasks with scopeType: LOCATION, countType: BLIND, tolerance: 1, and a single cells entry { locationId, skuId }.
  • While the request is in-flight the button shows "Adding…" and is disabled for that row.
  • On success a green notice confirms the task was created (e.g. Count task created for SKU-001 at A-01-01); on failure the error is shown in the existing red alert bar.
  • Rows where locationId or skuId is missing (e.g. unallocated stock) have the button disabled.

The created task appears in the stock-counting screen immediately and follows the normal capture → variance → reconcile → StockAdjusted lifecycle (see the counting service row in Services). For ASRS-family locations the task is created with routingStatus = PENDING and the background CountRoutingScheduler routes the tote to an active GTP STOCK_COUNT station within a minute, retrying on failure (see Goods-to-Person Stations).

Host-driven adjustments

A host can post a signed stock correction via POST /api/host/inventory/adjustments (Host Integration); it is appended to the txlog as a StockAdjusted event and applied by the projection like any other movement.

Related: Outbound Flow · Architecture.

Clone this wiki locally