Payment — Khái niệm cốt lõi
| Khái niệm | Nghĩa |
|---|---|
| PaymentOption | Cách thanh toán được chọn/lưu trên billing hoặc checkout: PayLater, PayNow, Direct Debit, Deposit... |
| Payment method availability | Quy tắc method nào được dùng theo BU, site, category, provider và master toggle. |
| PayLater | Cho phép tạo booking/invoice nhưng để việc thu tiền xử lý sau. |
| PayNow | Thu tiền ngay qua card/checkout provider. |
| Windcave | Provider checkout/card; dùng redirect/result/webhook để cập nhật trạng thái. |
| Direct Debit | Thu tiền tự động qua customer token/batch. |
| Kiwi Direct Debit | Luồng Direct Debit/provider đặc thù, cần BU scoping và customer create/sync. |
| Deposit | Khoản trả trước một phần cho booking; không đồng nghĩa invoice đã paid full. |
| DirectPaymentBatch | Batch/provider transaction group cho nhiều direct payment hoặc deposit payment. |
| AccountPaymentCustomer | Token/customer payment profile theo account + BU + provider. |
| Zero-amount checkout | Checkout có tổng tiền phải trả = 0: bỏ qua provider, dùng Proceed/Submit rồi auto-confirm hoặc giữ pending. |
| Checkout background finalization | Popup báo hệ thống đang hoàn tất booking ở nền sau khi provider trả về thành công. |
| PayLaterDisplayName | Tên hiển thị PayLater cho consumer, cấu hình ở BU level; fallback "Pay Later". |
| Master toggle | Công tắc bật/tắt method ở BU level; trạng thái suy từ việc provider đã cấu hình. |
Payment option vs provider
PaymentOption là lựa chọn nghiệp vụ/customer thấy. Provider là hệ thống ngoài xử lý giao dịch. Ví dụ PayNow có thể dùng Windcave; Direct Debit có thể dùng Kiwi. Cấu hình availability quyết định option có được show/cho submit hay không.
Deposit không phải full payment
Deposit có thể confirm booking sau khi thu một phần tiền, nhưng billing generation vẫn có thể tạo invoice full amount. Phần settlement còn lại thuộc workflow payment/finance sau đó.
PayLater category eligibility
ProgramCategory.PayLaterAllowedTypeId là quy tắc category-scope; giá trị hợp lệ phụ thuộc loại Program Category và subsidy.
| Loại Program Category | Giá trị hợp lệ của PayLaterAllowedTypeId |
|---|---|
| Holiday / Class | None, Subsidy, SubsidyApproved, All |
| Term Care | None, FullTime, PartTime, Subsidy, SubsidyApproved, FullTimeOrSubsidy, FullTimeOrSubsidyApproved, PartTimeOrSubsidy, PartTimeOrSubsidyApproved, FullTimeAndSubsidy, FullTimeAndSubsidyApproved, PartTimeAndSubsidy, PartTimeAndSubsidyApproved, All |
- Giá trị liên quan subsidy (
Subsidy,SubsidyApproved,*OrSubsidy*,*AndSubsidy*) chỉ hợp lệ khi subsidy đã bật cho category. - Eligibility theo booking classification precedence
FULL_TIME > PART_TIME > CASUAL: có ≥1 session Full Time → tính Full Time; không FT nhưng có PT → Part Time; chỉ Casual → không thỏa FT/PT. - Variant
*Approvedyêu cầu trạng thái subsidy approved;*AndSubsidy*đòi cả hai điều kiện cùng lúc.
Ví dụ thực tế: Booking có 1 session Full Time + 3 session Casual, category để FullTimeOrSubsidyApproved. → Xác định booking có thỏa quy tắc FT không. → Tính Full Time theo precedence → Pay Later khả dụng dù không hề subsidy.
Master toggle vs category availability
- Master toggle = bật/tắt provider ở BU level (
DirectPaymentProvider,PrimaryPayNowProvider...). - Category availability = booking eligibility theo từng ProgramCategory.
- Hai tầng độc lập: đổi availability không đổi provider; đổi toggle không viết lại category option.
- Checkout chỉ hiện method khi cả hai đều pass: provider đã bật ở BU và category cho phép.
Ví dụ thực tế: BU đã cấu hình provider Direct Debit nhưng category A để Disabled. → Tránh lẫn lộn hai tầng cấu hình. → Section DD vẫn enabled trong settings, nhưng khách checkout category A không thấy Direct Debit.
Zero-amount checkout bypass
- Tổng tiền phải trả =
0→ không init/redirect provider dù chọn method nào. - Method thu tiền ngay (Pay Now, Pay Deposit, Direct Debit) dùng nút
Proceed: confirm booking, hiện confirmed success surface. - Pay Later là method duy nhất → dùng
Submit: giữ bookingSubmitted/pending, hiện pending message. Submit: đủ điều kiện auto-confirm (Pay Now full/deposit, DD sign-up, DD include-current-booking) → confirm; không đủ → giữ pending.- Intent auto-confirm resolve từ payment settings, trạng thái DD, option đã chọn, eligibility — không từ display text.
Ví dụ thực tế: Khách đã trả hết trước đó, checkout booking mới có total = 0. → Tránh redirect Windcave cho khoản 0 đồng. → Chọn Pay Now → nút Proceed → confirm ngay, không mở provider.
Checkout background finalization
- Sau khi provider trả về thành công (total payable > 0), portal hiện popup thông báo đang hoàn tất booking nền.
- Popup nhắc người dùng không rời trang/đóng trình duyệt; không yêu cầu bấm
OK. - Hoàn tất xong → popup tự đóng, về resolved success state.
Ví dụ thực tế: Khách trả thẻ 90,000 VND, Windcave redirect về portal. → Hệ thống chưa confirm xong booking. → Popup "đang xử lý, đừng đóng trình duyệt" hiện ra rồi tự biến mất khi finalization xong.
Payment method availability semantics
SubsidyEnabledlà gate:false→ không chọn option chứa "Subsidy Intended"/"Excludes Subsidy-Intended"; save vi phạm bị reject.- "Excludes Subsidy-Intended" loại booking có ý định subsidy khỏi eligibility.
- "Approved Profiles Only" không còn chọn được cho config mới; giá trị legacy vẫn đọc được, UI hiện label không-approved tương ứng.
- Checkout nhiều order/category: method chỉ hiện khi mọi order đều đủ điều kiện.
- Server không tin state ẩn của UI: submit method bị ẩn → reject trước confirm/payment.
Ví dụ thực tế: Cart có 2 order thuộc 2 category, một category để Direct Debit = All Bookings (Excludes Subsidy-Intended) và order đó subsidy-intended. → Tránh mở phương thức không hợp lệ. → Direct Debit không hiện cho cả cart vì chưa đủ mọi order đủ điều kiện.
Ownership ngắn gọn
| Owner | Sở hữu |
|---|---|
| Payment | Provider transaction, payment customer token, batch lifecycle, checkout result. |
| Finance | Invoice/billing lifecycle và chứng từ tài chính. |
| BookingOrder | Booking lock/deposit snapshot liên quan confirm booking. |
| BusinessUnit | Method/provider settings và availability scope. |