Skip to content

PRD: Inventory Ledger

ModuleInventoryPRD IDPRD-LDG-001
StatusNo itemFEATLDG
EpicPlane
Date2026-07-13Versionv1.0
Packages@nx/inventoryURDLDG
SurfaceBackendClient · Owner/Mgr
OwnerPhát Nguyễn

What the inventory ledger is

A merchant can hold goods in several inventory locations, and each item at each location carries a stock number. The stock table only says how much is left today.

The inventory ledger is the book that says why that number came out that way. Every time stock goes up or down, the system appends one entry: how much was there before, how much moved, how much is left, why, and under which document. The ledger is append-only - an entry is never deleted and never overwritten.

The four stock numbers

Quoted from Stock Locations & Levels so nobody has to open another PRD. Each item at each location carries four numbers:

NumberWhat the system calls itMeaning
On-handon-handThe goods physically in the warehouse
ReservedreservedAlready promised to another document, no longer sellable to anyone else
AvailableavailableThe part that can still be sold
IncomingincomingAlready left the source location, not yet arrived at the destination

The invariant, true at every moment:

Available = On-hand - Reserved

The ledger records every single time those numbers move.

Why a stock table is not enough

The stock table cannot answer the question that always comes up when the numbers do not add up: there were 20 yesterday, why are there 12 now, who took 8. With nowhere to answer that, every discrepancy turns into an argument between the cashier, the stock keeper and the owner, and the only way to settle it is to count everything again from scratch.

The ledger is also where the context of a movement gets pinned down. A merchant receives goods by the case but holds stock by the can; this month's inventory valuation differs from next month's. If an entry only recorded a bare quantity, nobody reading it a year later would know whether "5" meant 5 cases or 5 cans, or what that batch was worth.

One can of soda, from cart to ledger

Coke at the bar counter, on-hand 20. A customer buys 2 cans.

What happensThe entry writtenBeforeDeltaAfter
The cashier taps 2 cans into the orderCart reservation20020
The customer pays, the order completesSale deduction20-218
The system re-delivers the payment notificationno entry18018
Receive one more case (1 case = 24 cans)Purchase receipt18+2442
The merchant changes the case factor from 24 to 20no entry--42
  • Tapping an item into the cart does not move on-hand. What moves is reserved and available.
  • A payment notification delivered a second time does not deduct stock a second time. The same document and the same stock item can only write one entry.
  • The receipt entry snapshots the unit case and the factor 24 at the moment it happened. Changing the factor later does not rewrite the old entry: reopen it and it still reads 1 case = 24 cans.

The easiest thing to get wrong

Dedupe must not rely on counting the entries that already exist

Reading "is there already an entry for this document" before writing is a very fragile way to dedupe: delete one entry and the door reopens for a second deduction.

The dedupe key is the triple source document + reason + stock item, enforced at the database layer. Deleting or editing an entry does not reopen the door for a second deduction.

The consequence: a wrong entry is fixed by appending a correction entry, never by editing the old one. Whoever reads the ledger sees both the error and the fix, which means today's stock figure can always be explained.

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.