The Inventory Model

Inventory is where quantity and money meet. It is also the most common place for an ERP to be “wrong” in the eyes of the business.

The stock key

A stock balance is not just “material X, quantity 500”. The full key:

(material, plant, storage_location, batch, stock_type, special_stock_indicator, owner)

Every dimension matters:

Dimension Why
Material What it is
Plant Which site owns it
Storage location Where inside the site
Batch / lot Which production run — different expiry, different characteristics
Stock type Unrestricted / quality inspection / blocked / in transit
Special stock Consignment / subcontracting / customer-owned / project stock
Valuation type Split valuation (e.g. domestic vs imported, grade A vs B)

Stock types

Type Available to MRP? Available to sell? On balance sheet?
Unrestricted Yes Yes Yes
Quality inspection Usually yes No Yes
Blocked No No Yes
In transit Yes (planned) No Yes
Returns No No Yes
Consignment (vendor’s) Yes Only on consumption No
Consignment (at customer) No Already shipped Yes — still yours
Subcontractor stock Yes No Yes — still yours
Customer-owned material No No No

The rule that catches people out: physical possession ≠ ownership. Vendor consignment sits in your warehouse and is not yours. Customer consignment sits at the customer’s site and is yours. Subcontractor stock is at someone else’s factory and is yours. Get this wrong and your balance sheet is wrong.

Movement types

Every stock change has a movement type — a code that determines everything about the posting.

Code (SAP convention) Movement
101 / 102 Goods receipt for PO / reversal
122 Return delivery to vendor
201 / 202 Goods issue to cost centre / reversal
261 / 262 Goods issue to production order / reversal
301 Transfer plant to plant, one step
311 Transfer storage location to storage location
321 Quality inspection → unrestricted
343 Blocked → unrestricted
501 Receipt without PO
551 Scrapping
561 Initial stock upload
601 Goods issue for delivery (sales)
641 Goods issue for stock transport order
701/702 Physical inventory adjustment

The movement type controls:

  • Quantity sign (+/−)
  • Which stock type
  • Which GL accounts (via account determination)
  • Which fields are required (cost centre, order, reason code)
  • Whether it’s reversible and by which counter-movement

If you’re building an ERP, implement movement types. The alternative — bespoke logic per transaction — becomes unmaintainable within a year.

The material document

Every stock movement creates a material document, separate from the accounting document:

material_document_header(id, doc_number, doc_year, posting_date, document_date,
                         movement_reason, created_by, reference)
material_document_item(doc_id, line, material_id, plant_id, storage_location_id,
                       batch, stock_type, movement_type,
                       quantity, uom, amount_local,
                       cost_object, reference_doc, reference_line,
                       accounting_document_id)

Append-only. A wrong movement is corrected with a reversal movement, never edited.

Your stock balance is SUM(quantity) over these lines for a stock key — with the same “derived vs materialised” trade-off as GL balances. See General Ledger.

Stock quantities you must distinguish

On hand              physically present
+ On order           open POs not yet received
+ Planned receipts   planned/production orders
− Allocated/reserved committed to sales orders or production
− Safety stock       buffer you refuse to plan into
────────────────────────────────────────────────
= Available to promise (ATP)

Different questions need different numbers:

  • “Can I sell it?” → ATP
  • “Is it on the shelf?” → unrestricted on hand
  • “What’s it worth?” → valuated stock (includes QI and blocked, excludes vendor consignment)
  • “What should I reorder?” → on hand + on order − requirements

Never expose a single “stock” number in a UI without saying which one it is. Half of all “the system is wrong” tickets are actually this.

Reservations and allocation

A reservation earmarks stock:

reservation(id, material, plant, storage_location, quantity_required,
            quantity_withdrawn, requirement_date,
            source_type,     -- SALES_ORDER | PRODUCTION_ORDER | MAINTENANCE | MANUAL
            source_document, status)

Types:

  • Hard allocation — this exact stock/batch is for this order, nobody else can take it
  • Soft allocation — a claim on quantity, satisfied by any matching stock
  • Time-phased — the claim exists on a date, not now

Design decision: allocate at order entry (guarantees the customer, may sit on stock for weeks) or at picking (maximises flexibility, risks disappointing the customer). Most systems allow both, configured by order type and customer priority.

Physical inventory

Reality drifts from the system. Counting fixes it.

Method How
Annual/periodic count Everything, once a year, warehouse stopped. Disruptive
Cycle counting Continuous rolling count; A items monthly, B quarterly, C annually
Perpetual with sampling Statistical sampling, extrapolate
Zero-count / opportunity count Count a bin when it hits zero during picking. Cheap and effective

Process:

1. Create count documents (freeze the book quantity at that moment)
2. Block movements for the counted stock, or record book quantity at freeze time
3. Count (paper, RF scanner, mobile app)
4. Enter results
5. Recount differences over tolerance
6. Approve, then post the adjustment:
     Shortage: Inventory Cr, Inventory adjustment expense Dr
     Overage:  Inventory Dr, Inventory adjustment income   Cr

Inventory accuracy = items with zero variance / items counted. World-class is >99%. Below 95% means MRP is planning on fiction and every promise date is a guess.

Adjustment postings need reason codes — theft, damage, mis-pick, receiving error, data entry, expiry. The reason distribution tells you what to fix; a lump of “adjustment” tells you nothing.

Inventory analysis

ABC classification

By annual consumption value:

  • A — ~20% of items, ~80% of value → tight control, frequent counts, low safety stock
  • B — ~30% of items, ~15% → moderate
  • C — ~50% of items, ~5% → loose control, bulk ordering

XYZ classification

By demand variability:

  • X — steady, predictable → easy to forecast
  • Y — variable with trend/season
  • Z — erratic → don’t forecast, buffer or make to order

Combined ABC-XYZ gives nine strategies. AX items get tight JIT; CZ items get a big buffer and no planner attention.

Key metrics

Metric Formula Meaning
Inventory turns COGS / average inventory How many times you cycle stock a year
DOH / DSI 365 / turns Days of inventory
Fill rate Lines shipped complete / lines ordered Service level
Stockout rate Stockout events / opportunities Failure rate
Obsolete/slow-moving % No movement in N months Dead capital
Inventory accuracy Count matches / counts Data quality
Carrying cost 15–30% of value/year Capital, storage, insurance, obsolescence, shrinkage

Slow-moving and obsolete (SLOB)

Inventory that isn’t turning is a write-down waiting to happen. Standard policy:

No movement 6–12 months  → provision 25%
No movement 12–24 months → provision 50%
No movement > 24 months  → provision 100%
Expired / superseded     → write off

IAS 2 requires inventory at the lower of cost and net realisable value. The provision calculation is a standard report you will be asked to build; the ageing must be based on last movement date (or last issue date), not creation date.

Design rules

  1. Movement types, not bespoke logic per transaction.
  2. Material documents are append-only. Reverse, never edit.
  3. Balances derived from movements, with an optional materialised projection that is reconciled nightly.
  4. Ownership is a separate concept from location. Model special stock explicitly.
  5. Quantity is meaningless without UoM — see Item Master and UoM.
  6. Negative stock should be blocked by default. Allowing it is a deliberate, per-material, per-plant configuration decision, and it always causes valuation problems.
  7. Every adjustment needs a reason code.
  8. Reconcile inventory subledger to the GL inventory accounts every period.

Next