- Documentation
- /
- Inventory
- /
- 03 — Integration
03 — Integration
Inventory is a member of the R9 Work & Supply network (message protocol v1). Its
contract is written in schema/inventory.integration.dsl (authoring spec:
docs/implementation/integration_authoring_spec.md) and turned into code by
python -m codegen.cli integration inventory --network work_supply; the business logic
for each message is hand-written in integration/handlers.py.
The whole network — every message with its publisher, subscribers and implementation
status, generated from the contracts — is in networks/work_supply/NETWORK_MAP.md
(python -m codegen.cli network-docs work_supply).
What it owns
| Network entity | Model | Business reference |
|---|---|---|
inventory.stock_location |
StockLocation | location_code |
inventory.reservation |
InventoryReservation | reservation_number (RES-…) |
inventory.goods_receipt |
GoodsReceipt | receipt_number (GR-…) |
inventory.goods_receipt_line |
GoodsReceiptLine | — |
Messages
| Kind | Message | When / what | Status |
|---|---|---|---|
| publishes | inventory.item_reserved |
a reservation becomes (or is created) reserved | ✅ automatic |
| publishes | inventory.item_unavailable |
a reservation becomes (or is created) unavailable | ✅ automatic |
| publishes | inventory.item_issued |
reserved stock was issued to its work order: quantity, the stock's average cost and the value | ✅ automatic |
| publishes | inventory.goods_arrived / receipt_accepted / receipt_quarantined / receipt_rejected |
receiving | ✅ automatic |
| consumes | work.material_requirement_created |
reserve stock for the requirement (all or nothing) | ✅ |
| consumes | work.material_requirement_changed |
a cancelled requirement releases its reservation | ✅ |
| consumes | purchasing.shipment_dispatched / delivery_commitment_changed |
expected inbound stock | ⏳ R10 |
| accepts | inventory.reserve_for_work |
same as the consumed event, by command (from Work or the orchestrator) | ✅ |
| accepts | inventory.issue_to_work |
issue the reserved stock to its work order: on hand and reserved fall, the issue is costed at the item's average cost (a moving average of the purchase price of accepted stock; a receipt line takes its purchase order line's price) | ✅ |
| accepts | inventory.release_reservation |
release unissued stock (rejects already_issued) | ✅ |
| accepts | inventory.record_goods_arrival, inspect_receipt, reverse_receipt_acceptance |
⏳ R10 (answers handler not found) | |
| answers | inventory.availability |
on hand / reserved / available per item, candidate locations | ✅ |
| answers | inventory.reservation_status |
one reservation | ✅ |
| answers | inventory.receipt_status |
⏳ R10 |
Events are written in the same transaction as the stock change and delivered afterwards; inbound messages are de-duplicated by message id and commands by idempotency key, so nothing is reserved twice even when a message is delivered twice.
References to other applications
| Points at | Owner | Fields |
|---|---|---|
work.work_order |
work_management | work_order_cid / work_order_ref — linked ↗ |
work.material_requirement |
work_management | material_requirement_cid / material_requirement_ref — linked ↗ |
catalogue.item |
catalogue (R10) | catalogue_item_cid / catalogue_item_ref |
purchasing.purchase_order / purchase_order_line / shipment |
purchasing (R10) | purchase_order_cid / purchase_order_ref … |
supplier.supplier |
supplier (R10) | supplier_cid / supplier_ref |
asset.component |
asset register | physical_component_cid / physical_component_ref |
Endpoints
| Endpoint | For | Protection |
|---|---|---|
PUT /integration/messages/<id> |
the orchestrator delivering messages | service token |
GET /resolve/<cid> |
people following a ↗ link from another app | normal login |
Settings (applications.yaml env:)
INTEGRATION_PUBLISHER=1, ORCHESTRATOR_URL=http://localhost:5089 (the R9 orchestrator);
ORCHESTRATOR_SERVICE_TOKEN from .env. The publisher starts on the app's first request.