Products
Đào sâu tính năng. Định danh dịch vụ, component và bề mặt async nằm trong Tổng quan Commerce và API Events.
Products là thực thể catalog cốt lõi. Mỗi product có ProductInfo liên quan (name/description đa ngôn ngữ), các bản ghi ProductIdentifier, và kết nối tới sale channels qua SaleChannelProduct.
Tổng quan
| Thuộc tính | Giá trị |
|---|---|
| Thực thể | Product, ProductInfo, ProductIdentifier, SaleChannelProduct, ProductVariant mặc định |
| Base path | /products (live spec: /v1/api/commerce/doc/openapi.json) |
| Aggregate | tạo/cập nhật product + con trong một transaction |
| Async | EventBus product.aggregate.{created,updated} → đồng bộ đa merchant tùy chọn; CDC public.Product → search/taxation |
Mô hình thực thể
Xem Domain Model §3.1. Bảng trường được duy trì ở đó; trang này bao quát thao tác.
REST Endpoints
Tham khảo đầy đủ: OpenAPI trực tiếp tại
/v1/api/commerce/doc/openapi.json. Các route tùy biến đáng lưu ý:
| Method | Path | Mục đích |
|---|---|---|
POST | /products/aggregate | Tạo product + ProductInfo + identifiers + liên kết sale channel + variant mặc định trong một transaction |
PATCH | /products/{id}/aggregate | Cập nhật product + ProductInfo + liên kết sale channel một cách atomic |
Phân giải identifier
GET /products/{id} phân giải tham số {id} bằng cách:
- Khớp ID trực tiếp
- Khớp trường
slug
Điều này được xử lý bởi ProductService.findByIdentifier().
Truy cập theo phạm vi merchant
Với người dùng không phải admin, find() và count() lọc sản phẩm theo các merchant ID mà người dùng có quyền truy cập (qua chính sách Casbin PolicyDefinitionRepository). Người dùng admin/super-admin thấy tất cả sản phẩm.
ProductService
File: src/services/product.service.ts
Methods
| Method | Mục đích |
|---|---|
findByIdentifier({ identifier, filter?, transaction? }) | Phân giải theo ID hoặc slug |
updateById({ id, data, transaction? }) | Cập nhật có hỗ trợ transaction |
batchCreate({ data }) | Insert hàng loạt sản phẩm |
createAggregate({ data, transaction? }) | Tạo product + info + identifiers + sale channels + variant mặc định |
updateAggregate({ id, data, transaction? }) | Cập nhật product + info + sale channels |
Request createAggregate()
{
// các trường ProductInsertSchema
name: string;
status?: string; // mặc định: 'activated'
categoryId?: string;
merchantId: string;
taxGroupId?: string;
// ... các trường product khác
// riêng cho aggregate
info: ProductInfoInsertSchema; // bắt buộc — name/description đa ngôn ngữ
saleChannelIds?: string[]; // tùy chọn — liên kết tới sale channels
slug?: string; // tùy chọn — tự sinh nếu bỏ qua
}Nó làm gì:
- Tạo hàng
Product - Tạo
ProductInfo(name, description trong{ en, vi }) - Tạo một
ProductIdentifiervới schemeSYSTEM - Tạo các hàng
SaleChannelProductcho mỗi sale channel ID - Tạo một
ProductVariantmặc định qua đường sync variant - Sau khi commit, phát
product.aggregate.createdtrên EventBus in-process (đánh dấu bước onboarding merchantPRODUCT; đưa sync đa merchant vào hàng đợi nếu cómerchantIds[])
Request updateAggregate()
{
// các trường ProductUpdateSchema (partial)
info?: ProductInfoUpdateSchema;
saleChannelIds?: string[];
}Sau khi commit, phát product.aggregate.updated trên EventBus in-process (đưa sync đa merchant vào hàng đợi nếu áp dụng). Lan truyền downstream tới search/taxation xảy ra qua CDC trên public.Product, không phải emit Kafka cấp ứng dụng — xem API Events.
Chuyển trạng thái
ACTIVATED ←→ DEACTIVATED
↓ ↓
ARCHIVED ARCHIVED| Từ | Đích cho phép |
|---|---|
activated | deactivated, archived |
deactivated | activated, archived |
archived | (không — trạng thái cuối) |
Sản phẩm đã archive không thể sửa qua updateById().
Xóa
Xóa sản phẩm được xử lý bởi DeletionPolicyService.deleteProductById():
- Nếu sản phẩm có lịch sử bán (orders), xóa bị chặn (HTTP 400) — archive thay vì xóa
- Nếu sản phẩm có variant và
cascadeProductDeletionlàfalsetrong chính sách xóa của merchant → HTTP 400 - Nếu
cascadeProductDeletionlàtrue, variant được xóa trước (chịu ràng buộc riêng của chúng)
Sự kiện
| Kênh | Tín hiệu | Khi nào | Consumer |
|---|---|---|---|
| EventBus (in-process) | product.aggregate.created / .updated | sau commit aggregate | đánh dấu bước onboarding + đưa sync đa merchant vào hàng đợi |
| CDC (Debezium) | public.Product, public.ProductInfo | khi ghi hàng | Search (index), Taxation (cấp phát nhóm thuế) |
Commerce không emit cấp ứng dụng các topic Kafka
product.created/product.updated— component Kafka chỉ producer và không dùng cho những thứ này. Xem API Events.
Trang liên quan
| Trang | Mô tả |
|---|---|
| Tổng quan Commerce | Định danh dịch vụ + catalog |
| Domain Model | Bảng trường Product + bất biến |
| API Events | Bề mặt CDC + EventBus + BullMQ |
| Variants | Quản lý product variant |
| Categories | Phân cấp category |
| Sale Channels | Phân phối kênh |