ADR-0001. Một thực thể SaleOrder duy nhất cho cart và order đã commit
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-01-10 |
| Người quyết định | sale-team |
| Thay thế | — |
Bối cảnh
- Workflow POS coi "cart" và "order" như cùng một thực thể được commit dần: barista xây bản nháp, nhấn checkout, rồi thanh toán.
- Tách thành hai thực thể (Cart + Order) yêu cầu copy state khi checkout, làm phức tạp merge/split, và nhân đôi số rooms WebSocket phải quản lý.
- Cần một nguồn sự thật duy nhất cho thứ user đang làm việc, với một vòng đời rõ ràng.
Quyết định
Dùng một thực thể SaleOrder duy nhất với trường status. DRAFT = cart (item có thể đổi). PROCESSING / PARTIAL / COMPLETED = đã commit. CANCELLED = terminal.
Các transition trạng thái được kiểm soát bởi canModifyItems() (chỉ DRAFT), canCheckout() (chỉ DRAFT), canRevertToCart() (chỉ PROCESSING), canCancel() (bất kỳ active).
Hệ quả
| Ưu | Nhược |
|---|---|
| Một thực thể = một nguồn sự thật | Status enum mã hóa logic state-machine — dễ sai khớp |
| Merge / split hoạt động đồng nhất qua các status | Truy vấn DB muốn "chỉ orders" phải lọc status != DRAFT |
| WebSocket subscriber thấy một vòng đời thực thể | Báo cáo audit phải cẩn thận với draft đã hủy |
| UI mobile/POS không cần copy state | Add-item đồng thời cần lock rõ ràng (ADR-0002) |
Phương án thay thế đã cân nhắc
| Phương án | Ưu | Nhược | Lý do từ chối |
|---|---|---|---|
Tách Cart + Order thành thực thể riêng | Mỗi thực thể có schema sạch hơn | Copy khi checkout; nhân đôi rooms WS; logic merge/split nhân đôi | Chi phí triển khai vượt trội so với độ sạch của schema |
SaleOrder + view Cart | View DRAFT vật chất hóa | Phức tạp view; vẫn vấn đề lock | Lợi ích không đáng kể |
Tham chiếu
core/src/models/schemas/sale/sale-order/schema.tssale/src/services/sale.service.ts:createDraftOrdercore/src/models/schemas/sale/sale-order/constants.ts:SaleOrderStatuses