Skip to content

Type Deep Dive — Stock Snapshot vs Ledger

1. Source-of-truth nằm ở đâu?

Source-of-truth cho movement là:

  • product_supplying

Nguồn đọc tồn vận hành là:

  • product_lot_no_stock
  • product_sku_stock

Nguồn aggregate/report là:

  • product_sku_stock_mv
  • product_sku_stock_product_mv
  • product_supplying_hold_mv

2. product_supplying là gì?

Mỗi row mang nhiều dimensions:

  • product_id
  • sku
  • lot_number
  • supplier_id
  • warehouse_id
  • quantity
  • price
  • type
  • inventory_document_id
  • shipping_note_code

Đây là lý do product_supplying vừa mạnh vừa nguy hiểm:

  • nó đủ dữ liệu để lần ra movement thật,
  • nhưng quá overloaded nếu dùng như bảng đọc trực tiếp cho UI.

3. product_lot_no_stock

Đây là snapshot chi tiết nhất ở tầng vận hành:

  • theo product + branch + sku + lot_number,
  • quantity, quantity_remain, quantity_expired, quantity_near_expired.

Khi cần:

  • xem tồn theo lot,
  • kiểm tra expiry,
  • đọc tồn khả dụng theo lot,

thì product_lot_no_stock mới là nguồn gần nhất với bài toán UI.

4. product_sku_stock

Đây là snapshot aggregate hơn:

  • tổng hợp từ product_lot_no_stock,
  • rồi join lại ledger để lấy:
    • last_import_date
    • last_export_date
    • nearest_expiry_date
    • stock_price

Nó phù hợp cho:

  • list inventory,
  • card tổng hợp theo SKU,
  • màn hình cần tồn theo SKU thay vì theo lot.

5. Materialized views

Hệ thống còn có thêm lớp MV cho reporting:

  • product_sku_stock_mv
  • product_sku_stock_product_mv
  • product_supplying_hold_mv

Điểm quan trọng:

  • chúng không phải nguồn read chính cho vận hành từng phiếu,
  • chúng phụ thuộc scheduler refresh,
  • nên không nên dùng làm kỳ vọng realtime tuyệt đối.

6. Permission / visibility drift

Một chi tiết đáng chú ý:

  • product_sku_stock cho cả anonymous, customer, user select,
  • product_lot_no_stock chỉ mở cho user.

Điều này cho thấy boundary public vs internal ở read model chưa hoàn toàn đồng nhất.

7. Rủi ro / Findings kỹ thuật

IDMứcFinding
SL-F01P1Nếu không tách rõ ledger và snapshot, rất dễ viết sai acceptance criteria hoặc report reconciliation.
SL-F02P1product_sku_stock không phải snapshot thấp nhất; nhiều case lot/expiry vẫn phải quay về product_lot_no_stock.
SL-F03P2Reporting MV và operational view sống song song, nên “stock hiện tại” có thể mang nghĩa khác nhau tùy màn hình/use case.
SL-F04P2product_sku_stock public hơn product_lot_no_stock, cho thấy boundary quyền đọc tồn kho chưa thuần nhất.