Inventory Item Module
Status: Built — inventory-pool implementation. Operations wires the Inventory Pool service and API, which Demand uses for its production arc. The discrete inventory-item custody rules below are the design target; Inventory Pools — Data Model describes the implemented shape.
What the runtime actually holds — tables, DTOs, cross-module references and API surface as they exist today — is Inventory Pools — Data Model. Where this page describes design ahead of the build, that page is the one that says what is stored.
Purpose
Section titled “Purpose”An inventory item is a discrete, homogeneous, located, owned quantity of goods — a specific chunk of physical stock — classified by a catalog Item. The catalog item describes what a thing is; an inventory item is some actual stock of it, sitting in a place, in a condition, at a quantity. This module makes the rules of holding, moving, splitting, consuming, and counting that stock precise.
The central distinction is identity versus state: an inventory item’s identity is permanent, while everything about its current condition is state that changes only through explicit, recorded operations.
Context
Section titled “Context”Inventory Items is the system’s custody layer: three modules build on it, and it builds on one. Clients sit to the left of the servers they depend on; every arrow is a dependency the client calls, and together they form a DAG.
What this module consumes:
- Item — every inventory item and every pool is classified by exactly one catalog Item, and the catalog item’s units-of-measure scheme is what gives inventory items their exact quantity arithmetic (conversions to a common base; min/max, “full”, and zero checks).
What its clients consume from it:
- Receiving — births inventory here: at a receiving line’s freeze, the accepted goods are born as inventory items grouped in a new pool, located at the dock, and the line holds custody of that pool until it releases it.
- Demand — a demand item accumulates produced materials in its holding pool (adding and removing members as material is produced and distributed).
- Kanban Cards — a loaded card carries inventory items across part of its lap, through a pool bound to its cycle. Built and not yet in the running system (R03): a card carries no inventory-pool reference today (see the Kanban data model).
- Any caller — the as-of counts: total, degraded, and usable quantities of an item at a location, computed from the live inventory items at the moment of the question.
A structural rule rides these relationships: a pool has exactly one custodian at a time — a receiving line, a demand item’s holding, or a card’s cycle, never two at once. Each client acquires custody through its own commitment and releases it explicitly.
Functional decomposition
Section titled “Functional decomposition”The module has two services. They depend one way — pools on inventory items, never the reverse — and each provides its own endpoints.
- InventoryItem service — owns the inventory items: their identity, their recorded condition, and every custody operation in the Operations table. It provides two endpoints: the Inventory Items API (create an inventory item, operate on it, read its state as of any moment) and the Counts API (the computed as-of counts described in Inventory pools and counts — a read-only surface with no operations of its own).
- InventoryPool service — owns pool membership: creating a pool and adding or removing member inventory items, through the Pools API. It depends on the InventoryItem service — membership references inventory items, and the one-item-per-pool guard reads each candidate member’s catalog item — while inventory items know nothing about pools.
Main entities
Section titled “Main entities”- Identity (permanent). Which catalog item it is stock of, its license plate (its handling-unit identity, like a pallet’s label), an optional serial number, and a reorder threshold. None of these change for the life of the inventory item.
- State (changes only through operations). Its fill (Sealed = asserted as-intended, Open = in use, Empty = nothing left), its quantity (and any degraded, unavailable portion), its location, its lot provenance, an optional expiration, and whether it is locked (held / quarantined). The system can answer what the state was at any moment in the past.
- Inventory pool. A set of inventory items of a single catalog item — the way the system refers to “all the stock of this item.” A pool tracks which inventory items belong to it (add and remove); it does not store a count of its own. See Inventory pools and counts for how counts over a pool are computed.
Lifecycle
Section titled “Lifecycle”Inventory item
Section titled “Inventory item”An inventory item’s job is to answer, precisely, “what condition is this stock in right now” — and to answer it for any moment in the past, too. That means tracking three independent things at once: whether it is sealed, being worked, or empty; whether it is fully usable, partly usable, or not usable at all; and whether it is administratively available or on hold. Each of the three moves on its own schedule, driven by different operations, so the diagram below shows them as three parallel tracks inside the inventory item’s active life, rather than one flat list of states.
An inventory item is born the moment it is created, with a positive quantity, working (not sealed), fully usable, and available. It stays alive — even at zero quantity — until someone explicitly deletes or writes it off; running out is never, by itself, the end of an inventory item’s life.
Inventory pool
Section titled “Inventory pool”A pool deliberately has no state machine — there is no status a pool moves through, and none should be read into it. Its life is told by two other things:
- Membership evolution. A pool’s only recorded state is which inventory items it holds right now. Each add or remove is an explicit, recorded act — refused with a precise reason when it would break the rules (an inventory item of the wrong catalog item, a duplicate add, a removal of something not held) — and the membership is queryable as of any moment in the past, just like an inventory item’s condition. An empty pool is not a dead pool: membership can grow and shrink for as long as the pool is in use.
- The custody arc. A pool is born at its custodian’s own commitment — a receiving line’s freeze, a demand item starting to accumulate produced materials, a card’s cycle starting to process — and is held by exactly one custodian at a time for as long as that work lives. When the custodian releases it (the line distributes, the run completes, the cycle closes), custody ends and is never re-acquired: the pool and its history persist as a record, but no new work picks up an old pool.
The custody arc belongs to the clients (see Context) — the pool itself neither knows nor stores who holds it; custody is read off the holders’ own records.
Operations
Section titled “Operations”| Action | What it does | Notes |
|---|---|---|
| Create | Mints a new inventory item (with a license plate). | Born Open. |
| Replenish / consume | Adds or removes quantity. | Over-consuming is refused; consuming to zero leaves an empty, revivable inventory item. |
| Adjust quantity | Sets the counted quantity to an observed value. | |
| Move | Relocates the inventory item. | Refused while locked. |
| Split / merge | Divides one inventory item into two, or combines two into one. | Quantity is conserved. |
| Repack | Re-expresses the same goods in a different unit of measure. | Does not change the real quantity. |
| Inspect | Marks a degraded (unusable) portion. | The single driver of condition. |
| Seal / unseal | Asserts, or releases, the as-intended condition. | |
| Lock / unlock | Places or releases an administrative hold. | |
| Delete / write off | Retires the inventory item. | Terminal. |
Guarantees
Section titled “Guarantees”- Identity is permanent and separate from state. The catalog item it is stock of, its license plate, and its serial number never change.
- License plates are never reused — once retired, a handling-unit identity does not come back.
- Depleting is not retiring. Consuming an inventory item to zero leaves it empty but alive, ready to receive new stock; only a delete or write-off retires it, and retirement is final.
- Split and merge conserve quantity — nothing is created or lost when an inventory item is divided or combined.
- Over-consuming is refused, specifically. Trying to remove more than is on hand is rejected with a precise reason, not silently clamped.
- Every state is well-formed, and the full history is queryable — you can ask what any inventory item’s quantity, location, or condition was as of any moment.
Inventory pools and counts
Section titled “Inventory pools and counts”An inventory pool is a set of inventory items of a single catalog item — the way the system talks about “all the stock of this item, here.” Counts are computed, never stored: the total, degraded, and usable quantities of an item at a location are derived from the live inventory items as of the moment you ask, so a count is always a true reading rather than a figure that can drift.
Notifications
Section titled “Notifications”Inventory Items is the one module outside the notification channel the rest of the system uses — see how modules stay in sync. It has no notification wiring: Demand calls it directly, as an injected service (see the data model).
What this module announces
- Status: not designed. No inventory-item action triggers a notification to other modules today; every change happens because a caller explicitly asked for it, never as a reaction to something the caller did elsewhere.
What this module listens for
- Status: not designed. Inventory Items does not react to any other module’s activity — every operation, including the pool’s add and remove, is invoked directly by a caller.
Scenarios
Section titled “Scenarios”Four moments show how an inventory item and its pool behave end to end. The caller in these diagrams is whoever is driving the workflow — an operator, a shop-floor screen, or an orchestrating service.
Stock is created, moved, run all the way down to nothing, and then brought back to life with fresh stock — the same inventory item throughout.
A seal is the operator’s assertion that an inventory item is exactly as it should be. It can be asserted and released any number of times, but any real change to the quantity breaks it automatically.
When part of an inventory item turns out to be damaged, an inspection marks the amount, and splitting isolates it into its own inventory item — leaving the rest fully usable again.
A pool only ever groups inventory items of one catalog item; anything else is refused outright.
These scenarios are verified against the formal model.
How it relates to its neighbors
Section titled “How it relates to its neighbors”- Item — every inventory item is classified by exactly one catalog item.
- Kanban Cards — a loaded card carries inventory items across part of its lap.
- Demand — a demand item accumulates produced materials in its holding pool.
Linear
Section titled “Linear”- Initiative: Product / Resources / Inventory Items
Copyright: © Arda Systems 2025-2026, All rights reserved