Skip to content

PRD: Tách và gộp check

ModuleĐơn hàng (CORE-07)PRD IDPRD-CHK-001
StatusShippedOwnerSale squad
Date2026-04-02Versionv1.0
Packages@nx/sale · @nx/core · apps/clientURDCHK · ORD

TL;DR

Cho phép một quán phục vụ tại bàn tách đơn hàng của một bàn thành nhiều check thanh toán độc lập - mỗi check có item, số lượng riêng, thậm chí một khách hàng khác - và gộp các đơn hàng riêng lẻ lại với nhau. Đơn hàng tự động hoàn tất khi tất cả check của nó đã được thanh toán, và màn hình POS lẫn màn hình bếp luôn đồng bộ qua các sự kiện real-time. Kết quả: các nhóm khách tự thanh toán phần của mình trên một hoá đơn chung mà không buộc nhân viên phải xử lý thủ công.

1. Context & Problem

Một quán phục vụ tại bàn thường xuyên phục vụ một bàn mà khách muốn thanh toán riêng - mỗi người trả cho item của mình, đôi khi dưới một hồ sơ khách hàng khác - và cũng cần gộp các đơn hàng được mở riêng cho cùng một nhóm khách. Coi đơn hàng như một đơn vị thanh toán duy nhất chặn cả hai nhu cầu: không có cách phân bổ item cụ thể giữa các nhóm thanh toán, không có cách hoàn tất đơn hàng theo từng check, và không có cách gọn gàng để gộp một đơn hàng vào đơn khác.

Increment này xây dựng aggregate SaleCheck trên nền vòng đời sale order hiện có, các service phân bổ item vào từng check và đối soát việc hoàn tất, cùng luồng gộp đơn để kết hợp hai đơn hàng nháp - lấp một khoảng trống lớn cho F&B và mọi tình huống hoá đơn nhiều khách mà KICKO hướng tới.

2. Goals & Non-Goals

Goals

  • Một aggregate SaleCheck tách một đơn hàng đã checkout thành nhiều check thanh toán độc lập.
  • Phân bổ item theo từng check - gán item và số lượng cụ thể cho mỗi check, có chặn phân bổ vượt mức.
  • Một khách hàng khác cho mỗi check, để mỗi nhóm thanh toán mang liên kết khách hàng riêng.
  • Đơn hàng tự động hoàn tất khi tất cả check của nó hoàn tất, được điều khiển bởi payment webhook.
  • Hoàn tác việc tách khi chưa có check nào được thanh toán.
  • Gộp đơn hàng cho hai đơn PROCESSING trong cùng merchant/branch.
  • Sự kiện real-time (check.created/updated/merged/rolledBack/paid, order.merged) để giữ màn hình POS và bếp đồng bộ.

Non-Goals

  • Luồng hoàn tiền / trả hàng - Non-Goal của URD (Planned).
  • Tích hợp nhà cung cấp thanh toán - chỉ nối phần bàn giao qua webhook (xem Thanh toán).
  • Engine thuế / phát hành hoá đơn điện tử theo từng check.
  • Thay đổi tồn kho khi phân bổ check (xem Kho hàng).

3. Success Metrics

MetricTarget / tín hiệu
Mức dùng táchTỷ lệ đơn phục vụ tại bàn dùng check khi có yêu cầu tách hoá đơn
Toàn vẹn phân bổKhông check nào được phân bổ vượt quá số lượng item còn lại của đơn
Độ chính xác hoàn tấtĐơn chỉ hoàn tất khi tất cả check của nó hoàn tất - không đóng sớm/muộn
An toàn hoàn tácHoàn tác thành công khi chưa check nào được thanh toán; không bao giờ sau khi một check đã trả
Độ trễ đồng bộPOS / bếp phản ánh sự kiện check & gộp theo real-time

4. Personas & Use Cases

PersonaMục tiêu trong tính năng này
Thu ngânTách hoá đơn của một bàn thành các check, phân bổ item, thu tiền theo từng check, gộp đơn
Phục vụ / Lễ tânKết hợp các đơn mở riêng cho cùng một nhóm khách
Quản lý / ChủTin rằng một đơn đóng đúng lúc mọi check đã thanh toán xong

Core scenarios: một đơn đã checkout được tách thành nhiều check → item và số lượng (và tuỳ chọn một khách hàng riêng) được phân bổ cho mỗi check → khách thanh toán check của mình → đơn hàng hoàn tất khi tất cả check hoàn tất; khi chưa có gì được thanh toán, việc tách có thể được hoàn tác, và hai đơn nháp cho cùng một nhóm khách có thể được gộp.

5. User Stories

  • Là một thu ngân, tôi muốn tách một đơn đã checkout thành nhiều check, để mỗi khách tự trả phần của mình.
  • Là một thu ngân, tôi muốn phân bổ item và số lượng cụ thể cho một check, để việc tách hoá đơn phản ánh đúng những gì mỗi khách đã dùng.
  • Là một thu ngân, tôi muốn gắn một khách hàng khác cho một check, để mỗi nhóm thanh toán giữ liên kết khách hàng riêng.
  • Là một thu ngân, tôi muốn đơn hàng tự động hoàn tất khi tất cả check đã trả, để không phải đóng đơn thủ công.
  • Là một thu ngân, tôi muốn hoàn tác việc tách khi chưa check nào được trả, để sửa một lần tách nhầm.
  • Là một phục vụ, tôi muốn gộp hai đơn cho cùng một nhóm khách, để một hoá đơn duy nhất đại diện cho cả bàn.

6. Functional Requirements

#Yêu cầuURD ref
FR-1Tách một đơn đã checkout thành nhiều check thanh toán độc lập qua aggregate SaleCheckURD-CHK-001
FR-2Phân bổ item và số lượng cụ thể cho mỗi check, có chặn phân bổ vượt mứcURD-CHK-002
FR-3Cho phép một khách hàng khác cho mỗi checkURD-CHK-003
FR-4Đơn tự động hoàn tất khi tất cả check của nó hoàn tất, điều khiển bởi payment webhookURD-CHK-004
FR-5Hoàn tác việc tách khi chưa có check nào được thanh toánURD-CHK-005
FR-6Tách một đơn thành nhiều đơn, chỉ ở DRAFTURD-ORD-012
FR-7Gộp nhiều đơn, chỉ ở DRAFT / cùng merchant/branchURD-ORD-013
FR-8Phát sự kiện real-time: check.created/updated/merged/rolledBack/paidorder.mergedURD-CHK-001..005

Toàn văn yêu cầu và tiêu chí chấp nhận nằm trong URD Đơn hàng. PRD này tham chiếu chúng thay vì lặp lại.

7. Non-Functional Requirements

Khía cạnhYêu cầu
Toàn vẹn dữ liệuPhân bổ theo từng check không bao giờ vượt số lượng còn lại của đơn; trạng thái hoàn tất là dẫn xuất, không gán tay
Nhất quánTách, phân bổ, hoàn tác và gộp là một thao tác duy nhất (transactional) - lỗi một phần không để lại check viết dở
Tenancy & authzMọi thao tác scope theo merchant (x-merchant-id); gộp giới hạn trong cùng merchant/branch; có gating theo permission
Real-timeThay đổi trạng thái check và gộp được broadcast qua sự kiện WebSocket để đồng bộ POS/KDS
Soft-deleteMọi bản ghi dùng soft-delete
i18nNhãn/trạng thái hiển thị cho người dùng là song ngữ ({ en, vi })

8. UX & Flows

Màn hình chính (trong apps/client): chi tiết đơn với thao tác tách hoá đơn, trình phân bổ theo từng check, thanh toán theo từng check, và thao tác gộp đơn.

9. Data & Domain

EntityVai trò
SaleCheckMột nhóm thanh toán độc lập trong một đơn - trạng thái, khách hàng tuỳ chọn, tổng tiền
CheckItemMột phân bổ theo check của một order item - tham chiếu item + số lượng
SaleOrderĐơn cha; hoàn tất khi tất cả check của nó hoàn tất
Sự kiện real-timeSaleCheckEvents - check.created/updated/merged/rolledBack/paid, order.merged

Chỉ ở mức khái niệm - schema đầy đủ và bất biến trong domain model của sale.

10. Dependencies & Assumptions

Phụ thuộc vào

  • Vòng đời Sale Order (URD-ORD) - một check được tách từ một đơn đã checkout; gộp thao tác trên đơn nháp/processing.
  • Thanh toán (@nx/payment) - payment webhook điều khiển việc hoàn tất check và, qua đó, hoàn tất đơn.
  • Khách hàng - liên kết khách hàng tuỳ chọn theo từng check.

Giả định

  • Đơn đã được checkout (PROCESSING) trước khi tách thành các check.
  • Sự kiện thanh toán đến qua webhook để đánh dấu một check đã trả.

11. Risks & Open Questions

Rủi ro / câu hỏiGiảm thiểu / trạng thái
Phân bổ có thể vượt số lượng còn lạiChặn phân bổ vượt mức ngay tại thời điểm phân bổ
Hoàn tác sau khi một check đã trảChỉ cho hoàn tác khi chưa check nào được trả
Tranh chấp khi nhiều check trả gần như đồng thờiHoàn tất dẫn xuất từ tất-cả-check-hoàn-tất; điều khiển bởi webhook, idempotent
Tồn kho không thay đổi theo phân bổ checkNgoài phạm vi - thuộc Kho hàng
Thuế / hoá đơn điện tử theo từng checkNgoài phạm vi - thuộc Thuế & Hóa đơn

12. Release Plan & Launch Criteria

Khía cạnhKế hoạch
PhaseP2 - xem danh mục tính năng Đơn hàng (MoSCoW: Should)
RolloutMọi merchant; không có feature flag
MigrationAggregate SaleCheck mới (schema + migration); không backfill dữ liệu
Tiêu chí ra mắtTách → phân bổ → trả-theo-từng-check → đơn tự hoàn tất được kiểm chứng đầu-cuối; hoàn tác được kiểm chứng khi chưa trả; gộp đơn được kiểm chứng cho cùng merchant/branch
Giám sátLượng tách theo merchant, tỷ lệ từ chối phân bổ vượt mức, nhất quán hoàn tất check-vs-đơn, việc giao sự kiện

13. FAQ

Tôi có thể tách một đơn trước khi checkout không? Không - một check được tách từ một đơn đã checkout (PROCESSING). Bản thân việc tách/gộp đơn chỉ ở DRAFT.

Mỗi check có thể có khách hàng riêng không? Có - có thể gắn một khách hàng khác cho mỗi check.

Khi nào đơn hoàn tất? Tự động, khi tất cả check của nó hoàn tất - điều khiển bởi payment webhook, không phải đóng thủ công.

Tôi có thể hoàn tác một lần tách không? Có, bằng cách hoàn tác - nhưng chỉ khi chưa check nào được thanh toán.

Tách hoá đơn có thay đổi tồn kho hay phát hành hoá đơn theo từng check không? Không - thay đổi tồn kho thuộc Kho hàng và phát hành thuế / hoá đơn điện tử nằm ngoài phạm vi ở đây.

References

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