Skip to content

ADR-0005. Lưu trữ UoM — uom jsonb trên catalog + uomId soft ref trên line

TrườngGiá trị
StatusAccepted
Date2026-04-05
Decidersinventory-team, PM
Supersedes

Bối cảnh

  • Material có nhiều "vai trò" UoM: base (đơn vị lưu kho, vd gram), purchase (đơn vị hóa đơn vendor, vd kg), sale (đơn vị hiển thị, vd portion).
  • PurchaseOrderItem, VendorItem, MaterialRecipeItem, InventoryTracking mỗi cái có một context UoM đơn lẻ trên mỗi row.
  • FK chặt từ bảng line tới UnitOfMeasure mong manh: row UoM là reference data và có thể bị soft-delete hoặc đổi key bởi merchant.

Quyết định

Lưu trữ hai lớp:

  1. Catalog entity (Material, ProductVariant) lưu các vai trò trong một cột jsonb uom có dạng:
    ts
    type TUomRoles = {
      base: { id: string; code: string; name: I18n; ratio: number };
      purchase?: { ... };
      sale?: { ... };
    };
  2. Line entity (PurchaseOrderItem, VendorItem, MaterialRecipeItem, InventoryTracking) lưu uomId: text như một soft reference cộng với multiplier: decimal(15,4). Khai báo relations() trong model.ts cung cấp accessor uom cho query; DB không có foreign key.

Hệ quả

ProsCons
Snapshot catalog ổn định — kể cả khi UoM của merchant bị xóa, Material.uom vẫn cònCần validate ở service-layer rằng uomId resolve được lúc ghi
Line entity tách rời khỏi vòng đời UnitOfMeasureKhông có tính toàn vẹn tham chiếu cấp DB cho uomId
multiplier được capture lúc ghi line → quy đổi đơn vị bất biến sau đóHai dạng lưu trữ phải nhớ (jsonb vs uomId)
Replay/audit hoạt động không cần join UnitOfMeasureBáo cáo phải cẩn thận dùng multiplier cấp line, không phải uom cấp catalog

Phương án thay thế đã cân nhắc

Phương ánProsConsLý do từ chối
FK chặt uomId → UnitOfMeasure.id ở mọi nơiToàn vẹn tham chiếuVỡ khi soft-delete UoM; mong manh khi merchant overrideSai primitive cho reference data
Một jsonb trên mỗi line entityKhông lo FKLặp dữ liệu UoM trên mỗi line; khó query "tất cả line đơn vị kg"Lãng phí storage, đau đầu query
UnitOfMeasure với row có version (không soft-delete)ID ổn địnhThay đổi thiết kế lớn, không giải quyết nhu cầu snapshot multiplierNgoài phạm vi

Tham chiếu

  • core/src/models/schemas/inventory/material/schema.ts (uom jsonb)
  • core/src/models/schemas/inventory/purchase-order-item/schema.ts (uomId soft ref + model.ts uom relation)
  • Memory: feedback_uom_storage_convention.md

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