Skip to content

PRD: Finance accounts & ledger

ModuleFinancePRD IDPRD-WAL-001
StatusReady to devFEATWAL
EpicPlaneBANA-1498
Date2026-06-04Versionv0.1
Packages@nx/financeURDWAL
SurfaceClient · Owner/MgrBO · Ops
OwnerPhát Nguyễn

TL;DR

A first-class home for a merchant's money: typed accounts (cash, bank, QR, mobile-POS) that each carry a running balance, plus the internal control accounts (Inventory, Cost of Goods Sold) the system keeps for itself. Every voucher posts balanced debit/credit ledger lines against them, each line snapshotting the balance before and after - so an owner can trace where money lives and how each posting moved it.

1. Context & Problem

The Finance module (URD §1) tracks money across accounts, records every movement as a balanced double-entry voucher, and posts most of them automatically - but none of that has anywhere to live until accounts and ledger lines exist. Without typed accounts there is no running balance to route postings to; without ledger lines there is no per-account, balanced audit of how each voucher moved money.

This work lays the foundation: the accounts (WAL) that hold money and carry a running balance, and the ledger lines (TXN) every voucher posts against them. It also adds non-cash internal control accounts (Inventory, Cost of Goods Sold) the system keeps for itself, so cost-of-goods and stock-adjustment postings have somewhere to land.

2. Goals & Non-Goals

Goals

  • Hold typed accounts (Cash, Bank, QR, Mobile-POS), each owned by one merchant, each with a running balance.
  • Maintain exactly one default account per type per merchant for routing automatic postings.
  • Seed each merchant's default accounts and the internal Inventory / Cost-of-Goods-Sold control accounts when the merchant is created.
  • Post debit/credit ledger lines against accounts, each carrying its account, amount, and a balance-before/after snapshot, in the voucher's currency.
  • Link accounts to payment integrations (referenced, not auto-included).

Non-Goals

  • Payment-gateway processing - owned by the Payment module; finance only links to integrations.
  • The full voucher lifecycle and auto-posting rules (VCH) and category taxonomy (CAT) - tracked by their own features.
  • Budget tracking, profit & loss, and cash-flow forecasting.
  • Multi-currency conversion within a single voucher (single currency per voucher, default VND).

3. Success Metrics

MetricTarget / signal
Account coverageEvery merchant has its default and internal control accounts after creation
Default uniquenessExactly one default account per type per merchant; zero duplicates
Balance integrityAccount running balance equals the sum of its posted ledger lines
Snapshot completenessEvery ledger line carries a balance-before/after snapshot in the voucher's currency

4. Personas & Use Cases

PersonaGoal
OwnerSee where money lives across cash, bank, QR, and mobile-POS accounts and reconcile balances
Accountant / ManagerRead the per-account ledger and trace each movement to its source document
SystemAuto-seed accounts on new merchant and post balanced ledger lines for every voucher

Core scenarios: a merchant is created → default and internal control accounts are seeded → vouchers post debit/credit ledger lines against those accounts → each account's running balance updates and each line records a balance-before/after snapshot.

5. User Stories

  • As an owner, I want typed accounts for cash, bank, QR, and mobile-POS, so I can see where my money lives and its running balance.
  • As an owner, I want one default account per type, so automatic postings route to a predictable account.
  • As the system, I want a new merchant's default and internal control accounts seeded automatically, so cost-of-goods and stock postings have somewhere to land from day one.
  • As an accountant, I want each voucher to post balanced ledger lines against accounts with a balance snapshot, so I can audit how every movement changed an account.
  • As an owner, I want an account to reference its payment integration, so a QR / mobile-POS account ties back to its gateway without auto-pulling integration data.

6. Functional Requirements

#RequirementURD ref
FR-1Hold accounts of types Cash, Bank, QR, and Mobile-POS, each owned by one merchantURD-WAL-001
FR-2Maintain a default account per type per merchant for routing automatic postingsURD-WAL-002
FR-3Auto-create each merchant's default and internal control accounts (Inventory, Cost of Goods Sold) when the merchant is createdURD-WAL-003
FR-4Track each account's running current balance as vouchers postURD-WAL-004
FR-5Allow account currency (default VND)URD-WAL-005
FR-6Restrict account visibility to merchants the user is granted; admins see allURD-WAL-006
FR-7Each voucher posts debit/credit ledger lines against accountsURD-TXN-001
FR-8A line carries the account it affects, an optional category, an amount, and a balance-before/after snapshotURD-TXN-002
FR-9Ledger lines share the voucher's currencyURD-TXN-003
FR-10A line may reference its source document for traceabilityURD-TXN-004

Full requirement text and acceptance criteria live in the Finance URD. This PRD references them rather than restating them.

7. Non-Functional Requirements

AreaRequirement
Data integrityAn account's running balance and the ledger lines that move it are written together; balance equals the sum of posted lines
Default uniquenessExactly one default account per type per merchant, enforced at the model level
Tenancy & authzAccounts are confined to the user's own merchant; non-admins see only the merchants they are granted, admins see all
PrecisionMonetary math uses 4-decimal precision; balances stored with the same precision
ConsistencyAccount seeding and ledger posting are idempotent and transactional; a repeated merchant event never double-seeds
i18nUser-facing labels/types are bilingual (English and Vietnamese)

8. UX & Flows

Key screens (in the merchant app): account list / filter / form (incl. bank type), voucher select-account-by-currency, and the ledger-line (transaction) table / filter / show page.

9. Data & Domain

ConceptRole
AccountA money account - type (Cash/Bank/QR/Mobile-POS), owning merchant, running balance, currency, a per-type default flag, optional payment-integration link
Internal control accountA non-cash account (Inventory, Cost of Goods Sold) the system maintains for cost/stock postings
Ledger lineA debit/credit row - affected account, optional category, amount, balance-before/after snapshot, voucher currency, source-document reference

Conceptual only - full schema and invariants in the finance domain model.

10. Dependencies & Assumptions

Depends on

  • Commerce (Merchant) - a new merchant's accounts are reconciled automatically on creation.
  • Vouchers & posting (URD-VCH) - vouchers are what post ledger lines against accounts.
  • Payment - accounts reference payment integrations (linked, not auto-included).

Assumptions

  • A merchant-created event reaches Finance so accounts can be seeded.
  • Internal control accounts exist before any cost-of-goods posting is attempted.

11. Risks & Open Questions

Risk / questionMitigation / status
Account balance and ledger lines could divergeWritten transactionally; balance equals the sum of posted lines, snapshotted per line
Repeated merchant event could double-seed accountsSeeding is idempotent - a repeated event never creates a second default account
Per-type default-flag uniquenessEnforced at the model level after initial fixes
No multi-currency within a voucherOut of scope; single currency per voucher (default VND)

12. Release Plan & Launch Criteria

AspectPlan
PhaseP1 (foundation) - see URD feature catalog
RolloutAll merchants; no feature flag
MigrationSeed migration for default finance accounts; internal control accounts seeded per merchant
Launch criteriaNew merchant gets default + control accounts; ledger lines post balanced with balance snapshots; account balance equals the sum of its lines
MonitoringPer-merchant account count, default-uniqueness checks, balance-vs-ledger-sum consistency

13. FAQ

What account types exist? Cash, Bank, QR, and Mobile-POS - plus non-cash internal control accounts (Inventory, Cost of Goods Sold) the system maintains for itself.

What is an internal control account? A non-cash bookkeeping account - not the merchant's money - that gives cost-of-goods and stock-adjustment postings a place to land.

How does a default account get chosen? Exactly one account per type per merchant is flagged default; automatic postings route to it.

What does a ledger line record? The affected account, an optional category, an amount, the voucher's currency, a balance-before/after snapshot, and an optional source-document reference.

Does linking an account to a payment integration pull integration data in? No - the relation is a reference; integrations are not auto-included in the account.

References

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