URD: Inventory
| Module | CORE-06 | Version | v0.4 |
|---|---|---|---|
| Status | In-progress | Date | 2026-05-30 |
1. Purpose
Define user-facing requirements for Inventory management — stock tracking, warehouse locations, purchase orders, vendors, materials (BOM), inventory tickets, and a complete, immutable audit trail of every stock movement. The outcome is that a merchant always knows what they have, where it is, and how it got there.
2. Scope
| Included | Excluded |
|---|---|
| Inventory locations (warehouses) with hierarchy | Sale quotation / quota-based reservation |
| Inventory items (variant/material linked to location) | Multi-level BOM / sub-assemblies |
| Stock quantities (on-hand, reserved, available) | Recipe yield and scrap percentage |
| Immutable tracking audit log | Multi-currency stock valuation |
| Tracking type catalog (19 pre-seeded) | Full barcode scanning integration |
| Vendor (supplier) management | Negative-stock enforcement at POS |
| Purchase orders with goods receipt | Technical API specifications |
| Inventory tickets (transfer, adjustment, count, return, scrap) | |
| Material catalog with identifiers | |
| Material recipes (BOM) with versioning | |
| BOM runtime explosion on kitchen ticket | |
| Production orders, inventory rules, unit of measure |
3. Definitions
| Term | Definition |
|---|---|
| Inventory Location | A warehouse or storage area within a merchant. Supports hierarchy. One default per merchant. |
| Inventory Item | A record linking a product variant or material to a merchant for stock tracking. |
| Inventory Stock | The quantity record — on-hand, reserved, available. One per (item, location, lot, serial). |
| Inventory Tracking | An immutable audit entry for every stock movement with before/after quantities. |
| Inventory Tracking Type | Categorizes movement direction (IN/OUT/NEUTRAL) and reason. 19 pre-seeded + 1 custom. |
| Inventory Ticket | A document for stock operations: transfer, adjustment, cycle count, returns, scrap. Has line items. |
| Vendor | A supplier from whom the merchant purchases goods. |
| Purchase Order | A goods-receipt document from a vendor, containing line items with quantities and pricing. |
| Material | A raw ingredient or semi-finished good tracked separately from sellable products. |
| Material Recipe (BOM) | A versioned recipe declaring which materials are consumed to produce a product variant. |
| BOM Explosion | Automatic material decrement triggered by kitchen ticket item status changes. |
| Production Order | A manufacturing document tracking planned/actual/scrap quantities for produced goods. |
| Inventory Rule | A configurable threshold rule that can trigger alerts, PO creation, or webhooks. |
| Unit of Measure | Measurement unit with 3-level scope: system defaults → merchant → product/material. |
4. Conceptual Model
Conceptual only — the full schema lives in the developer domain model.
5. Functional Requirements
One table per functional area.
<AREA>codes match the test-case IDs. Priority = MoSCoW (Must / Should / Could / Won't).
5.1 Inventory Location (LOC)
| ID | P | Requirement |
|---|---|---|
| URD-LOC-001 | M | Owner can create an inventory location with an i18n name. |
| URD-LOC-002 | M | A default location is auto-created for each merchant on commerce init. |
| URD-LOC-003 | M | Exactly one default location exists per merchant; setting a new default clears the previous. |
| URD-LOC-004 | S | Locations support parent-child hierarchy. |
| URD-LOC-005 | S | A location can store address and geographic (GPS) data. |
| URD-LOC-006 | M | Location lifecycle: NEW → ACTIVATED → DEACTIVATED → ARCHIVED (ARCHIVED terminal). |
| URD-LOC-007 | M | Each location has a system-generated identifier (LOC_YYYYMMDD_id), not user-editable. |
| URD-LOC-008 | M | Locations use soft-delete; data is preserved and admin-retrievable. |
| URD-LOC-009 | S | Owner can list and filter locations by status. |
| URD-LOC-010 | M | Locations are isolated per merchant. |
5.2 Inventory Item (ITM)
| ID | P | Requirement |
|---|---|---|
| URD-ITM-001 | M | An inventory item is auto-created when a product variant is created. |
| URD-ITM-002 | M | One item per (variant, location, unit) combination. |
| URD-ITM-003 | S | Item supports min/max stock-level thresholds; min ≤ max. |
| URD-ITM-004 | M | Each item has a system-generated identifier (SKU_YYYYMMDD_id), not user-editable. |
| URD-ITM-005 | M | Item lifecycle: ACTIVATED → DEACTIVATED → ARCHIVED (ARCHIVED terminal). |
| URD-ITM-006 | M | Item is linked to the merchant's default location on creation. |
5.3 Inventory Stock (STK)
| ID | P | Requirement |
|---|---|---|
| URD-STK-001 | M | One stock record per (item, location, lot, serial). |
| URD-STK-002 | M | Available = on-hand − reserved. |
| URD-STK-003 | M | All quantities stored with decimal precision (4 places). |
| URD-STK-004 | M | Owner can view current stock levels; first movement auto-creates the stock record. |
| URD-STK-005 | S | Last-stocked / last-counted timestamps update automatically. |
| URD-STK-006 | M | Stock updates are atomic — partial failure rolls back fully. |
| URD-STK-007 | C | Historical stock-level changes are viewable. |
5.4 Inventory Tracking (TRK)
| ID | P | Requirement |
|---|---|---|
| URD-TRK-001 | M | Every stock movement creates an immutable tracking entry. |
| URD-TRK-002 | M | Records before, change, and after quantities. |
| URD-TRK-003 | M | Entries from business documents store reference type and ID. |
| URD-TRK-004 | M | Idempotent: same (referenceType, referenceId) produces one entry only. |
| URD-TRK-005 | M | Each entry typed by tracking type (IN/OUT/NEUTRAL); 19 pre-seeded + custom. |
| URD-TRK-006 | S | Entries record the acting user (createdBy / modifiedBy). |
| URD-TRK-007 | M | Owner can view full tracking history. |
| URD-TRK-008 | S | Entries can record effective price and multiplier. |
| URD-TRK-009 | S | Manual entries can include a note/reason. |
| URD-TRK-010 | C | Filter history by date, type, or reference document. |
5.5 Inventory Ticket (TKT)
| ID | P | Requirement |
|---|---|---|
| URD-TKT-001 | M | Tickets support 6 operation types: Transfer, Adjustment, Cycle Count, Return to Vendor, Return from Customer, Scrap/Disposal. |
| URD-TKT-002 | M | Lifecycle: DRAFT → SUBMITTED → APPROVED → IN_PROGRESS → COMPLETED / CANCELLED. |
| URD-TKT-003 | M | Each ticket has line items with planned vs. actual quantities. |
| URD-TKT-004 | M | Completing a ticket creates tracking entries and updates stock. |
| URD-TKT-005 | S | Line items support lot/serial numbers. |
| URD-TKT-006 | S | Line items support per-item location override. |
5.6 Vendor (VEN)
| ID | P | Requirement |
|---|---|---|
| URD-VEN-001 | M | Owner can create vendors within a merchant. |
| URD-VEN-002 | M | Vendor has name, contact info (emails, phones), address, and a system identifier (VEN_YYYYMMDD_id). |
| URD-VEN-003 | S | Vendor can store a tax registration number. |
| URD-VEN-004 | M | Vendor uses soft-delete; historical PO references are preserved. |
| URD-VEN-005 | M | Vendors are isolated per merchant. |
5.7 Purchase Order (PO)
| ID | P | Requirement |
|---|---|---|
| URD-PO-001 | M | Owner can create a PO selecting vendor + items in one operation; vendor required. |
| URD-PO-002 | M | Lifecycle: DRAFT → PROCESSING → RECEIVED → COMPLETED → CLOSED (with valid transitions only). |
| URD-PO-003 | M | Owner can cancel a PO from any non-terminal status; received stock is not auto-reversed. |
| URD-PO-004 | M | Owner can revert PROCESSING → DRAFT. |
| URD-PO-005 | M | PO items are editable only in DRAFT status. |
| URD-PO-006 | M | A PO must have ≥1 item before it can be confirmed. |
| URD-PO-007 | M | Goods receipt increments stock and creates tracking entries. |
| URD-PO-008 | M | Receipt supports OVERRIDE and ACCUMULATIVE modes. |
| URD-PO-009 | M | PO defaults to the merchant's default location unless one is specified. |
| URD-PO-010 | M | PO total = subtotal − discount + tax. |
| URD-PO-011 | S | Manual vs. system discount/tax are flagged distinctly. |
| URD-PO-012 | M | Each PO has a system-generated purchase-order number. |
5.8 Purchase Order Item (POI)
| ID | P | Requirement |
|---|---|---|
| URD-POI-001 | M | Adding the same (itemType, itemId, uom) accumulates quantity; different uom creates a new line. |
| URD-POI-002 | M | Item total = (unitPrice × quantity × multiplier) + tax − discount. |
| URD-POI-003 | M | Setting an item quantity ≤ 0 soft-deletes the line and recalculates the PO total. |
| URD-POI-004 | S | Unit price defaults to the variant's active cost price. |
| URD-POI-005 | S | UOM defaults to the inventory item's base unit. |
5.9 Material (MAT)
| ID | P | Requirement |
|---|---|---|
| URD-MAT-001 | M | Owner can create materials within a merchant. |
| URD-MAT-002 | M | Material has a system identifier (MAT_YYYYMMDD_id) and an i18n name. |
| URD-MAT-003 | M | Material name supports multiple locales. |
| URD-MAT-004 | M | Material description is editable. |
| URD-MAT-005 | M | Material can be deactivated. |
| URD-MAT-006 | M | Material can be archived (terminal, read-only). |
| URD-MAT-007 | M | Material identifier is unique. |
| URD-MAT-101 | M | Owner can attach a BARCODE identifier to a material. |
| URD-MAT-102 | M | Material supports identifier schemes: SYSTEM, SLUG, SKU, BARCODE, QRCODE. |
| URD-MAT-103 | M | A (scheme, code) pair is unique across materials. |
| URD-MAT-104 | M | Identifier scheme defaults to SYSTEM when unspecified. |
| URD-MAT-105 | S | Multiple identifiers of different schemes can coexist on one material. |
| URD-MAT-106 | S | Material is searchable by registered barcode. |
5.10 Material Recipe / BOM (REC)
| ID | P | Requirement |
|---|---|---|
| URD-REC-001 | M | Owner can create a recipe attached to a product variant. |
| URD-REC-002 | M | Recipe has a version (default 1.0). |
| URD-REC-003 | M | (principal, version) is unique per recipe. |
| URD-REC-004 | M | Recipe items specify a material, quantity, and unit. |
| URD-REC-005 | M | Recipe items can be added to a recipe. |
| URD-REC-006 | M | Same material appears at most once per recipe. |
| URD-REC-007 | M | Owner can activate a recipe. |
| URD-REC-008 | M | Owner can deactivate a recipe. |
| URD-REC-009 | S | Editing an activated recipe creates a new version; the original is preserved. |
| URD-REC-010 | S | Multiple recipe versions can be listed per principal. |
| URD-REC-011 | M | Only the activated recipe version is used at runtime. |
| URD-REC-101 | M | Recipe item references a valid material. |
| URD-REC-102 | M | Recipe item quantity stored at decimal precision (4 places). |
| URD-REC-103 | M | Recipe item stores a unit. |
| URD-REC-104 | M | Recipe item quantity is editable. |
| URD-REC-105 | M | Recipe item soft-delete allows re-adding the same material. |
| URD-REC-201 | M | A kitchen-ticket-item status change triggers recipe lookup and decrement prep at the default location. |
| URD-REC-202 | M | Each recipe component is decremented; a tracking entry (Used as Material) is created. |
| URD-REC-203 | M | Component decrement updates stock at the default location. |
| URD-REC-204 | M | The activated recipe for the variant is the one exploded. |
| URD-REC-205 | M | A material.stock-changed event is emitted after explosion. |
| URD-REC-206 | S | No default location → log warning, skip (no hard failure). |
| URD-REC-207 | S | No activated recipe → silent no-op. |
| URD-REC-208 | C | Non-default kitchen location is respected (pending — current code uses the merchant default). |
5.11 Constraints & Cross-Cutting (CON)
| ID | P | Requirement |
|---|---|---|
| URD-CON-001 | M | All inventory endpoints require authentication (JWT or basic auth). |
| URD-CON-002 | M | All records use soft-delete; soft-deleted records are excluded from standard listings. |
| URD-CON-003 | M | Negative available quantity is currently tolerated (documented business constraint, not a bug). |
| URD-CON-004 | M | Stock deductions are idempotent per (referenceType, referenceId). |
6. Acceptance Criteria
AC-LOC-01: Default Location
| Given | When | Then |
|---|---|---|
| New merchant | Commerce initialization | Default location auto-created |
| Set a new default | — | Previous default cleared |
AC-STK-01: Stock Tracking
| Given | When | Then |
|---|---|---|
| Item with inventory | View | On-hand, reserved, available displayed |
| Available drops below threshold | — | Low-stock indicator shown |
AC-PO-01: Purchase Order Receipt
| Given | When | Then |
|---|---|---|
| PO in PROCESSING | Goods received | Stock incremented, tracking created |
| OVERRIDE mode | — | Replaces received quantity |
| ACCUMULATIVE mode | — | Adds to received quantity |
AC-BOM-01: Kitchen BOM
| Given | When | Then |
|---|---|---|
| Variant with activated recipe | Kitchen item status changes | Materials decremented per recipe item |
| No activated recipe | — | Silent no-op |
| No default location | — | Warning logged, skipped |
AC-TKT-01: Inventory Ticket
| Given | When | Then |
|---|---|---|
| Transfer ticket | COMPLETED | Source decreased, destination increased |
| Cycle count ticket | COMPLETED | Variance calculated and applied |
| Adjustment ticket | COMPLETED | Stock corrected with reason code |
7. Constraints & Non-Goals
Constraints
| ID | Constraint |
|---|---|
| C-01 | One default location per merchant at all times. |
| C-02 | One stock record per (item, location, lot, serial). |
| C-03 | Available = on-hand − reserved (negative currently tolerated). |
| C-04 | Tracking records are immutable. |
| C-05 | Stock movements are idempotent via (referenceType, referenceId). |
| C-06 | PO items editable only in DRAFT. |
| C-07 | 19 pre-seeded tracking types (+ 1 custom) at startup. |
| C-08 | All records use soft-delete. |
| C-09 | All quantities use decimal precision (4 places). |
Non-Goals
- Multi-level BOM (material as principal for sub-assemblies)
- Recipe yield and scrap percentage
- Explode-at-sale BOM for non-F&B retail
- Negative-stock enforcement at POS
- Full barcode scanning for stock takes
- Multi-currency stock valuation
8. Version History
| Date | Author | Description | Ver |
|---|---|---|---|
| 2026-02-28 | Q. Do - QE | Initial from code analysis | v0.1 |
| 2026-04-15 | Claude (AI pair) | Add Material and MaterialRecipe (BOM) requirements | v0.2 |
| 2026-04-16 | Q. Do - QE | Consolidated requirement areas | v0.3 |
| 2026-05-30 | Claude (AI pair) | Reformat to module template; reconcile tracking types to 19 (dev docs) | v0.4 |