PRD: Mô phỏng định giá & xem trước giá đơn hàng
| Module | Định giá (CORE-14) | PRD ID | PRD-SIM-001 |
| Trạng thái | Shipped | Chủ sở hữu | Nhóm Định giá |
| Ngày | 2026-06-15 | Phiên bản | v1.0 |
| Packages | @nx/pricing · @nx/sale · @nx/core | URD | SIM · FARE · TAX |
TL;DR
Định giá một giỏ hàng mà không bao giờ lưu một đơn hàng. Bộ máy phơi ra hai endpoint mô phỏng không trạng thái: v1 trả về bản phân rã phẳng theo dòng + tổng đơn hàng (fare đã chọn, thuế đã áp, tổng dòng và tổng đơn); v2 trả về một ảnh chụp định giá bất biến, kiểm toán được - một ảnh chụp đơn cộng một ảnh chụp theo từng dòng - nơi mọi quyết định đã áp (giá, thuế, giảm giá, phí) được sao chép tại thời điểm tính và một sổ cái theo bên nói chính xác ai gánh khoản nào. Luồng bán hàng gọi một xem trước giá đơn hàng chỉ-đọc để cho khách thấy giá trước khi thanh toán, và lúc thanh toán nó chạy v1 (chuẩn) song song với v2 (bổ sung, best-effort) để đơn được định giá và, về sau, ảnh chụp được lưu - tất cả chia sẻ cùng logic fare và thuế lõi.
1. Bối cảnh & Vấn đề
Bộ máy fare và thuế (PRD-FARE-001) quyết định fare thắng cho từng biến thể và tính thuế lũy tiến. Nó trả lời "giá ngay bây giờ của một biến thể là gì" - nhưng luồng bán hàng cần định giá cả một giỏ hàng cùng lúc, cho khách thấy giá đó trước khi bất kỳ đơn nào được cam kết, và về sau giữ một bản ghi kiểm toán được về cách từng dòng đã được định giá.
Không có một bề mặt mô phỏng, luồng bán hàng sẽ phải gọi các nguyên thủy fare và thuế từng dòng một, tự ráp lại tổng đơn hàng, và cài lại các quy tắc thuế đã gộp/chưa gộp - và sẽ không có bản ghi quyết định định giá bất biến, tự chứa nào để đính vào đơn cho khai thuế, sổ cái và xử lý tranh chấp. Một merchant cũng không thể trưng ra con số "đây là số bạn sẽ trả" đáng tin nếu định giá chỉ được tính tại thời điểm cam kết.
Bước tăng trưởng này lấp khoảng trống đó bằng một bộ máy định giá không trạng thái ở hai hình dạng - bản phân rã v1 phẳng để hiển thị trực tiếp và ảnh chụp v2 bất biến để lưu trữ và kiểm toán - cùng xem trước chỉ-đọc mà luồng bán hàng dùng, không lưu đơn, không đổi trạng thái, không tác động lên tồn kho.
2. Mục tiêu & Phi mục tiêu
Mục tiêu
- Một bộ máy định giá giỏ hàng không trạng thái (1-100 dòng) không bao giờ lưu đơn hay chạm vào tồn kho.
- Một bản phân rã phẳng v1 - fare đã chọn, thuế đã áp và tổng theo dòng, cùng tổng đơn hàng và một mốc thời gian tính.
- Một ảnh chụp bất biến v2 - một ảnh chụp đơn cộng một ảnh chụp theo từng dòng, mang mọi quyết định đã áp tự chứa để hiển thị lịch sử sống sót qua các chỉnh sửa quy tắc sau này.
- Một sổ cái theo bên (mua / bán / nền tảng / nhà cung cấp / nhà nước) trên v2 để bên đọc tiêu thụ tổng trực tiếp thay vì tổng hợp lại.
- Một xem trước giá đơn hàng chỉ-đọc mà luồng bán hàng gọi để cho thấy giá trước khi thanh toán.
- v1 (chuẩn) và v2 (bổ sung, best-effort) được tính cùng nhau lúc thanh toán, chia sẻ một lõi fare/thuế.
Phi mục tiêu
- Lưu trữ đơn hàng, đổi trạng thái, phát hành hóa đơn hay thay đổi tồn kho - xem trước là chỉ-đọc; việc lưu nằm ở các caller bán hàng.
- Áp khuyến mãi / giảm giá trong pipeline - bộ tính giảm giá chưa được đấu nối (URD-PROMO-006); v2 chừa sẵn ô quyết định giảm giá và phí nhưng chưa điền.
- Quy đổi đa tiền tệ - một dòng mang mã tiền tệ, nhưng bộ máy không quy đổi (URD-CON).
- Bản thân các quy tắc chọn fare và tính thuế - đặc tả trong PRD-FARE-001.
3. Chỉ số Thành công
| Chỉ số | Mục tiêu / tín hiệu |
|---|---|
| Không tác động phụ | Một xem trước hay mô phỏng không bao giờ lưu đơn, đổi trạng thái hay thay đổi tồn kho |
| Toàn vẹn tổng | tổng đơn = Σ tổng dòng đúng ở độ chính xác thập phân; thuế đã gộp không bao giờ làm tăng tổng |
| Khả năng kiểm toán ảnh chụp | Mọi quyết định đã áp của v2 hiển thị đúng kể cả sau khi quy tắc nguồn bị đổi tên hay ngừng kích hoạt |
| Truy vết dòng | Mọi dòng đã định giá ánh xạ ngược về dòng yêu cầu của nó qua id do bên gọi cấp |
| Bền bỉ khi thanh toán | Một lỗi v2 không bao giờ chặn thanh toán; kết quả v1 vẫn trả về |
4. Chân dung & Tình huống
| Chân dung | Mục tiêu trong feature này |
|---|---|
| Thu ngân | Thấy một giá giỏ hàng đáng tin trước khi cam kết đơn |
| Khách hàng | Được cho thấy số sẽ trả, theo từng dòng, trước thanh toán |
| Chủ / Quản lý | Tin rằng mỗi đơn giữ một bản ghi kiểm toán được về cách nó đã định giá |
| Luồng bán hàng (hệ thống) | Định giá một đơn chỉ-đọc để xem trước, và định giá + ảnh chụp nó lúc thanh toán |
Tình huống lõi: một thu ngân dựng một giỏ ba dòng; luồng bán hàng gọi xem trước giá đơn hàng, vốn định giá lại đơn đang có theo kiểu chỉ-đọc và trả về bản phân rã v1 - fare, thuế và tổng theo dòng cùng tổng đơn - không lưu gì. Lúc thanh toán luồng bán hàng định giá cùng đơn đó với v1 (chuẩn) và v2 (best-effort); ảnh chụp v2 - đơn cộng theo dòng, mỗi dòng mang giá, thuế và một sổ cái theo bên - sẵn sàng để lưu trên đơn. Nếu một dòng có biến thể không có fare set kích hoạt, lỗi từ chối thật từ thượng nguồn được phơi ra thay vì một lỗi chung chung.
5. User Story
- Là một thu ngân, tôi định giá cả giỏ trong một lệnh và nhận tổng theo dòng và theo đơn, để không bao giờ phải tự ráp tổng.
- Là một khách hàng, tôi được cho thấy số sẽ trả trước khi cam kết, để không bất ngờ lúc thanh toán.
- Là một chủ cửa hàng, tôi muốn mỗi đơn giữ một bản ghi tự chứa về cách từng dòng đã định giá, để bảo vệ con số lâu sau khi quy tắc đã đổi.
- Là một chủ cửa hàng, tôi muốn một bản phân rã theo bên về ai gánh khoản nào, để các phép đọc thuế và sổ cái không cần tính lại.
- Là luồng bán hàng, tôi muốn xem trước là chỉ-đọc, để việc trưng giá không bao giờ thay đổi đơn.
- Là luồng bán hàng, tôi muốn một lỗi v2 không bao giờ chặn thanh toán, để một khoảng trống ảnh chụp suy giảm êm về con số v1.
6. Yêu cầu Chức năng
| # | Yêu cầu | URD ref |
|---|---|---|
| FR-1 | Định giá giỏ không trạng thái 1-100 dòng, không lưu đơn và không thay đổi tồn kho | URD-SIM-001 |
| FR-2 | Bản phân rã phẳng v1: giá gốc/đơn vị theo dòng, fare đã chọn + quy tắc đã áp, thuế đã áp, subtotal/discount/tax/total; cùng tổng đơn và một mốc thời gian tính; thuế đã gộp và chưa gộp xử lý đúng | URD-SIM-002 · URD-SIM-004 |
| FR-3 | Một id dòng do bên gọi cấp được trả lại và dùng làm khóa kết quả để ánh xạ rõ ràng | URD-SIM-003 |
| FR-4 | Ảnh chụp bất biến v2 - một ảnh chụp đơn cộng một ảnh chụp theo từng dòng, mang mọi quyết định đã áp (giá, thuế, giảm giá, phí) sao chép tại thời điểm tính | URD-SIM-005 · URD-SIM-006 |
| FR-5 | Tổng v2: buyer-payable + sổ cái theo bên theo dòng; tổng đơn cuộn lên subtotal, buyer-payable, sổ cái theo bên, và seller liability | URD-SIM-007 |
| FR-6 | Một mô phỏng v2 khai báo một hướng giao dịch (SALE / PURCHASE) và một tiền tệ đơn (ISO 4217, mặc định VND) | URD-SIM-008 |
| FR-7 | Một xem trước giá đơn hàng chỉ-đọc định giá lại đơn đang có và trả về bản phân rã v1; định giá một giỏ rỗng bị từ chối | URD-SIM-009 · URD-SIM-010 |
| FR-8 | Lúc thanh toán đơn được định giá với v1 (chuẩn) + v2 (bổ sung, best-effort, không chặn); thuế theo dòng được lưu trộn mục VAT của v1 với mục PIT của v2 | URD-SIM-011 · URD-SIM-012 |
| FR-9 | Ngữ cảnh định giá mỗi dòng mang số lượng, thời điểm tính, ngày/giờ/thứ, các id biến thể của giỏ (quy tắc đồng xuất hiện), và một khung dịch vụ suy ra, để quy tắc fare đánh giá | URD-SIM-013 |
| FR-10 | Một từ chối thượng nguồn (vd: không có fare set kích hoạt) phơi ra với trạng thái/lý do thật; cả hai endpoint được xác thực + giới hạn theo merchant + chính xác thập phân; v1 và v2 chia sẻ logic fare/thuế lõi | URD-SIM-014 · URD-SIM-015 · URD-SIM-016 |
Toàn văn yêu cầu và tiêu chí chấp nhận nằm trong URD Định giá - SIM. PRD này tham chiếu thay vì lặp lại. Các quy tắc chọn fare và tính thuế được đặc tả trong PRD-FARE-001.
7. Yêu cầu Phi chức năng
| Lĩnh vực | Yêu cầu |
|---|---|
| Không trạng thái | Mô phỏng và xem trước là phép đọc thuần - không lưu đơn, đổi trạng thái, hay tác động tồn kho |
| Bất biến | Một ảnh chụp v2 bất biến sau khi đã tính (URD-CON-004); chỉnh sửa tính lại một ảnh chụp mới, không bao giờ sửa cái cũ |
| Tự chứa | Mỗi quyết định đã áp của v2 sao chép nhãn, cơ sở, giá trị và khoản tại thời điểm tính, để hiển thị đúng kể cả sau khi quy tắc nguồn đổi |
| Bền bỉ | v2 là bổ sung lúc thanh toán - lỗi của nó được log và bỏ qua, không bao giờ chặn kết quả v1 chuẩn |
| Đa thuê & phân quyền | Cả hai endpoint yêu cầu xác thực và phạm vi merchant (x-merchant-id); kiểm soát bởi quyền mô phỏng định giá |
| Độ chính xác | Mọi phép tính định giá dùng độ chính xác thập phân (float(value, 4)); thuế đã gộp không bao giờ làm tăng tổng |
| Lõi chung | v1 (/simulation) và v2 (/simulation-v2) chia sẻ cùng logic fare/thuế lõi, nên một bản sửa đáp ở cả hai (C-06) |
| i18n | Nhãn fare và thuế hướng người dùng là song ngữ ({ en, vi }) |
8. UX & Luồng
Bề mặt chính: xem trước giá hướng khách trong client bán hàng (tổng theo dòng và theo đơn), và - sau thanh toán - ảnh chụp v2 đính vào đơn và các dòng của nó cho kiểm toán, khai thuế, và đọc sổ cái.
9. Dữ liệu & Miền
| Khái niệm | Vai trò |
|---|---|
OrderPricingSnapshot | Ảnh chụp cấp đơn: hướng, tiền tệ, các quyết định phạm vi đơn, và tổng cuộn lên (subtotal, buyer-payable, sổ cái theo bên, seller liability) |
LineItemPricingSnapshot | Ảnh chụp một dòng: số lượng, ngữ cảnh đã trộn, các quyết định đã áp của nó, và tổng (buyer-payable + sổ cái theo bên) |
AppliedDecision | Một mục PRICE / TAX / DISCOUNT / FEE tự chứa - nhãn, cơ sở, giá trị, khoản, bên gánh, tính đã-gộp, ưu tiên, lũy tiến - sao chép tại thời điểm tính |
| Bản phân rã v1 | Kết quả phẳng theo dòng (fare, thuế, tổng) + tổng đơn, khóa theo id dòng do bên gọi cấp |
Chỉ mang tính khái niệm - schema ảnh chụp đầy đủ và các bất biến nằm trong mô hình miền định giá. Ảnh chụp được thiết kế để được lưu trên đơn và các dòng của nó bởi các caller bán hàng.
10. Phụ thuộc & Giả định
Phụ thuộc vào
- Bộ máy fare & thuế (PRD-FARE-001, URD-FARE · URD-TAX) - mô phỏng dẫn dắt chọn fare và tính thuế; cả hai phiên bản chia sẻ lõi đó.
- Đơn hàng (Đơn hàng) - xem trước định giá lại một đơn đang có; thanh toán lưu ảnh chụp.
@nx/core- độ chính xác tiền chung, hình dạng ảnh chụp thuế, và giới hạn theo merchant.
Giả định
- Mỗi biến thể được định giá có một fare set kích hoạt (tự khởi tạo khi tạo biến thể); thiếu fare set là một từ chối thượng nguồn, được phơi ra như vậy.
- Bộ tính giảm giá / khuyến mãi chưa được đấu nối (URD-PROMO-006); v2 chừa sẵn nhưng chưa điền quyết định giảm giá và phí.
- Các caller bán hàng sở hữu mọi việc lưu và đổi trạng thái; bộ máy định giá giữ không trạng thái.
11. Rủi ro & Câu hỏi mở
| Rủi ro / câu hỏi | Giảm thiểu / trạng thái |
|---|---|
| Một ảnh chụp có thể lệch khỏi quy tắc nó trích nếu quy tắc đổi sau này | Mỗi quyết định đã áp sao chép nhãn/cơ sở/giá trị/khoản tại thời điểm - ảnh chụp tự chứa |
| Lỗi v2 có thể chặn thanh toán | v2 là bổ sung và best-effort - lỗi được log và bỏ qua; kết quả v1 chuẩn vẫn trả về |
| Thuế đã gộp bị tính sai vào tổng | Thuế đã gộp được tính ngược và không bao giờ làm tăng tổng (C-03) |
| Lẫn lộn dòng khi ánh xạ kết quả ngược về | Id dòng do bên gọi cấp được trả lại và dùng làm khóa kết quả |
| Một biến thể không có fare set kích hoạt lỗi mờ ám | Trạng thái/lý do thật từ thượng nguồn được lan truyền thay vì một lỗi 500 chung chung |
12. Kế hoạch Phát hành & Tiêu chí Ra mắt
| Khía cạnh | Kế hoạch |
|---|---|
| Phase | P2 - SIM trong danh mục feature URD, bên cạnh COST |
| Triển khai | Mọi merchant; không cờ tính năng |
| Di trú | Không - mô phỏng và xem trước là phép đọc không trạng thái trên bộ máy fare/thuế đang có |
| Tiêu chí ra mắt | v1 trả về tổng theo dòng + theo đơn với thuế đã gộp/chưa gộp đúng; v2 trả về một ảnh chụp đơn + theo dòng bất biến với sổ cái theo bên; xem trước là chỉ-đọc và từ chối giỏ rỗng; thanh toán định giá v1 + v2 với v2 không bao giờ chặn; từ chối thượng nguồn phơi ra trạng thái thật |
| Giám sát | Độ trễ và tỉ lệ lỗi mô phỏng theo phiên bản, tỉ lệ lỗi best-effort của v2 lúc thanh toán, số lần từ chối thượng nguồn (vd: thiếu fare set) |
13. FAQ
Xem trước một giá có thay đổi đơn không? Không - xem trước là một phép đọc thuần. Nó định giá lại một đơn đang có và trả về bản phân rã v1 mà không lưu gì, đổi trạng thái, hay chạm tồn kho.
Khác biệt giữa v1 và v2 là gì? v1 là bản phân rã phẳng để hiển thị trực tiếp - fare, thuế và tổng theo dòng cùng tổng đơn. v2 là một ảnh chụp bất biến, kiểm toán được - một ảnh chụp đơn cộng một ảnh chụp theo từng dòng, với mọi quyết định tự chứa và một sổ cái theo bên - nhằm được lưu trên đơn.
Vì sao chạy cả hai lúc thanh toán? v1 là chuẩn và luôn bắt buộc; v2 là bổ sung và best-effort. Tính chúng cùng nhau cho phép đơn được định giá từ v1 trong khi ảnh chụp v2 được nắm bắt cho kiểm toán - và một lỗi v2 không bao giờ chặn việc bán.
Một ảnh chụp có còn đọc đúng nếu tôi đổi tên một thuế sau này? Có - mỗi quyết định đã áp sao chép nhãn, cơ sở, giá trị và khoản của nó tại thời điểm tính, nên hiển thị lịch sử không bị ảnh hưởng bởi chỉnh sửa quy tắc sau này.
Khuyến mãi có được áp ở đây không? Chưa - bộ tính giảm giá chưa được đấu nối vào pipeline (URD-PROMO-006). v2 chừa sẵn ô quyết định giảm giá và phí cho khi nó được đấu nối.
Tham chiếu
- URD: Định giá - SIM · FARE · TAX
- PRD cùng nhóm: Bộ máy định giá Fare & Thuế · Khuyến mãi, phương thức & quy tắc phân khúc
- Module: Định giá - tổng quan + năng lực
- Kỹ thuật: @nx/pricing · mô hình miền
- Bên tiêu thụ: Đơn hàng / Bán hàng