Skip to content

PRD: Stock, items & movement tracking

ModuleInventory (CORE-06)PRD IDPRD-STK-001
StatusShippedOwnerInventory squad
Date2026-05-28Versionv1.0
Packages@nx/inventory · @nx/core · apps/clientURDSTK · ITM · TRK

TL;DR

Gives a merchant a single, editable view of what they actually hold - on-hand, reserved, and available per item per location, with decimal precision - backed by an aggregate stock-list endpoint and an immutable movement audit trail. Low-stock thresholds and an attention signal surface items that need restocking, so an owner can see and correct stock at a glance instead of inferring it from the movement layer.

1. Context & Problem

Inventory already auto-creates an item per product variant (ITM) and logs every movement immutably (TRK), but a merchant has no consolidated, editable surface for what they actually hold. Stock figures live close to the movement layer, and the oversell flag sits on the item rather than on the stock record - so a clean "how much is on-hand / reserved / available per location" view, and a list endpoint to power it, are missing.

Without that surface a merchant cannot answer the most basic inventory question at a glance, cannot spot items running low, and cannot correct a count without reasoning about raw movement entries. This PRD closes that gap on top of the existing item and tracking primitives, giving the owner a first-class stock-management screen.

2. Goals & Non-Goals

Goals

  • Surface on-hand / reserved / available per item per location with decimal precision (STK).
  • First movement auto-creates the stock record; the oversell flag moves from item → stock record.
  • An aggregate inventory-items list endpoint with stock rollup, plus an overview endpoint.
  • Carry low-stock thresholds (min/max) through the list and flag items needing attention.
  • A client stock screen: list, full-field edit panel, per-location editing, confirm-on-save, attention highlight.
  • Keep the immutable movement audit trail (TRK) as the source of truth behind every stock change.

Non-Goals

  • Negative-stock enforcement at POS - negative available is tolerated (URD-CON-003).
  • Multi-currency stock valuation.
  • A dedicated historical stock-level browsing UI - history is recorded via TRK; URD-STK-007 remains a Could.
  • Inventory tickets and purchase-order receipt flows (TKT, PO) - separate increments.

3. Success Metrics

MetricTarget / signal
Stock visibilityOwner can read on-hand / reserved / available per item per location from one screen
Audit integrityZero stock rows without a matching immutable movement record
Available accuracyavailable = on-hand − reserved holds across the list at decimal precision
Attention signalItems below their low-stock threshold are flagged and highlighted in the list

4. Personas & Use Cases

PersonaGoal in this feature
OwnerSee true stock per location, spot low stock, correct counts
Inventory staffEdit stock fields and per-location quantities with a confirm step
CashierRead product availability at the point of sale

Core scenarios: open the stock screen → see on-hand/reserved/available per item per location with low-stock items highlighted → edit a stock record (full fields, per-location) → confirm on save → the edit writes a movement record and the available figure recomputes.

5. User Stories

  • As an owner, I want to see on-hand, reserved, and available per item per location on one screen, so I always know what I hold and where.
  • As an owner, I want items below their threshold flagged and highlighted, so I can restock before I run out.
  • As inventory staff, I want to edit a stock record's full fields per location, so I can correct counts accurately.
  • As inventory staff, I want a confirm-on-save step on stock edits, so I don't commit a mistaken count.
  • As an owner, I want every stock change backed by an immutable movement record, so the figure is always auditable.

6. Functional Requirements

#RequirementURD ref
FR-1One stock record per (item, location, lot, serial); available = on-hand − reservedURD-STK-001..002
FR-2All quantities stored at decimal precision (4 places)URD-STK-003
FR-3First movement auto-creates the stock record; owner can view current levelsURD-STK-004
FR-4Last-stocked / last-counted timestamps update automaticallyURD-STK-005
FR-5Stock updates are atomic - partial failure rolls back fullyURD-STK-006
FR-6Oversell flag lives on the inventory-stock record (moved from the item)URD-STK-001..004
FR-7Aggregate inventory-items list endpoint with stock rollup, plus an overview endpointURD-STK-004 · URD-ITM-001..006
FR-8Low-stock thresholds (min/max, min ≤ max) carried through the list and flag attentionURD-ITM-003
FR-9Items are auto-created per variant, linked to the merchant's default locationURD-ITM-001..006
FR-10Every stock change writes an immutable tracking entry (before/change/after, reference, idempotent)URD-TRK-001..007

Full requirement text and acceptance criteria live in the Inventory URD. This PRD references them rather than restating them.

7. Non-Functional Requirements

AreaRequirement
Data integrityA stock change and its movement record are written together - no stock row without a matching immutable audit entry
ImmutabilityMovement records are append-only; corrections happen via new entries, never edits
Tenancy & authzAll operations scoped per merchant (x-merchant-id); gated by inventory permissions
PrecisionQuantity math uses float(value, 4)
ConsistencyStock updates are atomic; partial failure rolls back fully
PerformanceAggregate list reads stock rollup + thresholds in one call, not N per-item lookups
i18nUser-facing labels/statuses are bilingual ({ en, vi })

8. UX & Flows

Key screens (in apps/client): the stock list and items table, the full-field stock edit panel with per-location editing, the confirm-on-save dialog, and the attention/highlight indicators for low stock.

9. Data & Domain

EntityRole
InventoryStockThe quantity record - on-hand, reserved, available per (item, location, lot, serial); carries the oversell flag
InventoryItemThe stock-tracked record per variant, linked to the default location; carries min/max thresholds
InventoryTrackingImmutable movement entry (before/change/after, reference type/ID, tracking type) behind every change

Conceptual only - full schema and invariants in the inventory domain model.

10. Dependencies & Assumptions

Depends on

  • Inventory items (URD-ITM) - stock attaches to an auto-created item per variant.
  • Movement audit trail (URD-TRK) - every stock change writes an immutable entry.
  • Inventory locations (URD-LOC) - stock is held per location; a merchant default must exist.
  • @nx/core - item model and schema (thresholds, oversell flag location).

Assumptions

  • Each merchant has a default inventory location and at least one product variant (hence an item).
  • The movement (TRK) layer is already in place as the audit source of truth.

11. Risks & Open Questions

Risk / questionMitigation / status
Stock edit and movement record could diverge on partial failureUpdates are atomic; no stock row without a matching movement entry
Negative available toleratedDocumented business constraint (URD-CON-003), not a bug; POS enforcement out of scope
Default low-stock threshold valueResolved - sensible default applied; threshold input validated min ≤ max
No dedicated stock-history viewerHistory recorded via TRK; URD-STK-007 remains a Could, dedicated UI deferred

12. Release Plan & Launch Criteria

AspectPlan
PhaseP1 (foundation) - STK, ITM, TRK in the URD feature catalog
RolloutAll merchants; no feature flag
MigrationOversell flag relocated item → stock record; thresholds added on the item model
Launch criteriaList shows on-hand/reserved/available per location; edit writes a movement record; available = on-hand − reserved holds; low-stock flagged
MonitoringStock-vs-movement consistency checks, low-stock counts per merchant, stock-edit error rate

13. FAQ

Where does the oversell flag live now? On the inventory-stock record, not the item - so oversell is decided per stock row, alongside the quantities it governs.

What makes an item show as "needs attention"? Available falling below the item's low-stock threshold (min) flags it and highlights the row in the list.

Can I browse historical stock levels? Not via a dedicated viewer in this increment - every change is recorded immutably via TRK; a history UI (URD-STK-007) is a Could, deferred.

Is negative available a bug? No - negative available is a documented, tolerated business constraint (URD-CON-003); POS-level negative-stock enforcement is out of scope.

Does editing stock skip the audit trail? No - every stock change, including a manual edit, writes an immutable movement record.

References

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