Skip to content

ADR-0002. Liên kết Vendor chỉ qua VendorItem — không có vendorId trên principal

TrườngGiá trị
StatusAccepted
Date2026-03-20
Decidersinventory-team, PM
Supersedes

Bối cảnh

  • Một Material (hoặc ProductVariant) có thể được nhiều vendor cung cấp với giá và UoM khác nhau.
  • Một vendor cung cấp nhiều item.
  • Quan hệ thực tế là M:N với các thuộc tính không tầm thường (price, UoM, multiplier, isPreferred, snapshot lastInvoiced).
  • Phản xạ ban đầu: thêm cột vendorId vào Material ("vendor ưu tiên"). Đã bị từ chối.

Quyết định

Liên kết Vendor↔principal chỉ tồn tại trong bảng nối VendorItem. MaterialProductVariant không có cột vendorId. Để biểu diễn "vendor ưu tiên" cho một item, set VendorItem.isPreferred = true (flip atomic qua setPreferredAtomic, partial unique theo (merchantId, itemType, itemId)).

Hệ quả

ProsCons
Một nguồn-sự-thật duy nhất cho quan hệ vendorTruy vấn "vendor ưu tiên cho material X" cần JOIN
Tự nhiên hỗ trợ M:N: cùng material từ 3 vendor với giá khác nhauCho phép "Material không có vendor ưu tiên" (không có ràng buộc NOT NULL)
Snapshot lastInvoiced thuộc phạm vi VendorItem (một lịch sử cho mỗi cặp vendor-item)Cần helper flip atomic (setPreferredAtomic)
recordPurchase cập nhật một row, không phải cột MaterialUI phải hiển thị "vendor selector" thay vì hardcode

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

Phương ánProsConsLý do từ chối
Material.vendorId (đơn)Đọc đơn giản không cần JOINKhông mô hình hóa được M:N; "vendor phụ" vẫn cần cấu trúc song songKhông khớp với thực tế procurement
Material.preferredVendorId + bảng VendorItemLookup nhanhHai nguồn-sự-thật, đồng bộ trôi không tránh khỏiAnti-pattern
Vendor.itemIds[] jsonbĐọc một-rowKhông có constraint, không query được theo itemTệ hơn không quyết định

Tham chiếu

  • core/src/models/schemas/inventory/vendor-item/schema.ts
  • inventory/src/services/vendor-item.service.tssetPreferred, recordPurchase
  • Memory: feedback_vendor_via_vendoritem_only.md

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