Skip to content

ADR-0003. Bộ phân biệt type của product variant + quan hệ ProductBundler

TrườngGiá trị
StatusAccepted
Ngày2026-04-10
Người quyết địnhcommerce-team, inventory-team
Thay thế

Bối cảnh

  • Catalog phải biểu diễn nhiều hành vi: hàng vật lý có tồn kho, hàng tiêu hao không lưu kho, dịch vụ, kit/hàng sản xuất (bill-of-materials), combo ảo, addon miễn phí, và gợi ý "thường được mua cùng nhau".
  • Một mô hình trước đó nạp chồng Category.type (COMBO/ADDON/FBT) để điều khiển hành vi tồn kho và bán. Điều này dễ vỡ: re-categorize một sản phẩm có thể lật nó giữa vật lý và ảo, và category về cơ bản là mối quan tâm nhóm FE.
  • Inventory và sale cần một tín hiệu cấu trúc đơn, ổn định cho "cái này có lưu kho không?" và "nó có nổ tung thành thành phần khi bán không?".

Quyết định

Tách mối quan tâm thành một bộ phân biệt cấu trúc theo từng variant và một bảng quan hệ riêng:

  1. ProductVariant.type (ProductVariantTypes, core/.../public/product-variant/constants.ts) là bộ phân biệt cấu trúc duy nhất:
    • STORABLE (mặc định) / MANUFACTURED → lưu kho (STOCKABLE_SET).
    • CONSUMABLE / SERVICE → không lưu kho.
    • KIT / COMBO / MANUFACTURED → có BOM (BOMABLE_SET).
    • COMBO là ảo — không có InventoryItem; nó nổ tung khi thêm vào giỏ thành các variant thành phần.
  2. ProductBundler là bảng quan hệ đơn cho COMBO / ADDON / FBT (ProductBundlerTypes), khóa theo (type, leadVariantId, relatedVariantId). ADDON và FBT là quan hệ, không phải variant type — một addon variant là một PV vật lý thông thường; hàng quan hệ làm nó thành addon.
  3. Category.type trở thành nhãn nhóm FE thuần túy — không có gì trong inventory/sale rẽ nhánh theo nó.

Việc nổ combo khi thêm vào giỏ được triển khai trong @nx/sale / @nx/inventory — xem ADR cross-package.

Hệ quả

ƯuNhược
Tín hiệu cấu trúc ổn định độc lập với phân loạiHai khái niệm (variant type + bundler type) — không được gộp lẫn
Re-categorize một sản phẩm an toàn (không thể lật vật lý↔ảo)Cần migration để backfill type từ dữ liệu dựa-trên-category cũ
Một bảng quan hệ bao quát gọn COMBO/ADDON/FBT với basis giá tùy chọnTính có hướng FBT yêu cầu một hàng cho mỗi hướng
Inventory seed item chỉ cho variant STOCKABLE_SETConsumer phải đọc helper ProductVariantTypes, không phải category

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

Tùy chọnƯuNhượcVì sao bị từ chối
Giữ Category.type làm bộ phân biệtKhông đổi schemaDễ vỡ; re-categorize lật hành vi; gộp nhóm với cấu trúcNguyên nhân gốc của bug đang được sửa
Bảng riêng cho mỗi quan hệ (combo/addon/FBT)Tường minhBa bảng gần như giống nhau; logic trùng lặpMột ProductBundler với type đơn giản hơn
Cờ boolean trên ProductVariant (isCombo, isKit…)Đơn giảnCờ loại trừ lẫn nhau mô hình hóa enum hữu hạn kémMột enum type có kiểu đơn là đúng theo code style

Tham khảo

  • packages/core/src/models/schemas/public/product-variant/constants.ts (ProductVariantTypes, STOCKABLE_SET, BOMABLE_SET)
  • packages/core/src/models/schemas/public/product-bundler/{schema,constants}.ts
  • Cross-package: developer/packages/inventory/decisions/0006-combo-explosion-at-cart-add

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