Skip to content

Inventory Tracking

1. Tổng quan

Thuộc tínhGiá trị
IDFEAT-INV-TRACK
StatusStable
Ownerinventory-team
Phụ thuộcInventoryStock (mọi row đều tham chiếu một cái), DiscriminationType (validate type / referenceType / reason)

InventoryTrackingaudit trail duy nhất cho mọi thay đổi stock trong hệ thống. Mọi mutation adjustStock BẮT BUỘC ghi một row tracking. Bảng này cũng đóng vai trò sổ cái idempotency cho Kafka worker — xem ADR-0004.

2. Mô hình Entity

Trường InventoryTracking

TrườngKiểuBắt buộcMô tả
inventoryStockIdtextFK tới bucket được thay đổi
merchantIdtextDenormalize từ stock chain
referenceTypetextMột trong §4; typed<TInventoryTrackingReferenceType>
referenceIdtextID doc khởi nguồn (PO id, sale order id, v.v.) — nullable cho adjustment mồ côi
uomIdtextĐơn vị lúc ghi
multiplierdecimal(15,4)Hệ số UoM-to-base (mặc định 1)
quantityBeforedecimal(15,4)Snapshot trước khi thay đổi
quantityChangedecimal(15,4)Delta có dấu
quantityAfterdecimal(15,4)Snapshot sau khi thay đổi
effectivePricedecimal(15,4)Cost mỗi đơn vị (chỉ với write PURCHASE)
fromLocationId / toLocationIdtextSource / destination TRANSFER
reasonCodetextMột trong §5 (13 reason)
lotNumber / serialNumber / expiryDatetext / timestamptzSnapshot bất biến của bucket được di chuyển
remainingQuantitydecimal(15,4)Tracker layer FIFO (giảm dần khi outbound tiêu thụ)
notetextTự do (xem InventoryTrackingNotes bên dưới)
createdBy / modifiedBytextAudit user (cho phép ẩn danh)

Chú ý: không có cột type trong schema. "Loại movement" (một trong 19 FixedInventoryTrackingTypes) được suy ra từ (referenceType, reasonCode, dấu của quantityChange) lúc đọc, không lưu riêng. Code service thường ghi note để phân biệt.

Mutability: append-only. Service xem bảng này là bất biến; không bao giờ ghi deletedAt hay update row trong path bình thường.

3. Loại Tracking

Nguồn: FixedInventoryTrackingTypes trong @nx/core/src/models/schemas/inventory/inventory-tracking/constants.ts. Tổng cộng 19 + 1 CUSTOM.

Inbound (6)

TypeDùng bởi
STOCK_INNhận hàng thủ công không qua PO
PURCHASELuồng PO receive
TRANSFER_INChuyển cross-location (phía destination)
RETURN_FROM_CUSTOMERPhiếu return của customer
ADJUSTMENT_INTăng thủ công của admin
PRODUCTION_COMPLETEOutput ProductionOrder được ghi

Outbound (10)

TypeDùng bởi
STOCK_OUTTrừ thủ công không qua bán hàng
SALETrừ khi sale payment success
TRANSFER_OUTChuyển cross-location (phía source)
RETURN_TO_VENDORPhiếu return cho vendor
ADJUSTMENT_OUTGiảm thủ công của admin
EXPIREDScrap do hết hạn
LOSTMất/trộm
DAMAGEDWrite-off do hư hỏng
USED_INTERNALPhiếu dùng nội bộ
USED_AS_MATERIALTiêu thụ kitchen ticket (bung BOM)

Neutral (2)

TypeDùng bởi
INVENTORY_COUNTĐối chiếu cycle count
ADJUSTMENT_NEUTRALNhập admin delta-zero (chỉ để annotation)

Custom (1)

TypeDùng bởi
CUSTOMMở rộng tự do — bất kỳ loại merchant tự định nghĩa qua DiscriminationType

4. ReferenceTypes

Nguồn: InventoryTrackingReferenceTypes.

ReferenceTypeSử dụng
PURCHASE_ORDERPO receive
SALE_ORDERSale payment success → trừ product + reserve material
KITCHEN_TICKETVòng đời kitchen ticket
KITCHEN_TICKET_ITEMTiêu thụ BOM theo từng item
INVENTORY_TICKETWorkflow ticket (transfer, adjust, count, scrap, return)
PRODUCTION_ORDERTiêu thụ + output sản xuất
ADJUSTMENTNhập tay của admin không có doc cha
UNKNOWNFallback / chưa phân loại

5. Reasons

Nguồn: InventoryTrackingReasons.

ReasonSử dụng
DAMAGEDStock bị hỏng
LOSTĐặt sai chỗ / trộm
EXPIREDQuá hạn dùng
CYCLE_COUNTĐối chiếu audit
CORRECTIONSửa thủ công
CUSTOMER_RETURNRMA từ customer
VENDOR_RETURNRMA cho vendor
TRANSFER_IN / TRANSFER_OUTCross-location
PRODUCTION_CONSUMEMaterial dùng trong sản xuất
PRODUCTION_OUTPUTHàng hóa được sản xuất
RESERVATIONMaterial được reserve cho bán
RESERVATION_RELEASEReservation bị hủy (kitchen VOIDED)

6. Notes

Nguồn: inventory/src/common/constants.ts:1-18 (InventoryTrackingNotes).

Hằng sốGiá trị
ADJUSTMENT_FROM_PRODUCT_VARIANT_CREATE"Adjustment from product variant create form"
ADJUSTMENT_FROM_PRODUCT_VARIANT_UPDATE"Adjustment from product variant update form"
ADJUSTMENT_FROM_PRODUCT_VARIANT_CDC"Adjustment from product variant CDC bridge"
OVERSELL_BLOCKED"OVERSELL_BLOCKED: deduct skipped; insufficient stock with allowOversell=false"
INBOUND_FROM_PURCHASE_ORDER"Inbound from purchase order"
OUTBOUND_FROM_MATERIAL_USED"Outbound from material used"
ADJUSTMENT_FROM_MATERIAL_CREATE"Adjustment from material create from"
ADJUSTMENT_FROM_MATERIAL_UPDATE"Adjustment from material update from"
MATERIAL_RESERVED_FROM_SALE_ORDER"Material reserved at sale-order payment success"

7. Vận hành

Bề mặt service

InventoryTrackingService (inventory-tracking.service.ts:21-41) là MerchantScopedService chỉ kế thừa CRUD — không có mutator tùy biến. Read được filter theo merchant. Write xảy ra trong các luồng stock-mutation của service khác; không có public write API hôm nay (chủ ý — để bảo toàn tính toàn vẹn audit).

Bề mặt REST

VerbPathAuthPermission
6× CRUD/inventory-trackingsJWT/BASICInventoryTracking.<crud>

Thực tế là read-only — POST và endpoint mutation tồn tại qua CRUD nhưng service layer không lộ entry point write tùy biến nào.

8. Vai trò Idempotency

Mọi Kafka worker dùng InventoryTracking như sổ cái dedup trước bất kỳ stock mutation nào:

Xem ADR-0004 để có lý do đầy đủ.

9. Pattern Truy vấn

Câu hỏiTruy vấn
Movement cho một SaleOrderWHERE reference_type = 'SALE_ORDER' AND reference_id = '<id>'
Lịch sử stock cho một bucketWHERE inventory_stock_id = '<id>' ORDER BY created_at DESC
Sự cố oversell (24h gần nhất)WHERE note LIKE 'OVERSELL_BLOCKED%' AND created_at > now() - interval '24h'
Hàng nhận từ một vendor (qua PO)join PurchaseOrder trên referenceId where vendorId = '<id>'
Khối lượng phát hàng theo ngày theo typeGROUP BY type, date_trunc('day', created_at)

10. Side effects khi ghi

Side effectKhi nào
Denormalize merchantIdTừ InventoryStock.merchantId lúc ghi
Snapshot multiplierTừ UoM của line entity lúc ghi
Snapshot effectivePriceTừ unitPrice của line PO (chỉ trên type PURCHASE)

11. Trang liên quan

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