URD: Payment & Transaction
| Module | CORE-08 | Version | v0.4 |
|---|---|---|---|
| Status | In-progress | Date | 2026-05-30 |
1. Purpose
Define the user-facing requirements for collecting payments and recording the resulting money. The module connects a merchant's payment providers to BANA, surfaces live payment status, and books every completed payment, purchase, and stock movement into a double-entry finance ledger so owners can see balances and reconcile their books.
2. Scope
| Included | Excluded |
|---|---|
| Per-merchant payment provider credentials (VNPAY QR MMS, PhonePOS) | Direct gateway integration code (developer concern) |
| Real-time payment status (webhook + WebSocket) | Checkout / split-payment UX (Orders module) |
| Outbound webhook subscriptions per merchant | Card-data / token storage |
| Finance accounts / wallets + control accounts | Multi-currency conversion |
| Double-entry vouchers (RECEIPT / PAYMENT / TRANSFER / ADJUSTMENT) | Tax invoice issuance (Tax & Invoice module) |
| Auto-posting from sale, purchase, and inventory events | Structured provider refunds (Planned) |
| Category hierarchy (seeded + custom) | Per-shift cash reconciliation (Planned) |
3. Definitions
| Term | Definition |
|---|---|
| Payment provider | An external service (e.g. VNPAY) that processes a customer's payment |
| Webhook | An outbound notification BANA sends to a subscriber when a payment changes state |
| Account / Wallet | A place money sits: cash, bank, QR collection, mobile POS, or an internal control account |
| Voucher | A balanced bookkeeping entry of one type (RECEIPT, PAYMENT, TRANSFER, ADJUSTMENT) |
| Transaction (ledger line) | One DEBIT or CREDIT line within a voucher, affecting one account's balance |
| Category | An income or expense label classifying where money came from or went |
| Auto-posting | A voucher created automatically by the system in reaction to a business event |
4. Conceptual Model
Conceptual only — full schema lives in the payment and finance developer domain models.
5. Functional Requirements
One table per functional area.
<AREA>codes match the test-case IDs. Priority = MoSCoW (Must / Should / Could / Won't).
5.1 Payment Lifecycle (PAY)
| ID | P | Requirement |
|---|---|---|
| URD-PAY-001 | M | The system receives payment results from the provider and updates the payment's status |
| URD-PAY-002 | M | On a successful payment, the system notifies subscribers (e.g. the sale that settles the order) |
| URD-PAY-003 | M | Payment status is broadcast live to the cashier (pending → paid / failed / expired) |
| URD-PAY-004 | M | The same payment result is applied only once, even if delivered multiple times (idempotent) |
| URD-PAY-005 | S | An owner can subscribe webhook endpoints by event type, with retries on delivery failure |
| URD-PAY-006 | W | Structured refund back through the original provider (Planned — see §7) |
5.2 Provider Credentials (PRV)
| ID | P | Requirement |
|---|---|---|
| URD-PRV-001 | M | An owner can connect a payment provider (VNPAY QR MMS, PhonePOS) per merchant |
| URD-PRV-002 | M | Provider credentials are stored encrypted and never shown in full |
| URD-PRV-003 | S | Credentials are scoped per merchant so one merchant cannot use another's |
5.3 Accounts & Wallets (WAL)
| ID | P | Requirement |
|---|---|---|
| URD-WAL-001 | M | An owner can create accounts of type CASH, BANK, QR code, or mobile POS |
| URD-WAL-002 | M | The system maintains internal control accounts (e.g. inventory, COGS) automatically |
| URD-WAL-003 | M | Each account tracks an opening balance and a running current balance |
| URD-WAL-004 | M | A default account per merchant receives auto-posted sale income |
| URD-WAL-005 | S | Non-owner roles see only the accounts of merchants they are granted access to |
5.4 Vouchers & Ledger (VCH)
| ID | P | Requirement |
|---|---|---|
| URD-VCH-001 | M | Every voucher is balanced: total DEBIT equals total CREDIT |
| URD-VCH-002 | M | Voucher types are RECEIPT, PAYMENT, TRANSFER, ADJUSTMENT |
| URD-VCH-003 | M | A completed sale payment auto-posts a RECEIPT voucher to the default account |
| URD-VCH-004 | M | Receiving a purchase order auto-posts a PAYMENT voucher |
| URD-VCH-005 | M | A stock issue/adjustment auto-posts the matching ledger voucher |
| URD-VCH-006 | M | Each voucher records its source event so the same event posts only once (idempotent) |
| URD-VCH-007 | M | Vouchers are numbered per merchant and type (e.g. PT / PC / PCK / PKT) |
| URD-VCH-008 | S | An owner can create a manual voucher (draft → issue) |
| URD-VCH-009 | S | An owner can void a voucher via a balanced reversal (no hard delete) |
| URD-VCH-010 | C | Transfer between two accounts is recorded as a zero-sum voucher |
5.5 Categories (CAT)
| ID | P | Requirement |
|---|---|---|
| URD-CAT-001 | M | 14 system categories are seeded and cannot be removed |
| URD-CAT-002 | M | Categories are typed as INCOME or EXPENSE |
| URD-CAT-003 | S | An owner can add merchant-specific custom categories, including a parent hierarchy |
6. Acceptance Criteria
AC-PAY-01: Payment status updates
| Given | When | Then |
|---|---|---|
| A pending payment | The provider reports success | Status becomes paid, subscribers are notified, cashier sees the update live |
| A pending payment | The provider reports failure / expiry | Status becomes failed / expired; the order stays open |
| An already-applied result | The same result is redelivered | It is ignored; no duplicate effect |
AC-VCH-01: Auto-posting from events
| Given | When | Then |
|---|---|---|
| A successful sale payment | The event is processed | A balanced RECEIPT voucher posts to the default account |
| A received purchase order | The event is processed | A balanced PAYMENT voucher posts |
| The same source event | It is delivered again | No second voucher is created (idempotent) |
AC-VCH-02: Manual voucher and void
| Given | When | Then |
|---|---|---|
| An owner | Creates and issues a manual voucher | A balanced voucher appears in the ledger with a sequence number |
| An issued voucher | The owner voids it | A balanced reversal voucher is posted; the original is preserved |
AC-WAL-01: Accounts and balances
| Given | When | Then |
|---|---|---|
| An owner | Creates an account with an opening balance | The account shows that opening balance as current |
| A posted voucher | It debits/credits an account | The account's running balance updates accordingly |
7. Constraints & Non-Goals
Constraints
| ID | Constraint |
|---|---|
| C-01 | Every voucher must be balanced (DEBIT total = CREDIT total) |
| C-02 | The 14 seeded categories cannot be removed |
| C-03 | Provider credentials are encrypted at rest and masked in responses |
| C-04 | Each business event posts at most one voucher (idempotent via source event id) |
| C-05 | Records use soft-delete / reversal — no hard delete of financial history |
| C-06 | One default account per merchant for auto-posted sale income |
Non-Goals
- SoftPOS / NFC tap-to-pay flow
- Additional e-wallet providers (Momo, ZaloPay)
- Structured refund / reversal of external provider charges
- Multi-currency conversion and cross-currency reconciliation
- Per-shift cash reconciliation dashboard
8. Version History
| Date | Author | Description | Ver |
|---|---|---|---|
| 2026-02-26 | P. Do — Product Owner | Initial user stories | v0.1 |
| 2026-04-16 | P. Do — Product Owner | Finance wallets, transactions, categories | v0.3 |
| 2026-05-30 | Migration | Restructured to module convention; aligned areas (PAY/PRV/WAL/VCH/CAT) to two-package reality; refund + reconciliation marked Planned | v0.4 |