Test Cases: Inventory
| Module | CORE-06 | URD | Inventory URD |
|---|
1. Coverage Summary
| Area | URD reqs | Test cases | Covered |
|---|---|---|---|
Location (LOC) | 10 | 20 | ✅ |
Item (ITM) | 6 | 10 | ✅ |
Stock (STK) | 7 | 11 | ✅ |
Tracking (TRK) | 10 | 13 | ✅ |
Vendor (VEN) | 5 | 7 | ✅ |
Purchase Order (PO) | 12 | 26 | ✅ |
PO Item (POI) | 5 | 12 | ✅ |
Material (MAT) | 13 | 13 | ✅ |
Material Recipe / BOM (REC) | 24 | 21 | ⚠️ |
Constraints (CON) | 4 | 8 | ✅ |
Priority below = P1 (critical / Must) · P2 (major / Should) · P3 (minor / Could). One gap is open:
TC-REC-206(non-default kitchen location) is blocked on a code TODO.
2. Test Cases
TC-<AREA>-NNNlines up withURD-<AREA>-NNN.
Location (LOC)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-LOC-001 | URD-LOC-001, 007, 010 | Create location with i18n name | Authenticated merchant creates a location with a valid name | Location created; LOC_YYYYMMDD_id assigned; linked to exactly one merchant | P1 |
| TC-LOC-002 | URD-LOC-001 | Create without name | Attempt to create a location with no name | Rejected; "name required" error | P1 |
| TC-LOC-003 | URD-LOC-001 | Multilingual name | Provide name in en + vi | Created with all locales stored and retrievable | P1 |
| TC-LOC-004 | URD-LOC-007 | Identifier format | Create any location | Identifier matches LOC_YYYYMMDD_id; unique; not user-editable | P1 |
| TC-LOC-005 | URD-LOC-007 | Same-day uniqueness | Create two locations on the same date | Same date segment, distinct trailing id; both globally unique | P1 |
| TC-LOC-006 | URD-LOC-002 | Default auto-create | Complete commerce initialization | Exactly one default location auto-created and usable | P1 |
| TC-LOC-007 | URD-LOC-003 | Switch default | Mark a second location as default | New location becomes default; previous default cleared | P1 |
| TC-LOC-008 | URD-LOC-003 | Delete sole default | Delete/deactivate the only default without replacement | Rejected; merchant must always have one default | P1 |
| TC-LOC-009 | URD-LOC-004 | Child location | Create a child under a parent | Child references parent; parent lists children | P2 |
| TC-LOC-010 | URD-LOC-004 | Delete parent with children | Delete a parent that has children | Rejected or cascades; no orphans; integrity preserved | P2 |
| TC-LOC-011 | URD-LOC-005 | Store geo data | Update location with address + GPS | Geographic data stored and retrievable | P2 |
| TC-LOC-012 | URD-LOC-005 | Missing geo data | Create location with no address/coords | Created; geo fields null; no validation error | P2 |
| TC-LOC-013 | URD-LOC-006 | Activate | Activate a NEW location | Status NEW → ACTIVATED; usable for stock | P1 |
| TC-LOC-014 | URD-LOC-006 | Deactivate | Deactivate an ACTIVATED location | Status → DEACTIVATED; no new assignments; stock preserved | P1 |
| TC-LOC-015 | URD-LOC-006 | Archive | Archive a DEACTIVATED location | Status → ARCHIVED; data preserved; removed from active lists | P1 |
| TC-LOC-016 | URD-LOC-006 | Invalid skip | NEW → ARCHIVED directly | Rejected; invalid transition | P1 |
| TC-LOC-017 | URD-LOC-006 | Reactivate archived | Reactivate an ARCHIVED location | Rejected; ARCHIVED is terminal | P1 |
| TC-LOC-018 | URD-LOC-008 | Soft delete | Soft-delete a location | Flagged deleted; absent from active lists; data preserved; admin can retrieve | P1 |
| TC-LOC-019 | URD-LOC-009 | Filter by status | List filtered by ACTIVATED (3 active, 2 inactive) | Only the 3 ACTIVATED returned | P2 |
| TC-LOC-020 | URD-LOC-009, 010 | Merchant isolation | Merchant A lists locations | Only A's locations returned; B's hidden | P2 |
Inventory Item (ITM)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-ITM-001 | URD-ITM-001, 006 | Auto-create on variant | Create a product variant | Item auto-created, linked to default location, system identifier | P1 |
| TC-ITM-002 | URD-ITM-002 | Uniqueness | Create a 2nd item for same (variant, location, unit) | Rejected; uniqueness enforced; existing item unchanged | P1 |
| TC-ITM-003 | URD-ITM-002 | Different unit coexists | Create item for same variant+location, unit BOX vs PCS | New item created; both coexist; uniqueness is per (variant, location, unit) | P1 |
| TC-ITM-004 | URD-ITM-004 | Identifier format | Create any item | Identifier SKU_YYYYMMDD_id; unique; not editable | P1 |
| TC-ITM-005 | URD-ITM-005 | Deactivate | Deactivate an ACTIVATED item | Status → DEACTIVATED; excluded from active stock queries | P1 |
| TC-ITM-006 | URD-ITM-005 | Archive | Archive a DEACTIVATED item | Status → ARCHIVED; data preserved; removed from listings | P1 |
| TC-ITM-007 | URD-ITM-005 | Reactivate archived | Reactivate an ARCHIVED item | Rejected; ARCHIVED is terminal | P1 |
| TC-ITM-008 | URD-ITM-003 | Set thresholds | Set min=10, max=500 | Both thresholds stored and retrievable | P2 |
| TC-ITM-009 | URD-ITM-003 | Low-stock trigger | On-hand drops to 9 (below min 10) | Low-stock condition detected; event triggered/logged | P2 |
| TC-ITM-010 | URD-ITM-003 | Invalid thresholds | Set min > max | Rejected; min must be ≤ max | P2 |
Stock (STK)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-STK-001 | URD-STK-001, 002 | Available formula | Query stock with on-hand 100, reserved 30 | Available = 70 (on-hand − reserved) | P1 |
| TC-STK-002 | URD-STK-002 | Zero available | Reserved equals on-hand | Available = 0; not an error | P1 |
| TC-STK-003 | URD-STK-003 | Decimal precision | Store quantity 10.12345 | Rounded/truncated to 4 decimal places | P1 |
| TC-STK-004 | URD-STK-003 | Max boundary | Store 999999999999999.9999 | Persisted without overflow | P1 |
| TC-STK-005 | URD-STK-004 | First receipt | First stock receipt for a new item | Stock record created; on-hand = received; reserved 0; available = on-hand | P1 |
| TC-STK-006 | URD-STK-004 | Deduct before receipt | Deduct from an item with no stock | Either rejected (insufficient) or negative tolerated per URD-CON-003; behavior consistent | P1 |
| TC-STK-007 | URD-STK-005 | Counted timestamp | Complete a physical count | lastCountedAt updated to now | P2 |
| TC-STK-008 | URD-STK-005 | Stocked timestamp | Complete a stock receipt | lastStockedAt updated to now | P2 |
| TC-STK-009 | URD-STK-006 | Concurrent deduct | Two concurrent sales deduct 5 each from on-hand 10 | Total deduction exactly 10; no double-count; final on-hand 0 | P1 |
| TC-STK-010 | URD-STK-006 | Atomic rollback | Stock update fails mid-operation | Entire update rolls back; orphan tracking not persisted | P1 |
| TC-STK-011 | URD-CON-003 | Negative available | Sale of 8 from on-hand 5 | Available becomes −3; not rejected; stored and visible; warning logged | P1 |
QE finding (TC-STK-011): the service intentionally tolerates negative
quantityAvailable("refactor when business logic clearer"). This is a documented business constraint (URD-CON-003), not a bug — but downstream POS checkout must prevent or surface it, or it becomes a data-integrity risk.
Tracking (TRK)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-TRK-001 | URD-TRK-001, 002 | Inbound entry | PO receipt of 20 units | Immutable entry: before/change (+20)/after; cannot be edited or deleted | P1 |
| TC-TRK-002 | URD-TRK-001, 002 | Outbound entry | Sale deduction of 3 units | Entry: before/change (−3)/after; direction OUT; persisted | P1 |
| TC-TRK-003 | URD-TRK-002 | Boundary from zero | PURCHASE_IN of 50 from on-hand 0 | before 0, change +50, after 50 | P1 |
| TC-TRK-004 | URD-TRK-003 | PO reference | Movement triggered by a PO | Entry stores referenceType=PURCHASE_ORDER + PO id; traceable | P1 |
| TC-TRK-005 | URD-TRK-003 | Sale reference | Movement triggered by sale payment | Entry stores referenceType=SALE_ORDER + order id | P1 |
| TC-TRK-006 | URD-TRK-003 | Missing reference | Movement with no valid reference | Rejected, or entry flagged; audit traceability not silently lost | P1 |
| TC-TRK-007 | URD-TRK-004 | Idempotent replay | Replay an already-processed payment-success event | No second deduction; on-hand unchanged; no duplicate entry; returns success | P1 |
| TC-TRK-008 | URD-TRK-004 | Distinct concurrent | Two different sale orders deduct same item near-simultaneously | Each processed exactly once; neither skipped nor doubled | P1 |
| TC-TRK-009 | URD-TRK-005 | IN direction | Process a PURCHASE_IN | Direction IN; on-hand increases | P1 |
| TC-TRK-010 | URD-TRK-005 | OUT direction | Process a SALE_OUT | Direction OUT; on-hand decreases | P1 |
| TC-TRK-011 | URD-TRK-005 | NEUTRAL direction | Process ADJUSTMENT_NEUTRAL | Direction NEUTRAL; no net change; entry persisted for audit | P1 |
| TC-TRK-012 | URD-TRK-005 | Invalid type | Create entry with unrecognized type | Rejected; "not a valid tracking type" (19 + custom enumerated) | P1 |
| TC-TRK-013 | URD-TRK-006 | Audit fields | User triggers a movement | Entry stores createdBy/modifiedBy of the authenticated user | P2 |
Note (TC-TRK-007): the sync and queue payment-success paths duplicate the deduction logic with different error messages. Both must independently pass idempotency; a future refactor should unify them.
Vendor (VEN)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-VEN-001 | URD-VEN-001, 002, 005 | Create vendor | Create a vendor with name + contact | Created; VEN_YYYYMMDD_id assigned; linked to one merchant | P1 |
| TC-VEN-002 | URD-VEN-001 | Create without name | Create a vendor with no name | Rejected; "name required" | P1 |
| TC-VEN-003 | URD-VEN-003 | Tax number | Provide a tax registration number | Stored and retrievable | P2 |
| TC-VEN-004 | URD-VEN-002 | Identifier format | Create any vendor | Identifier VEN_YYYYMMDD_id; unique | P1 |
| TC-VEN-005 | URD-VEN-004 | Soft delete (unused) | Soft-delete a vendor with no active PO | Flagged deleted; absent from active lists; data preserved | P1 |
| TC-VEN-006 | URD-VEN-004 | Soft delete (in use) | Delete a vendor referenced by active POs | Rejected (in use) or proceeds preserving PO references; no orphans | P1 |
| TC-VEN-007 | URD-VEN-005 | Merchant isolation | Merchant A lists vendors | Only A's vendors returned; B's hidden | P1 |
Purchase Order (PO)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-PO-001 | URD-PO-001, 012 | Create with items | Create PO with vendor + items in one call | DRAFT; PO number assigned; items + merchant linked | P1 |
| TC-PO-002 | URD-PO-001 | Create without vendor | Create a PO with no vendor | Rejected; "vendor required" | P1 |
| TC-PO-003 | URD-PO-009 | Default location | Create PO without a location | Assigned to merchant default location | P1 |
| TC-PO-004 | URD-PO-009 | Explicit location | Create PO with a non-default location | Assigned to the specified location; default not overridden | P1 |
| TC-PO-005 | URD-PO-002 | Confirm | Confirm a DRAFT PO with ≥1 item | DRAFT → PROCESSING | P1 |
| TC-PO-006 | URD-PO-002, 004 | Revert | Revert a PROCESSING PO | PROCESSING → DRAFT; items intact | P1 |
| TC-PO-007 | URD-PO-002, 007 | Receive | Receive a PROCESSING PO | PROCESSING → RECEIVED; stock updated via tracking | P1 |
| TC-PO-008 | URD-PO-002 | Complete | Complete a RECEIVED PO | RECEIVED → COMPLETED | P1 |
| TC-PO-009 | URD-PO-002 | Close | Close a COMPLETED PO | COMPLETED → CLOSED | P1 |
| TC-PO-010 | URD-PO-003 | Cancel DRAFT | Cancel a DRAFT PO | → CANCELLED; data preserved; no stock movement | P1 |
| TC-PO-011 | URD-PO-003 | Cancel PROCESSING | Cancel a PROCESSING PO | → CANCELLED; no stock movement | P1 |
| TC-PO-012 | URD-PO-003 | Cancel RECEIVED | Cancel a RECEIVED PO | → CANCELLED; received stock NOT auto-reversed | P1 |
| TC-PO-013 | URD-PO-003 | Cancel CLOSED | Cancel a CLOSED PO | Rejected; CLOSED is terminal | P1 |
| TC-PO-014 | URD-PO-003 | Re-cancel | Cancel a CANCELLED PO | Rejected; already cancelled | P1 |
| TC-PO-015 | URD-PO-002 | Invalid skip | DRAFT → RECEIVED directly | Rejected; invalid transition | P1 |
| TC-PO-016 | URD-PO-002 | From terminal | CLOSED → any non-terminal | Rejected; CLOSED is terminal | P1 |
| TC-PO-017 | URD-PO-002 | Backward | COMPLETED → RECEIVED | Rejected; backward transition not permitted | P1 |
| TC-PO-018 | URD-PO-002 | Complete endpoint | Call complete on a RECEIVED PO | → COMPLETED, no error | P1 |
| TC-PO-019 | URD-PO-006 | Confirm empty PO | Confirm a DRAFT PO with zero items | Rejected; "must have at least one item" | P1 |
| TC-PO-020 | URD-PO-008 | OVERRIDE receive | Receive 50 in OVERRIDE on on-hand 20 | On-hand set to 50; prior balance discarded; PURCHASE_IN tracked | P1 |
| TC-PO-021 | URD-PO-008 | ACCUMULATIVE receive | Receive 50 in ACCUMULATIVE on on-hand 20 | On-hand 70; prior balance preserved; change +50 | P1 |
| TC-PO-022 | URD-PO-008 | Modes from zero | Receive 50 both modes on on-hand 0 | Both yield 50 | P1 |
| TC-PO-023 | URD-PO-010 | Total computation | subtotal 1,000,000; discount 50,000; tax 50,000 | total = 1,000,000; all summary fields consistent | P1 |
| TC-PO-024 | URD-PO-010 | Zero discount/tax | subtotal 100,000; discount 0; tax 0 | total = 100,000 | P1 |
| TC-PO-025 | URD-PO-011 | Manual discount flag | Enter discount manually | Metadata flags discount as manual | P2 |
| TC-PO-026 | URD-PO-011 | Auto tax flag | System calculates tax | Metadata flags tax as auto-calculated | P2 |
QE finding (TC-PO-018):
completePurchaseOrderhas an inverted guard — it currently throws when the PO IS in RECEIVED/COMPLETED, the opposite of intended. As written, only POs in other statuses can be "completed". TC-PO-018 fails against the current implementation — a blocking defect for the complete flow.
Purchase Order Item (POI)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-POI-001 | URD-POI-001 | Accumulate | Add same (type, id, uom) again, qty +5 | Existing line incremented to 15; no duplicate row | P1 |
| TC-POI-002 | URD-POI-001 | Distinct items | Add variant V1 and V2 | Two separate lines; tracked independently | P1 |
| TC-POI-003 | URD-POI-001 | Different uom | Add same variant, uom BOX vs PCS | New line; no accumulation across differing uom | P1 |
| TC-POI-004 | URD-POI-002 | Line total | unitPrice 10,000 × qty 5 × mult 1 + tax 500 − disc 200 | itemTotal = 50,300; DB-computed | P1 |
| TC-POI-005 | URD-POI-002 | Zero price | unitPrice 0, qty 1 | itemTotal = 0; no errors | P1 |
| TC-POI-006 | URD-POI-003 | Zero quantity removes | Set a DRAFT item qty to 0 | Soft-deleted; absent from list; PO total recalculates | P1 |
| TC-POI-007 | URD-POI-003 | Negative removes | Set a DRAFT item qty to −1 | Soft-deleted (qty ≤ 0 triggers deletion) | P1 |
| TC-POI-008 | URD-POI-003, PO-005 | Edit after confirm | Set item qty 0 on a PROCESSING PO | Rejected; items only editable in DRAFT | P1 |
| TC-POI-009 | URD-PO-005 | Add after receive | Add a new item to a RECEIVED PO | Rejected; items only modifiable in DRAFT | P1 |
| TC-POI-010 | URD-PO-005 | Edit in DRAFT | Add/update/remove items on a DRAFT PO | All succeed; summary recalculates each change | P1 |
| TC-POI-011 | URD-POI-004 | Price default | Add item without unit price (variant cost 8,000) | unitPrice defaults to 8,000 | P2 |
| TC-POI-012 | URD-POI-005 | UOM default | Add item without uom (base unit PCS) | uom defaults to PCS | P2 |
Material (MAT)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-MAT-001 | URD-MAT-001, 002 | Create material | Create material with i18n name | Persisted; MAT_YYYYMMDD_id; status ACTIVATED | P1 |
| TC-MAT-002 | URD-MAT-002 | Unique identifiers | Rapidly create multiple materials | Each has a unique MAT_YYYYMMDD_id | P1 |
| TC-MAT-003 | URD-MAT-003 | Multilingual name | Provide name in en + vi | All locales stored and retrievable | P1 |
| TC-MAT-004 | URD-MAT-004 | Update description | Update a material's description | Persisted; modifiedAt updated | P1 |
| TC-MAT-005 | URD-MAT-005 | Deactivate | Deactivate an activated material | Status DEACTIVATED; still readable; not added to new recipes | P1 |
| TC-MAT-006 | URD-MAT-006 | Archive | Archive a material | Status ARCHIVED; permanently read-only | P1 |
| TC-MAT-007 | URD-MAT-007 | Duplicate identifier | Create material with duplicate identifier | Unique constraint rejects the insert | P1 |
| TC-MAT-101 | URD-MAT-101 | Attach barcode | Attach a BARCODE identifier | Identifier row persisted with scheme BARCODE | P1 |
| TC-MAT-102 | URD-MAT-102 | All schemes | Attach SYSTEM, SLUG, SKU, BARCODE, QRCODE | All five persist and are retrievable | P1 |
| TC-MAT-103 | URD-MAT-103 | Duplicate (scheme, code) | Register an existing (BARCODE, code) on another material | Rejected by unique index | P1 |
| TC-MAT-104 | URD-MAT-104 | Scheme default | Create identifier without scheme | Scheme defaults to SYSTEM | P1 |
| TC-MAT-105 | URD-MAT-105 | Multiple schemes | Add a 2nd identifier of a different scheme | Both coexist; neither replaces the other | P2 |
| TC-MAT-106 | URD-MAT-106 | Search by barcode | Search by a registered barcode | The material is returned as the single match | P2 |
Material Recipe / BOM (REC)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-REC-001 | URD-REC-001, 002 | Create recipe | Create a recipe for PV_X with 3 items | Persisted with version 1.0; 3 items linked | P1 |
| TC-REC-002 | URD-REC-002 | Version default | Create a recipe with no version | Version defaults to 1.0 | P1 |
| TC-REC-003 | URD-REC-003 | Duplicate (principal, version) | Create a 2nd recipe with same triple | Rejected by unique constraint | P1 |
| TC-REC-004 | URD-REC-004, 005 | Add item | Add a recipe item (material, qty, unit) | New row persisted with all fields | P1 |
| TC-REC-005 | URD-REC-006 | Duplicate material | Add a material already in the recipe | Rejected by unique constraint | P1 |
| TC-REC-006 | URD-REC-007 | Activate | Activate a DRAFT recipe | Status ACTIVATED | P1 |
| TC-REC-007 | URD-REC-008 | Deactivate | Deactivate an ACTIVATED recipe | Status DEACTIVATED | P1 |
| TC-REC-008 | URD-REC-009 | New version | Add a new row same principal version 1.1 | Original preserved; new row inserted | P2 |
| TC-REC-009 | URD-REC-010 | List versions | Query recipes by principal (1.0, 1.1, 2.0) | All three versions returned | P2 |
| TC-REC-010 | URD-REC-011 | Runtime resolves activated | Query by (principal, status=ACTIVATED) with only 2.0 active | Only the 2.0 recipe returned | P1 |
| TC-REC-101 | URD-REC-101 | Valid material FK | Create a recipe item | FK resolves to an existing material | P1 |
| TC-REC-102 | URD-REC-102 | Quantity precision | Create item with qty 0.0125 | Persisted at 4-decimal precision | P1 |
| TC-REC-103 | URD-REC-103 | Unit stored | Create item with unit 'ml' | Unit stored as ml | P1 |
| TC-REC-104 | URD-REC-104 | Edit quantity | Update item qty 200 → 250 | Quantity updated; modifiedAt bumps | P1 |
| TC-REC-105 | URD-REC-105 | Soft-delete re-add | Remove an item then re-add same material | Row soft-deleted; re-add allowed | P1 |
| TC-REC-201 | URD-REC-201, 204 | Explosion trigger | Kitchen-ticket-item status change for PV_X with activated recipe | Worker looks up recipe, finds default location, prepares decrements | P1 |
| TC-REC-202 | URD-REC-202, 203 | Component decrement | For each recipe item during explosion | Material stock at default location decremented; USED_AS_MATERIAL tracking created | P1 |
| TC-REC-203 | URD-REC-205 | Emit event | Explosion completes | material.stock-changed event emitted | P1 |
| TC-REC-204 | URD-REC-206 | No default location | Kitchen status change, merchant has no default location | Warning logged, decrement skipped, no hard error | P2 |
| TC-REC-205 | URD-REC-207 | No activated recipe | Kitchen status change, variant has no activated recipe | "Recipe Not Found" logged; no decrement | P2 |
| TC-REC-206 | URD-REC-208 | Non-default kitchen location | Explosion runs for a kitchen on a non-default location | GAP — code uses merchant default location (TODO); blocked until resolved | P3 |
Constraints (CON)
| TC ID | URD ref | Scenario | Steps | Expected | P |
|---|---|---|---|---|---|
| TC-CON-001 | URD-CON-001 | No token | Call any endpoint with no auth | HTTP 401; no data | P1 |
| TC-CON-002 | URD-CON-001 | Expired token | Call any endpoint with an expired JWT | HTTP 401; no data | P1 |
| TC-CON-003 | URD-CON-001 | Valid JWT | Call any endpoint with a valid JWT | Authenticated; responds with data | P1 |
| TC-CON-004 | URD-CON-001 | Basic auth | Call any endpoint with valid basic auth | Authenticated; responds normally | P1 |
| TC-CON-005 | URD-CON-002 | Admin retrieve deleted | Admin queries including soft-deleted records | Record retrievable; fields intact; delete flag set; excluded from standard lists | P1 |
| TC-CON-006 | URD-CON-002 | Standard list excludes deleted | Standard listing of a soft-deleted location | Excluded; no error | P1 |
| TC-CON-007 | URD-CON-004 | Idempotent replay | Replay payment-success for SO-001 | No second deduction; on-hand unchanged; duplicate silently acknowledged | P1 |
| TC-CON-008 | URD-CON-004 | Concurrent idempotency | Idempotency check during in-flight deduction for same order | Exactly one deduction; second skips; no race-driven double deduction | P1 |
3. Traceability
Every Must requirement maps to ≥1 test case. One gap is flagged below.
| URD requirement | Test case(s) | Status |
|---|---|---|
| URD-LOC-001…010 | TC-LOC-001…020 | ✅ Covered |
| URD-ITM-001…006 | TC-ITM-001…010 | ✅ Covered |
| URD-STK-001…006 | TC-STK-001…010 | ✅ Covered |
| URD-STK-007 | — | ⚠️ Uncovered (Could — historical stock view) |
| URD-TRK-001…010 | TC-TRK-001…013 | ✅ Covered |
| URD-VEN-001…005 | TC-VEN-001…007 | ✅ Covered |
| URD-TKT-001…006 | — | ⚠️ Uncovered (ticket flows pending build) |
| URD-PO-001…012 | TC-PO-001…026 | ✅ Covered |
| URD-POI-001…005 | TC-POI-001…012 | ✅ Covered |
| URD-MAT-001…106 | TC-MAT-001…106 | ✅ Covered |
| URD-REC-001…207 | TC-REC-001…205 | ✅ Covered |
| URD-REC-208 | TC-REC-206 | ⚠️ Gap — pending code TODO in MaterialWorkerService |
| URD-CON-001…004 | TC-CON-001…008, TC-STK-011, TC-TRK-007 | ✅ Covered |
Summary: ~96 URD requirements → 131 test cases · 1 known gap (TC-REC-206) · Must-level coverage complete except inventory tickets (TKT), which are not yet built (see URD §5.5).
4. References
| Document | Description |
|---|---|
| Inventory URD | Requirement source for all TC traceability |
| Inventory overview | Module identity, capabilities, flows |
Developer docs — @nx/inventory | Implementation detail and verified behavior |