Skip to content

PRD: Ví, voucher & sổ cái

ModuleThanh toán & Giao dịch (CORE-08)PRD IDPRD-WAL-001
StatusShippedOwnerPayment & Finance squad
Date2026-05-28Versionv1.0
Packages@nx/finance · @nx/payment · @nx/ledgerURDWAL · VCH · CAT

TL;DR

Cung cấp cho merchant một nơi để ghi nhận dòng tiền đằng sau mỗi khoản thanh toán: các tài khoản (ví) nơi số dư tiền mặt, ngân hàng, QR và mobile POS được giữ, các voucher ghi sổ kép cân bằng cho mọi chuyển động, và auto-posting ghi sổ các giao dịch bán hàng hoàn tất, đơn mua hàng đã nhận, và chuyển động kho - mỗi sự kiện đúng một lần. Kết quả: chủ có thể thấy số dư thực và đối chiếu sổ sách, thay vì chỉ biết một khoản thanh toán đã được đánh dấu paid.

1. Context & Problem

KICKO có thể chuyển một khoản thanh toán sang trạng thái paid, nhưng không có nơi nào để ghi nhận dòng tiền phát sinh. Không có nơi để số dư tiền mặt, ngân hàng hay QR được giữ, không có ghi sổ kép, và không có cách phân loại thu và chi - nên một merchant có thể thu tiền nhưng không thể thấy số dư hay đối chiếu sổ sách. Việc theo dõi chi phí và khả năng nhìn thấy tài chính ở cấp chủ bị chặn, đây là yêu cầu bắt buộc cho nghiệp vụ kế toán HKD/SME mà KICKO hướng tới.

Tính năng này xây dựng phần tài chính trên nền vòng đời thanh toán hiện có: các tài khoản nơi tiền được giữ, voucher cân bằng cho mọi chuyển động, danh mục thu/chi được seed sẵn, và auto-posting kết nối các sự kiện bán hàng, mua hàng và kho vào sổ cái. "Account" là thuật ngữ chuẩn cho nơi tiền được giữ, thay thế tên gọi "wallet" trước đây.

2. Goals & Non-Goals

Goals

  • Tài khoản tài chính loại CASH, BANK, QR code và mobile POS, mỗi tài khoản có số dư đầu kỳ và số dư hiện tại, các tài khoản kiểm soát nội bộ được duy trì tự động, và một tài khoản mặc định cho mỗi merchant nhận thu nhập bán hàng được auto-post.
  • Voucher ghi sổ kép cân bằng ở bốn loại - RECEIPT, PAYMENT, TRANSFER, ADJUSTMENT - với vòng đời DRAFT → ISSUED → VOIDED, đánh số theo từng merchant/từng loại, và hủy-bằng-bút-toán-đảo (không xóa cứng).
  • Auto-posting từ sự kiện nghiệp vụ: một khoản thanh toán bán hàng hoàn tất post một RECEIPT, một đơn mua hàng đã nhận post một PAYMENT, và một lần xuất/điều chỉnh kho post voucher tương ứng - mỗi cái idempotent theo source event id.
  • Phân loại danh mục thu/chi: 14 danh mục hệ thống được seed sẵn (được bảo vệ, gắn loại INCOME hoặc EXPENSE) cùng các danh mục tùy chỉnh riêng từng merchant với phân cấp cha.

Non-Goals

  • Hoàn tiền / đảo giao dịch có cấu trúc qua lại nhà cung cấp thanh toán gốc (URD §7 - Planned).
  • Bảng đối chiếu tiền mặt theo ca (URD §7 - Planned).
  • Quy đổi đa tiền tệ và đối chiếu liên tiền tệ.
  • Phát hành hóa đơn thuế - thuộc module Thuế & Hóa đơn.

3. Success Metrics

MetricTarget / signal
Độ phủ sổ cái100% khoản thanh toán bán hàng hoàn tất, PO đã nhận, và chuyển động kho đều post voucher tương ứng
Tính toàn vẹn số dưMọi voucher đều cân bằng (tổng DEBIT = tổng CREDIT); không có bút toán mất cân bằng
IdempotencyMỗi source event post tối đa một voucher, kể cả khi gửi lại - không có trùng lặp
Đối chiếuChủ có thể đọc số dư tài khoản trực tiếp khớp với tổng các dòng sổ cái đã post

4. Personas & Use Cases

PersonaMục tiêu trong tính năng này
Chủ (Owner)Thấy số dư thực, phân loại thu/chi, đối chiếu sổ sách, hủy bút toán sai
Quản lý (Manager)Quản lý tài khoản, tạo voucher thủ công, xem sổ cái
Thu ngân (Cashier)Thu tiền để auto-post thu nhập (không truy cập sổ cái)

Core scenarios: chủ tạo các tài khoản nơi tiền được giữ → một khoản thanh toán bán hàng hoàn tất auto-post một RECEIPT cân bằng vào tài khoản mặc định → một PO đã nhận hoặc chuyển động kho auto-post voucher tương ứng một lần → chủ xem sổ cái, phân loại bút toán theo danh mục, và hủy bất kỳ sai sót nào qua một bút toán đảo cân bằng.

5. User Stories

  • Là một chủ, tôi muốn tạo các tài khoản loại tiền mặt, ngân hàng, QR và mobile POS với số dư đầu kỳ, để tiền có nơi để giữ và tôi thấy được số dư hiện tại.
  • Là một chủ, tôi muốn một khoản thanh toán bán hàng hoàn tất auto-post một RECEIPT cân bằng vào tài khoản mặc định của tôi, để thu nhập xuất hiện trong sổ cái mà không cần nhập tay.
  • Là một chủ, tôi muốn một đơn mua hàng đã nhận và một lần xuất/điều chỉnh kho auto-post voucher tương ứng đúng một lần, để chi phí và chuyển động kho tự đối chiếu.
  • Là một chủ, tôi muốn tạo một voucher thủ công (draft → issue) và hủy bằng bút toán đảo, để chỉnh sửa sổ sách mà không bao giờ xóa lịch sử tài chính.
  • Là một chủ, tôi muốn thu và chi được phân loại theo danh mục, với danh mục tùy chỉnh nằm dưới một danh mục cha, để báo cáo tiền đến từ đâu và đi về đâu.
  • Là một quản lý, tôi muốn chỉ thấy các tài khoản của những merchant mà tôi được grant quyền truy cập, để tầm nhìn tôn trọng scope của tôi.

6. Functional Requirements

#RequirementURD ref
FR-1Tạo tài khoản loại CASH, BANK, QR code, mobile POS; mỗi tài khoản theo dõi số dư đầu kỳ và số dư hiện tạiURD-WAL-001 · URD-WAL-003
FR-2Duy trì tài khoản kiểm soát nội bộ (ví dụ kho, COGS) tự độngURD-WAL-002
FR-3Một tài khoản mặc định cho mỗi merchant nhận thu nhập bán hàng được auto-postURD-WAL-004
FR-4Các role không phải chủ chỉ thấy tài khoản của những merchant mà họ được grant quyềnURD-WAL-005
FR-5Mọi voucher đều cân bằng (tổng DEBIT = tổng CREDIT) ở bốn loại RECEIPT / PAYMENT / TRANSFER / ADJUSTMENTURD-VCH-001..002
FR-6Một khoản thanh toán bán hàng hoàn tất auto-post một RECEIPT vào tài khoản mặc định; một PO đã nhận auto-post một PAYMENT; một lần xuất/điều chỉnh kho auto-post voucher tương ứngURD-VCH-003..005
FR-7Mỗi voucher ghi lại source event của nó để cùng một sự kiện chỉ post một lần (idempotent)URD-VCH-006
FR-8Voucher được đánh số theo từng merchant và từng loại (ví dụ PT / PC / PCK / PKT)URD-VCH-007
FR-9Chủ có thể tạo voucher thủ công (draft → issue) và hủy qua bút toán đảo cân bằng (không xóa cứng)URD-VCH-008..009
FR-10Một lần chuyển tiền giữa hai tài khoản được ghi nhận là voucher tổng-bằng-khôngURD-VCH-010
FR-1114 danh mục hệ thống được seed sẵn, được bảo vệ, gắn loại INCOME hoặc EXPENSE; chủ có thể thêm danh mục tùy chỉnh với phân cấp chaURD-CAT-001..003

Toàn văn requirement và tiêu chí chấp nhận nằm trong URD Thanh toán & Giao dịch. PRD này tham chiếu thay vì viết lại.

7. Non-Functional Requirements

AreaRequirement
Toàn vẹn dữ liệuMọi voucher phải cân bằng (tổng DEBIT = tổng CREDIT); số dư hiện tại của tài khoản luôn bằng tổng các dòng sổ cái đã post của nó
IdempotencyMỗi sự kiện nghiệp vụ post tối đa một voucher, khóa theo source event id; gửi lại không có hiệu ứng lần hai
Bất biếnKhông xóa cứng lịch sử tài chính - chỉnh sửa thực hiện qua voucher bút toán đảo cân bằng
Tenancy & authzMọi tài khoản, voucher và danh mục đều scoped theo merchant (x-merchant-id); tầm nhìn của role không phải chủ giới hạn ở các merchant được grant
Độ chính xácTính toán tiền tệ dùng float(value, 4)
i18nNhãn/loại/trạng thái hiển thị cho người dùng là song ngữ ({ en, vi })

8. UX & Flows

Các màn hình chính (trong apps/client): danh sách và tạo tài khoản, màn hình voucher (bảng giao dịch chỉnh sửa được, phần party/transaction, banner hủy, tổng quan), và tổng quan sổ cái với số dư và lịch sử voucher.

9. Data & Domain

EntityVai trò
FinanceAccountNơi tiền được giữ - loại CASH / BANK / QR_CODE / MOBILE_POS, số dư đầu kỳ + hiện tại; bao gồm tài khoản kiểm soát nội bộ
FinanceVoucherMột bút toán cân bằng thuộc một loại (RECEIPT / PAYMENT / TRANSFER / ADJUSTMENT) với vòng đời DRAFT → ISSUED → VOIDED và source event id
Dòng sổ cái (transaction)Một dòng DEBIT hoặc CREDIT trong một voucher, tác động số dư của một tài khoản, có thể được phân loại theo danh mục
FinanceCategoryNhãn thu/chi - 14 danh mục hệ thống được bảo vệ cùng các danh mục tùy chỉnh với phân cấp cha
Voucher sequenceNguồn đánh số theo từng merchant, từng loại
Ledger snapshot / jobCác bút toán snapshot và queue job sổ cái (tách API + worker, tiến độ qua WebSocket)

Chỉ mang tính khái niệm - schema đầy đủ và bất biến nằm trong finance domain model.

10. Dependencies & Assumptions

Depends on

  • Vòng đời thanh toán (URD-PAY) - một khoản thanh toán hoàn tất là thứ kích hoạt auto-posting RECEIPT.
  • Đơn hàng (module Đơn hàng) - sale chuyển tiếp finance metadata trên payment.success.
  • Kho hàng (module Kho hàng) - sự kiện nhận purchase-order và xuất/điều chỉnh kho dẫn động các bút toán PAYMENT / ADJUSTMENT.
  • @nx/ledger - bộ máy ledger snapshot và job (tách API/worker).

Assumptions

  • Mỗi merchant có một tài khoản mặc định được chỉ định để nhận thu nhập bán hàng auto-post.
  • 14 danh mục hệ thống được seed khi sổ cái tài chính của merchant khởi tạo.
  • Sự kiện nghiệp vụ mang theo một source event id ổn định cho idempotency.

11. Risks & Open Questions

Risk / questionMitigation / status
Post trùng nếu một sự kiện bị gửi lạiMỗi voucher ghi lại source event id; việc post là idempotent
Một voucher mất cân bằng có thể làm hỏng sổ cáiBất biến được enforce: tổng DEBIT phải bằng tổng CREDIT trước khi issue
Hủy so với giữ lịch sử tài chínhHủy là một bút toán đảo cân bằng; voucher gốc không bao giờ bị xóa cứng
Không hỗ trợ đa tiền tệNgoài scope; mỗi voucher một tiền tệ được ghi nhận như một ràng buộc
Đảo tài chính trên một nguồn đã bị đảo (ví dụ revert PO)Mở: định nghĩa đường bù trừ xuyên module

12. Release Plan & Launch Criteria

AspectPlan
PhaseP2 (sổ cái tài chính) - xem URD feature catalog
RolloutTất cả merchant; không feature flag
MigrationKhông có migration dữ liệu; tài khoản tài chính và 14 danh mục hệ thống được seed khi khởi tạo merchant
Launch criteriaAuto-post từ bán hàng/mua hàng/kho được verify idempotent; mọi voucher cân bằng; số dư hiện tại khớp tổng dòng sổ cái; tạo thủ công + hủy-bằng-bút-toán-đảo được verify
MonitoringSố lượng voucher theo merchant, tỷ lệ lỗi auto-post, kiểm tra nhất quán số-dư-vs-sổ-cái, số lần va chạm idempotency

13. FAQ

Tiền đi đâu khi một giao dịch bán hàng được thanh toán? Một khoản thanh toán bán hàng hoàn tất auto-post một RECEIPT voucher cân bằng vào tài khoản mặc định của merchant - không cần nhập tay.

Có thể xóa một voucher nếu nó sai không? Không. Lịch sử tài chính không bao giờ bị xóa cứng; một voucher đã issue được sửa bằng một bút toán đảo cân bằng để hủy nó trong khi vẫn giữ bản gốc.

Điều gì ngăn cùng một sự kiện post hai lần? Mỗi voucher ghi lại source event id của nó; nếu sự kiện được gửi lại, không có voucher thứ hai được tạo.

Khác biệt giữa một tài khoản và một danh mục là gì? Tài khoản là nơi tiền được giữ (tiền mặt, ngân hàng, QR, mobile POS); danh mục phân loại một chuyển động thuộc loại thu hay chi nào.

Tôi có thể đổi tên hoặc xóa các danh mục được seed không? 14 danh mục hệ thống được bảo vệ và không thể xóa. Bạn có thể thêm các danh mục tùy chỉnh riêng từng merchant, có thể nằm dưới một danh mục cha.

Cái này có phát hành hóa đơn thuế không? Không - việc phát hành hóa đơn thuế thuộc module Thuế & Hóa đơn.

References

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