ADR-0005. Lưu snapshot giá (v1 + v2) khi thanh toán vào item của đơn
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-03-20 |
| Người quyết định | Phat Nguyen |
| Thay thế cho | - |
Bối cảnh
- Quy tắc định giá trong
@nx/pricingthay đổi thường xuyên - khuyến mãi, hiệu chỉnh giá, ghi đè fare. - Hoá đơn POS phát hành phải phản ánh đúng giá tại thời điểm thanh toán - chứ không phải giá hiện hành 3 tuần sau khi kế toán đối chiếu.
- Định giá v1 trả về các điểm giá đơn giản. v2 trả về một object snapshot giàu thông tin, kèm vết áp dụng quy tắc, các mức giảm giá đã áp dụng, và chi tiết quy đổi tiền tệ.
Quyết định
Tại bước thanh toán (CheckoutService.checkout), sale gọi PricingNetworkService.calculate() (v1) VÀ calculateV2() (v2) cho các item của đơn. Cả hai kết quả được lưu trên mỗi SaleOrderItem:
unitPrice← kết quả v1 (giá bán hiển thị)priceMetadata(jsonb) ← snapshot v2 kèm vết định giá đầy đủfareId,fareProvider← tham chiếu tới quy tắc đã định giá cho dòng đó
Snapshot v2 là nguồn sự thật cho hoàn tiền, audit và khai thuế. v1 là cái khách nhìn thấy.
Hệ quả
| Ưu | Nhược |
|---|---|
| Hoá đơn bất biến sau khi thanh toán | Độ trễ gọi định giá tăng gấp đôi |
| Vết audit đầy đủ cho từng dòng | priceMetadata jsonb phình to |
| Thay đổi quy tắc không bao giờ ảnh hưởng tới đơn cũ | Service định giá phải truy cập được lúc thanh toán |
| Hoàn tiền biết chính xác mức giảm giá nào đã áp dụng | Logic hoàn tiền phải đọc snapshot v2, không gọi lại định giá |
Các phương án đã cân nhắc
| Phương án | Ưu | Nhược | Lý do từ chối |
|---|---|---|---|
Chỉ lưu unitPrice (không snapshot) | Tốn ít dung lượng hơn | Không audit được quy tắc nào đã áp dụng | Không đủ cho hoàn tiền và thuế |
| Gọi lại định giá mỗi lần đọc | Luôn "mới nhất" | Hoàn tiền phản ánh giá hiện tại, không phải giá đã trả | Sai về bản chất thiết kế |
| Chỉ lưu snapshot khi đơn hoàn tất | Tốn ít dung lượng trước khi trả tiền | Mất dữ liệu định giá nếu đơn bị huỷ trước khi hoàn tất | Thiếu sót cho audit |
Tham chiếu
sale/src/services/checkout.service.tssale/src/services/pricing-network.service.tscore/src/models/schemas/sale/sale-item/schema.ts(priceMetadata,fareId,fareProvider)