ADR-0005. Lưu trữ UoM - uom jsonb trên danh mục + uomId tham chiếu mềm trên dòng
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-04-05 |
| Người quyết định | Phat Nguyen |
| Thay thế | - |
Bối cảnh
Materialcó nhiều vai trò UoM: base (đơn vị lưu kho, ví dụ gram), purchase (đơn vị trên hóa đơn vendor, ví dụ kg), sale (đơn vị hiển thị, ví dụ phần).PurchaseOrderItem,VendorItem,MaterialRecipeItem,InventoryTrackingmỗi loại có một ngữ cảnh UoM duy nhất trên mỗi dòng.- FK chặt từ các bảng dòng tới
UnitOfMeasurerất mong manh: các dòng UoM là dữ liệu tham chiếu và có thể bị soft-delete hoặc đổi khóa bởi merchant.
Quyết định
Lưu trữ hai lớp:
- Thực thể danh mục (
Material,ProductVariant) lưu các vai trò trong một cột jsonbuomcó dạng:tstype TUomRoles = { base: { id: string; code: string; name: I18n; ratio: number }; purchase?: { ... }; sale?: { ... }; }; - Thực thể dòng (
PurchaseOrderItem,VendorItem,MaterialRecipeItem,InventoryTracking) lưuuomId: textnhư một tham chiếu mềm cộng vớimultiplier: decimal(15,4). Khai báorelations()trongmodel.tscung cấp accessoruomcho truy vấn; DB không có foreign key.
Hệ quả
| Ưu điểm | Nhược điểm |
|---|---|
Snapshot danh mục ổn định - kể cả khi UoM của merchant bị xóa, Material.uom vẫn còn | Cần kiểm tra ở tầng service rằng uomId phân giải được lúc ghi |
Thực thể dòng tách rời khỏi vòng đời UnitOfMeasure | Không có toàn vẹn tham chiếu ở cấp DB cho uomId |
multiplier được chốt lúc ghi dòng → quy đổi đơn vị bất biến về sau | Phải nhớ hai dạng lưu trữ (jsonb so với uomId) |
Lập luận khi phát lại/kiểm toán hoạt động mà không cần join UnitOfMeasure | Báo cáo phải cẩn thận dùng multiplier cấp dòng, không phải uom cấp danh mục |
Phương án thay thế đã cân nhắc
| Phương án | Ưu điểm | Nhược điểm | Lý do từ chối |
|---|---|---|---|
FK chặt uomId → UnitOfMeasure.id ở mọi nơi | Toàn vẹn tham chiếu | Vỡ khi soft-delete UoM; mong manh khi merchant ghi đè | Sai primitive cho dữ liệu tham chiếu |
| Một jsonb trên mỗi thực thể dòng | Không lo FK mong manh | Lặp dữ liệu UoM trên mỗi dòng; khó truy vấn "tất cả dòng đơn vị kg" | Lãng phí lưu trữ, khổ khi truy vấn |
UnitOfMeasure có phiên bản theo dòng (không soft-delete) | ID ổn định | Thay đổi thiết kế lớn, không giải quyết nhu cầu snapshot multiplier | Ngoài phạm vi |
Tham chiếu
core/src/models/schemas/inventory/material/schema.ts(uomjsonb)core/src/models/schemas/inventory/purchase-order-item/schema.ts(uomIdtham chiếu mềm + quan hệuomtrongmodel.ts)- Memory:
feedback_uom_storage_convention.md