Skip to content

PRD: Materials

ModuleInventory (CORE-06)PRD IDPRD-MAT-001
StatusShippedOwnerInventory squad
Date2026-05-18Versionv1.0
Packages@nx/inventory · @nx/core · apps/clientURDMAT

TL;DR

Gives F&B merchants a first-class Material catalog - raw ingredients and semi-finished goods tracked separately from sellable products. Each material carries an i18n name, a system identifier, and multiple identifier schemes (SKU, barcode, QR) so it can be looked up at receipt and stock-take time. Materials are the principal that recipes (BOM) consume, turning ad-hoc ingredient notes into a managed, scannable inventory.

1. Context & Problem

F&B merchants buy and consume raw ingredients - flour, milk, syrup - that are never sold directly but are needed to produce sellable products. The existing inventory model only tracks product variants, so there is nowhere to record these inputs or to drive a bill-of-materials decrement at the kitchen. Without a material entity, ingredient stock cannot be counted, looked up by barcode, or consumed by a recipe, which blocks accurate cost tracking and kitchen automation for the F&B vertical KICKO targets.

Materials introduces a per-merchant catalog of raw and semi-finished goods kept separate from the product catalog. It is the principal that recipes (the REC feature) consume, and it carries its own identifier scheme so it can be found by SKU, barcode, or QR code.

2. Goals & Non-Goals

Goals

  • A per-merchant Material catalog entity, isolated per merchant, separate from product variants.
  • An i18n material name (multiple locales) and an editable description.
  • A system identifier (MAT_YYYYMMDD_id), auto-generated and not user-editable.
  • A lifecycle that supports deactivate and archive (archived is terminal / read-only).
  • A MaterialIdentifier sub-entity supporting schemes SYSTEM, SLUG, SKU, BARCODE, QRCODE, with SYSTEM as the default and (scheme, code) unique across materials.
  • Multiple identifiers of different schemes on one material, plus barcode search.
  • A material aggregate API (create/update with identifiers and vendor dimensions) backing the client management screens.

Non-Goals

  • Material recipes / BOM and kitchen explosion - owned by the REC feature.
  • Multi-level BOM (material as principal for sub-assemblies) - URD Non-Goal.
  • Recipe yield and scrap percentage - URD Non-Goal.
  • Full barcode-scanning integration for stock takes - URD Non-Goal.

3. Success Metrics

MetricTarget / signal
Catalog adoptionF&B merchants maintain their raw ingredients as materials rather than free-text notes
Identifier uniquenessZero duplicate (scheme, code) pairs across a merchant's materials
Lookup coverageMaterials with a registered BARCODE are found by barcode search at receipt/stock-take
BOM readinessMaterials available as the principal that recipes (REC) can consume

4. Personas & Use Cases

PersonaGoal in this feature
OwnerMaintain the raw-ingredient catalog, assign SKUs/barcodes, archive obsolete materials
Inventory staffFind a material by barcode/QR at receipt and stock-take time
Kitchen (via Recipes)Reference materials as recipe components for BOM decrement

Core scenarios: create a material with an i18n name and vendor dimensions → attach SKU/barcode/QR identifiers → look it up by barcode at receipt → deactivate or archive when it is no longer used.

5. User Stories

  • As an owner, I want to create a material with an i18n name and description, so my raw ingredients are catalogued separately from sellable products.
  • As an owner, I want each material to get a unique system identifier automatically, so I never have to invent or collide codes.
  • As an owner, I want to attach SKU, barcode, and QR identifiers to a material, so it can be scanned and looked up at receipt and stock-take.
  • As inventory staff, I want to search a material by its registered barcode, so I can find it quickly on the floor.
  • As an owner, I want to deactivate or archive a material, so obsolete ingredients leave the working catalog without losing history.
  • As an owner, I want to create and update a material together with its identifiers and vendor dimensions in one aggregate call, so the management screen saves a complete record at once.

6. Functional Requirements

#RequirementURD ref
FR-1Create a per-merchant material, isolated per merchant, separate from product variantsURD-MAT-001
FR-2Material has an auto-generated system identifier (MAT_YYYYMMDD_id) and an i18n name supporting multiple localesURD-MAT-002..003
FR-3Material description is editableURD-MAT-004
FR-4Material lifecycle supports deactivate and archive (archived is terminal / read-only)URD-MAT-005..006
FR-5Material identifier is uniqueURD-MAT-007
FR-6Owner can attach a BARCODE identifier to a materialURD-MAT-101
FR-7Identifier supports schemes SYSTEM, SLUG, SKU, BARCODE, QRCODE; scheme defaults to SYSTEM when unspecifiedURD-MAT-102 · URD-MAT-104
FR-8A (scheme, code) pair is unique across materialsURD-MAT-103
FR-9Multiple identifiers of different schemes can coexist on one materialURD-MAT-105
FR-10Material is searchable by registered barcodeURD-MAT-106
FR-11Material aggregate create/update accepts identifiers and vendor dimensions; malformed update payloads are rejectedURD-MAT-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 integrity(scheme, code) uniqueness is enforced across a merchant's materials; identifier conflicts are rejected
Tenancy & authzMaterials are isolated per merchant (x-merchant-id) and gated by inventory permissions
Lifecycle safetyArchived materials are terminal / read-only; soft-delete preserves history
i18nMaterial names are stored as an i18n object ({ en, vi, … }) supporting multiple locales
Vendor linkageVendor association flows through VendorItem, never a vendorId column on the material
ConsistencyAggregate create/update (material + identifiers + vendor dimensions) is transactional; malformed payloads are rejected without partial writes

8. UX & Flows

Key screens (in apps/client): the material management screen with unit-of-measure support, form validation, vendor multi-select, identifier entry, and an overview with summary widgets.

9. Data & Domain

EntityRole
MaterialThe catalog principal - i18n name, description, system identifier, status, typed metadata jsonb
MaterialIdentifierA sub-entity holding an identifier (scheme, code); schemes SYSTEM / SLUG / SKU / BARCODE / QRCODE
VendorItemThe link between a material and its vendors (sole source of truth for vendor association)
InventoryItem / stockOptional stock linkage created together with the material

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

10. Dependencies & Assumptions

Depends on

  • Inventory items & stock (URD-ITM · URD-STK) - a material can be created together with its inventory item/stock linkage.
  • Vendors (URD-VEN) - vendor dimensions on a material link through VendorItem.
  • @nx/core - material and material-identifier schemas/models live under the centralized core inventory schemas.

Assumptions

  • The merchant exists and has a default inventory location for any stock linkage.
  • Identifier codes are unique per (scheme, code) within the merchant's materials.

11. Risks & Open Questions

Risk / questionMitigation / status
Duplicate (scheme, code) would break lookupUniqueness enforced across materials; conflicting writes rejected
Vendor link could drift if stored on the materialVendor association flows through VendorItem only - no vendorId column
Archived materials still referenced by recipesArchive is terminal/read-only; recipes (REC) consume only active materials
Full barcode-scanning integration for stock takesOut of scope this increment; barcode search is supported, hardware scan flow deferred

12. Release Plan & Launch Criteria

AspectPlan
PhaseP3 (BOM + Advanced) - see URD feature catalog
RolloutAll merchants; no feature flag (F&B verticals are the primary users)
MigrationNone - new entities under @nx/core inventory schemas
Launch criteriaCreate material → attach SKU/barcode/QR → barcode lookup returns it → (scheme, code) uniqueness rejected on conflict → aggregate create/update verified end-to-end
MonitoringMaterial count per merchant, identifier-conflict rejection rate, barcode-search hit rate

13. FAQ

How is a material different from a product? A material is a raw or semi-finished input that is never sold directly; a product variant is sellable. Materials are catalogued separately and consumed by recipes (BOM).

Can one material have several barcodes? Yes - multiple identifiers of different schemes (SKU, BARCODE, QRCODE) can coexist on one material, as long as each (scheme, code) pair is unique across materials.

What scheme is used if I do not pick one? The identifier scheme defaults to SYSTEM, and a system identifier (MAT_YYYYMMDD_id) is generated automatically.

Can I delete a material? Materials are soft-deleted and can be deactivated or archived; archived is terminal and read-only, so history is preserved.

How do I link a vendor to a material? Vendor association flows through VendorItem (the vendor multi-select on the management screen), never a column on the material itself.

References

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