Materials Inventory
Materials inventory is the running record of raw-material stock, kept as a ledger. Nothing overwrites a stock number; every movement is appended as an entry, and the current position is derived by summing those entries per material and location.
How the ledger works
Each entry records one movement: a material, a location, an event type, a
quantity, an optional unit cost, and a ref linking it back to whatever caused it. Entries
are never edited or deleted in normal operation; a movement that needs undoing is offset
by a reversing entry. This makes the ledger a complete, auditable history rather than a
single mutable balance.
Two timestamps matter: event date is the business moment the movement happened, date and time, so same-day movements keep their real order (you can set it), while created-at is when the row was written. Positions and ordering use the event date.
Event types
Each entry's event type is drawn from the shared inventory vocabulary, identical on both
ledgers. The single canonical list, with every forward event, its REVERSE_ counterpart,
and the SETTLE_ close forms, lives in the
modules overview.
A SETTLE_ entry trues an order up when it is closed. The first receipt moves an order to
Partial and Received is set by hand, so the booked commitment rarely matches exactly what
arrived. On reaching Received the system writes a settle entry for the gap between ordered
and received: SETTLE_ORDER on the on-order side, SETTLE_ALLOCATE on a job's allocated
inputs. The gap is signed, so the one entry trues the figure to zero whether the order came
up short (it clears the leftover) or over (it cancels the excess). It is written
automatically, never by hand, and is undone by deletion: revert an order back out of Received
and its settle entries are removed, restoring the open commitment.
Deriving the position
The summary is computed, not stored. Each figure is a signed sum over the entries, with
every REVERSE_ form backing out its event:
- On hand = RECEIVE + ADJUST - CONSUME - DISPOSE. A transfer out is a CONSUME, so it is already counted. Settle never touches on hand.
- On order = ORDER - RECEIVE - SETTLE_ORDER. Receiving draws on-order down as goods arrive; SETTLE_ORDER clears whatever is left when the order is closed short.
Inputs a work or production order reserves are released the same way finished goods track allocation (see finished goods): SETTLE_ALLOCATE backs out the part never consumed. Positions are grouped by material and location.
The API serves one complete position per material and location: on hand, on order, allocated, available, in stock (on hand net of allocation, never below zero), demand, wasted (the DISPOSE total), in-transit, and net position (in stock plus on order plus in-transit minus demand). The same shape is served for finished goods, so the two ledgers cannot drift.
A manual ADJUST corrects a count in either direction: a positive quantity raises on-hand, a negative one lowers it (for example, fixing a count that was entered too high). A DISPOSE is the write-off path for damage, loss, or expiry; it carries waste semantics and stays a positive reduction.
Lots and expirations
An arrival carries the lot and expiration entered on its receipt line; every later movement of that stock derives them from there. When one movement spans several lots (a consumption drawn from two deliveries, say) the ledger view splits it into one line per lot, each with its own expiration and unit cost, even though only one movement is stored. How that works, and why, is covered in Lots & Expirations.
Where the entries come from
| Source | Events |
|---|---|
| Purchase orders (materials) | ORDER, RECEIVE, SETTLE_ORDER |
| Work orders (inputs) | DEMAND, ALLOCATE, CONSUME, SETTLE_ALLOCATE |
| Production orders (inputs) | DEMAND, ALLOCATE, CONSUME, SETTLE_ALLOCATE |
| Transfers | CONSUME, RECEIVE |
| Manual operations | ADJUST, DISPOSE |
See also
Read summaries and post manual events through the REST API or the MCP server.