Skip to content

PRD: Inventory Valuation

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

What inventory valuation is

Cost is what one unit of an item sitting in a location is worth. On a sale, the selling price minus the cost is the gross margin.

Every item of a merchant has exactly one cost, shared across all inventory locations of that merchant. Several merchants sit under one organizer, and each merchant keeps its own cost. Moving stock from the central warehouse to the sales floor shifts quantity only; the money stays put.

The four numbers in stock

Lifted from Stock locations & levels so there is no need to open another PRD. Every item at every location carries four numbers:

NumberWhat the system calls itMeaning
On-handon-handGoods physically sitting in the location
ReservedreservedAlready promised to another document, no longer sellable to anyone else
AvailableavailableThe part still sellable
IncomingincomingLeft the source location, not yet arrived at the destination

The invariant, true at every moment:

Available = On-hand - Reserved

The denominator of the weighted moving average is the merchant's total on-hand, accumulated across every location.

Why a hand-typed box does not solve this

A merchant buys the same item in batches at different prices: a carton of milk was VND 22,000 last month and VND 24,000 this month. If the system does not roll those batches into one number, the owner does the arithmetic on paper, and every profit report is wrong from the ground up.

A single box for the owner to type a cost into does not solve it either. A hand-typed number sits still even when goods arrive at a completely different price, so the longer it is used the further it drifts from what was actually paid, and the margin computed at the point of sale drifts with it.

So the system keeps two numbers side by side: the weighted moving average the system computes itself, and the standard cost the owner types in. The owner picks which one each item uses.

One item, end to end

Fresh milk. The location is empty. Two receipts at two prices, sell it all, then receive again.

What happensOn-handStock valueAverage cost
Receive 100 cartons at VND 20,000100VND 2,000,000VND 20,000
Sell 40 cartons60VND 1,200,000VND 20,000
Receive 40 cartons at VND 25,000100VND 2,200,000VND 22,000
Sell the last 100 cartons, on-hand back to 00VND 0VND 22,000 (frozen)
Receive 50 cartons at VND 24,00050VND 1,200,000VND 24,000 (replaced outright)
  • Selling does not change the cost. Cost only changes at receipt: (1,200,000 + 40 × 25,000) divided by 100 is VND 22,000.
  • On-hand reaching 0 freezes the old cost at VND 22,000. The system does not divide by zero and does not return a cost of 0.
  • The next receipt replaces the old cost outright with the unit price of the new lot, because there is no old stock left to blend into.
  • If this item is running a standard cost of VND 21,000, the gross margin on a sale is computed at VND 21,000, while the average-cost column still ticks along exactly as in the table above.

The easiest thing to get wrong

Per-location costing is one-way and cannot be turned off

A merchant whose purchasing is spread across locations can turn on an advanced setting so that each item-and-location pair carries its own cost.

Turning it on splits one number into many. Merging them back has no correct rule: averaging by quantity, or picking one location as the reference, is wrong for some merchant. So the system does not allow turning it off. The form says so plainly before the switch.

By default the cost is a single number for the whole merchant, and that is the right choice for nearly every merchant.

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