Skip to content

Inventory Schema

The inventory schema contains 12 models that manage stock levels, inventory tracking, purchase orders, vendor relationships, and bill-of-materials recipes with raw-material tracking. It supports multi-location inventory with detailed audit trails.

Source: packages/core/src/models/schemas/inventory/

Models Overview

ModelTable NameDescription
InventoryLocationinventory.InventoryLocationPhysical or logical storage locations
InventoryIteminventory.InventoryItemTrackable items linked to product variants or materials
InventoryStockinventory.InventoryStockStock quantities for an inventory item
InventoryTrackinginventory.InventoryTrackingAudit log of all stock movements
InventoryTrackingTypeinventory.InventoryTrackingTypeCategorization of tracking movements
PurchaseOrderinventory.PurchaseOrderPurchase orders from vendors
PurchaseOrderIteminventory.PurchaseOrderItemLine items within a purchase order
Vendorinventory.VendorSupplier/vendor information
Materialinventory.MaterialRaw materials and semi-finished goods used in bill-of-materials recipes
MaterialIdentifierinventory.MaterialIdentifierScheme-based identifiers (SKU, BARCODE, QRCODE, …) attached to a Material
MaterialRecipeinventory.MaterialRecipeVersioned bill-of-materials recipe attached to a principal (typically a ProductVariant)
MaterialRecipeIteminventory.MaterialRecipeItemLine item in a MaterialRecipe: a Material consumed at a given quantity

InventoryLocation

Physical or logical storage locations with hierarchical support.

ColumnTypeConstraintsDescription
identifiertextNOT NULL, UNIQUEAuto-generated (e.g., LOC_20260216_...)
namejsonb (i18n)NOT NULLInternationalized name
statustextNOT NULL, DEFAULT NEWLocation status (NEW, ACTIVATED, DEACTIVATED, ARCHIVED)
locationjsonb (ILocation)Physical address and coordinates
is_defaultbooleanNOT NULL, DEFAULT falseWhether this is the default location
merchant_idtextNOT NULLFK to Merchant
parent_idtextFK to parent InventoryLocation
+ common columnsid, createdAt, modifiedAt, deletedAt, metadata

InventoryItem

Trackable items linked to a principal entity via polymorphic references. The principal can be a Product, ProductVariant, or Material; ProductVariant is the default.

ColumnTypeConstraintsDescription
item_typetextPolymorphic entity type: Product, ProductVariant, or Material (default: ProductVariant)
item_idtextPolymorphic entity ID
identifiertextNOT NULL, UNIQUEAuto-generated (e.g., SKU_20260216_...)
statustextNOT NULL, DEFAULT ACTIVATEDItem status (ACTIVATED, DEACTIVATED, ARCHIVED)
min_stock_leveldecimal(15,4)Minimum stock threshold
max_stock_leveldecimal(15,4)Maximum stock threshold
base_unittextNOT NULLBase unit of measure
inventory_location_idtextNOT NULLFK to InventoryLocation
+ common columns

InventoryStock

Stock quantities for an inventory item. Tracks on-hand, reserved, and available stock.

ColumnTypeConstraintsDescription
quantity_on_handdecimal(15,4)NOT NULL, DEFAULT '0'Total physical stock
quantity_reserveddecimal(15,4)NOT NULL, DEFAULT '0'Allocated for orders
quantity_availabledecimal(15,4)NOT NULL, DEFAULT '0'Available for sale (on-hand - reserved)
last_counted_atisoTimestampLast physical count timestamp
last_stocked_atisoTimestampLast stocking timestamp
inventory_item_idtextNOT NULLFK to InventoryItem
+ common columns

InventoryTracking

Audit log entry recording every stock movement with before/after quantities.

ColumnTypeConstraintsDescription
reference_idtextReference entity ID (e.g., SaleOrder ID, PurchaseOrder ID)
reference_typetextReference entity type
uomtextNOT NULLUnit of measure for this movement
multiplierdecimal(15,4)NOT NULL, DEFAULT '1'UOM multiplier
quantity_beforedecimal(15,4)NOT NULLStock quantity before movement
quantity_changedecimal(15,4)NOT NULLChange amount (positive or negative)
quantity_afterdecimal(15,4)NOT NULLStock quantity after movement
effective_pricedecimal(15,4)Price per unit for this movement
inventory_stock_idtextNOT NULLFK to InventoryStock
inventory_tracking_type_idtextNOT NULLFK to InventoryTrackingType
notetextMovement note
created_bytextCreator user ID
modified_bytextLast modifier user ID
+ common columns

InventoryTrackingType

Categorization of tracking movements with direction (inbound, outbound, neutral).

ColumnTypeConstraintsDescription
typetextNOT NULLTracking type code
namejsonb (i18n)NOT NULLInternationalized name
descriptionjsonb (i18n)Internationalized description
directiontextNOT NULLDirection: 000_IN, 100_OUT, 200_NEUTRAL
statustextDEFAULT ACTIVATEDStatus (ACTIVATED, DEACTIVATED, ARCHIVED)
merchant_idtextFK to Merchant (null for global types)
+ common columns

Unique constraint: (type, merchantId)

Fixed Inventory Tracking Types

Inbound (IN):

CodeValueDescription
STOCK_IN000_STOCK_INGeneral stock in
PURCHASE001_PURCHASEReceived from purchase order
TRANSFER_IN002_TRANSFER_INTransferred from another location
RETURN_FROM_CUSTOMER003_RETURN_FROM_CUSTOMERReturned by customer
ADJUSTMENT_IN004_ADJUSTMENT_INManual increase adjustment
PRODUCTION_COMPLETE005_PRODUCTION_COMPLETECompleted production

Outbound (OUT):

CodeValueDescription
STOCK_OUT100_STOCK_OUTGeneral stock out
SALE101_SALESold to customer
TRANSFER_OUT102_TRANSFER_OUTTransferred to another location
RETURN_TO_VENDOR103_RETURN_TO_VENDORReturned to vendor
ADJUSTMENT_OUT104_ADJUSTMENT_OUTManual decrease adjustment
EXPIRED105_EXPIREDExpired stock
LOST106_LOSTLost stock
DAMAGED106_DAMAGEDDamaged stock
USED_INTERNAL107_USED_INTERNALUsed internally
USED_AS_MATERIAL107_USED_AS_MATERIALConsumed as a raw material in a production/recipe flow

Neutral (NEUTRAL):

CodeValueDescription
INVENTORY_COUNT200_INVENTORY_COUNTPhysical inventory count
ADJUSTMENT_NEUTRAL201_ADJUSTMENT_NEUTRALNeutral adjustment (no quantity change)

PurchaseOrder

Purchase orders from vendors with a status lifecycle identical to SaleOrder.

Status Lifecycle

Status Values: DRAFT (001_DRAFT), PROCESSING (203_PROCESSING), RECEIVED (205_RECEIVED), COMPLETED (303_COMPLETED), CLOSED (404_CLOSED), CANCELLED (505_CANCELLED)

Active set (can be modified or cancelled): DRAFT, PROCESSING, RECEIVED, COMPLETED. Receivable set (can accept goods receipt): PROCESSING, RECEIVED, COMPLETED. Terminal set (read-only): CLOSED, CANCELLED.

Columns

ColumnTypeConstraintsDescription
purchase_order_numbertextNOT NULL, UNIQUEAuto-generated (e.g., 20260216120000-...)
nametextOrder name (auto-generated)
slugtextUNIQUEURL-friendly identifier (auto-generated)
order_dateisoTimestampNOT NULLOrder date (defaults to now)
expected_delivery_dateisoTimestampExpected delivery date
actual_delivery_dateisoTimestampActual delivery date
statustextNOT NULL, DEFAULT 001_DRAFTOrder status
draft_atisoTimestampTimestamp when entered DRAFT
processing_atisoTimestampTimestamp when entered PROCESSING
confirmed_atisoTimestampTimestamp when confirmed
received_atisoTimestampTimestamp when entered RECEIVED
completed_atisoTimestampTimestamp when entered COMPLETED
closed_atisoTimestampTimestamp when entered CLOSED
cancelled_atisoTimestampTimestamp when entered CANCELLED
merchant_idtextNOT NULLFK to Merchant
vendor_idtextNOT NULLFK to Vendor
inventory_location_idtextNOT NULLFK to InventoryLocation
currencytextNOT NULL, DEFAULT 'VND'Currency code
exchange_ratedecimal(12,6)DEFAULT '1'Exchange rate
subtotaldecimal(15,4)NOT NULL, DEFAULT '0'Subtotal
taxdecimal(15,4)NOT NULL, DEFAULT '0'Total tax
discountdecimal(15,4)NOT NULL, DEFAULT '0'Total discount
totaldecimal(15,4)NOT NULL, DEFAULT '0'Final total
metadatajsonbTPurchaseOrderMetadata
created_bytextCreator user ID
modified_bytextLast modifier user ID
+ common columns

TPurchaseOrderMetadata

typescript
type TPurchaseOrderMetadata = {
  note?: string;
  merchantId?: string;
  isDiscountManual?: boolean; // true = use PO.discount, ignore item discounts
  isTaxManual?: boolean;      // true = use PO.tax, ignore item taxes
  [key: string]: any;
};

PurchaseOrderItem

Line items within a purchase order with polymorphic product/material reference and computed total.

ColumnTypeConstraintsDescription
purchase_order_idtextNOT NULLFK to PurchaseOrder
item_typetextPolymorphic entity type: Product, ProductVariant, or Material (default: ProductVariant)
item_idtextPolymorphic entity ID
currencytextNOT NULL, DEFAULT 'VND'Currency code
uomtextNOT NULLUnit of measure
multiplierdecimal(15,4)NOT NULL, DEFAULT '1'UOM multiplier
quantitydecimal(15,4)NOT NULLOrdered quantity
received_quantitydecimal(15,4)NOT NULL, DEFAULT '0'Received quantity
unit_pricedecimal(15,4)NOT NULL, DEFAULT '0'Price per unit
taxdecimal(15,4)NOT NULL, DEFAULT '0'Tax amount
discountdecimal(15,4)NOT NULL, DEFAULT '0'Discount amount
totaldecimal(15,4)NOT NULL, GENERATEDComputed: (unit_price * quantity * multiplier + tax - discount)
created_bytextCreator user ID
modified_bytextLast modifier user ID
+ common columns

Item Modes: PRODUCT (000_PRODUCT), MATERIAL (001_MATERIAL), CUSTOM (100_CUSTOM)

  • PRODUCT mode: line item references a ProductVariant (default).
  • MATERIAL mode: line item references a Material (raw ingredient or semi-finished good purchased for BOM consumption).
  • CUSTOM mode: free-text line item with no SKU reference — the metadata fields (name, description, sku, barcode, imageUrl) are used instead.

Vendor

Supplier/vendor information.

ColumnTypeConstraintsDescription
nametextNOT NULLVendor name
identifiertextNOT NULL, UNIQUEAuto-generated (e.g., VEN_20260216_...)
emailstext[]DEFAULT '{}'Email addresses
phonestext[]DEFAULT '{}'Phone numbers
locationjsonb (ILocation)Physical address
tax_numbertextTax identification number
notetextNotes
merchant_idtextNOT NULLFK to Merchant
+ common columns

Material

Raw materials and semi-finished goods used as components inside a MaterialRecipe (bill-of-materials). Materials are not sellable on their own — they exist to be consumed by a recipe that produces a sellable ProductVariant.

ColumnTypeConstraintsDescription
slugtextNOT NULLHuman-readable identifier within the Merchant scope
statustextNOT NULL, DEFAULT 201_ACTIVATEDMaterial status (ACTIVATED, DEACTIVATED, ARCHIVED)
identifiertextNOT NULL, UNIQUEAuto-generated (e.g., MAT_20260414_...)
namejsonb (i18n)NOT NULLInternationalized name
descriptionjsonb (i18n)Internationalized description
merchant_idtextNOT NULLFK to Merchant
+ common columnsid, createdAt, modifiedAt, deletedAt, metadata

Status Values: ACTIVATED (201_ACTIVATED), DEACTIVATED (202_DEACTIVATED), ARCHIVED (203_ARCHIVED)

MaterialIdentifier

Scheme-based identifier for a Material. Enables looking up a Material by SKU, barcode, QR code, or other code systems. A Material can have multiple identifiers across different schemes; the (scheme, identifier) pair is unique globally so the same barcode or SKU cannot be registered against two different materials.

ColumnTypeConstraintsDescription
schemetextNOT NULL, DEFAULT SYSTEMIdentifier scheme (SYSTEM, SLUG, SKU, BARCODE, QRCODE)
identifiertextNOT NULLThe identifier value
material_idtextNOT NULLFK to Material
+ common columns

Unique index: UQ_MaterialIdentifier_scheme_identifier on (scheme, identifier).

Schemes: SYSTEM (internal ID, default), SLUG (URL-friendly), SKU (stock-keeping unit), BARCODE (linear barcode), QRCODE (QR code).

MaterialRecipe

Versioned bill-of-materials recipe defining which Materials are consumed to produce a given principal entity. The principal is polymorphic (currently Product or ProductVariant). Recipes are versioned — a single principal can have multiple recipe versions, but only the activated version is looked up at runtime.

ColumnTypeConstraintsDescription
principal_typetextPolymorphic principal type: Product or ProductVariant
principal_idtextNOT NULLPolymorphic principal ID
statustextNOT NULL, DEFAULT 201_ACTIVATEDRecipe status (DRAFT, ACTIVATED, DEACTIVATED)
merchantIdtextNOT NULLFK to Merchant (note: camelCase column name)
namejsonb (i18n)Optional recipe display name
descriptionjsonb (i18n)Optional recipe description
versionnumeric(10,1)NOT NULL, DEFAULT '1.0'Recipe version
+ common columns

Unique index: UQ_MaterialRecipe_product_variant_id_version on (principal_type, principal_id, version). Prevents duplicate recipes of the same version for the same principal.

Status Values: DRAFT (001_DRAFT), ACTIVATED (201_ACTIVATED), DEACTIVATED (202_DEACTIVATED).

Principal Types: Product, ProductVariant — resolved via the polymorphic (principal_type, principal_id) pair.

INFO

The merchantId column is camelCase in the database (unlike other inventory tables that use snake_case). This is a historical artifact from migration 0004_abnormal_photon.sql where the column was added post-hoc. Query it as "merchantId" with quotes in raw SQL.

MaterialRecipeItem

A single line in a MaterialRecipe: "consume X units of Material Y." One recipe has many items; each item references exactly one Material.

ColumnTypeConstraintsDescription
quantitydecimal(15,4)NOT NULLQuantity of the material consumed per produced unit
unittextNOT NULLUnit of measure for the quantity
material_idtextNOT NULLFK to Material
material_recipe_idtextNOT NULLFK to MaterialRecipe
+ common columns

Unique index: UQ_MaterialRecipeItem_material_id_material_recipe_id on (material_id, material_recipe_id). A Material can appear at most once as an item within the same recipe.

Entity Relationships

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