URD: Tax & Invoice
| Module | CORE-10 | Version | v0.5 |
|---|---|---|---|
| Status | In-progress | Date | 2026-06-04 |
Business documentation. This URD is Tax & Invoice's feature list - each feature below is one Functional Area (
<AREA>). The same<AREA>keys the feature's PRDs (PRD-<AREA>-NNN) and tests (TC-<AREA>-NNN), and each feature is listed in the Delivery feature catalog. See the Feature Spine convention.
1. Purpose
Define the user-facing requirements for staying tax-compliant when selling. The module records the merchant's tax identity, applies the correct tax rules to products, and turns a completed payment into a legal Vietnamese electronic invoice that can be delivered to the buyer and submitted to the tax authority - with adjustment, cancellation, and buyer self-service claims along the way.
2. Scope
| Included | Excluded |
|---|---|
| Seller tax identity (tax code / MST, name, address) | Authoritative tax-code registry (tax authority owns it) |
| Tax-group rule templates applied onto products | Tax-rate calculation at sale time (pricing engine) |
| VN administrative reference data (provinces, wards, units) | PDF rendering of the invoice (provider-side) |
| Merchant invoice profile + encrypted provider credentials | Payment capture (Payment module) |
| Invoice issuance lifecycle (queued → issued / failed / cancelled) | Order lifecycle (Orders module) |
| Provider integration: VNPAY / VNIS via iiapi + T-VAN | Multiple providers beyond the current iiapi/T-VAN set |
| Tax-authority (CQT) submission and status tracking | Tax declaration / filing automation |
| Invoice adjustment, replacement, cancellation | Cross-merchant settlement |
| Invoice request + buyer self-service claim (QR) | |
| Channel routing + profile sharing across branches | |
| Immutable audit trail for every invoice event |
3. Definitions
| Term | Definition |
|---|---|
| Tax identity (MST) | The seller's tax registration code, business name, and address printed as the seller on every invoice |
| Tax group | A reusable rule template that decides which tax applies to which products |
| Invoice profile | A merchant's invoicing setup linking the tax identity to a provider |
| Provider | The e-invoice gateway (currently VNPAY / VNIS via iiapi) that issues the legal invoice |
| Tax authority (CQT) | Vietnam's tax authority, reached through the T-VAN network for submission and validation |
| Issuance | The act of turning an order into a numbered, legal e-invoice via a provider |
| Buyer claim | A buyer self-serving their own invoice by scanning a receipt QR before a deadline |
| Audit trail | The immutable record of every state change an invoice goes through |
4. Conceptual Model
Conceptual only - full schema lives in the taxation and invoice developer domain models.
5. Feature Catalog
The feature list of this module. Each row is one feature (a Functional Area). Detail in §6. Mirrored in the Delivery feature catalog.
| Feature ID | Feature | Phase | Status | Priority |
|---|---|---|---|---|
TAX | Tax Identity | P1 | Built | High |
GRP | Tax Groups | P1 | Built | High |
CFG | Invoice Configuration | P1 | Built | High |
INV | Invoice Lifecycle | P1 | Built | High |
REQ | Invoice Request & Buyer Claim | P1 | Built | High |
MOD | Issuance Modes | P1 | Built | High |
DCL | Tax declaration (HKD 1-3B) | P2 | Planned | High |
ISS | Invoice issuance experience | P2 | Planned | High |
Status: live from Plane where mapped, otherwise registry-declared. Vocabulary mirrors Plane (state-group / phase).
6. Features
One sub-section per feature, in catalog order. Each feature keeps its description, requirements, and acceptance together. Priority = MoSCoW (Must / Should / Could / Won't).
TAX - Tax Identity Built
Feature ID: tax/TAX · Phase: P1 · PRDs: - · Dev: @nx/taxation
What it does for users: owners register the merchant's tax code (MST), business name, and address that print as the seller on every issued invoice, with VN province/ward lookups when entering addresses.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-TAX-001 | M | Register the seller tax identity (MST, business name, address) used on issued invoices |
| URD-TAX-002 | M | Look up Vietnamese provinces, wards, and administrative units when entering addresses |
| URD-TAX-003 | S | Tax code is validated for correct Vietnamese format before it is accepted |
Acceptance
AC-TAX-01: Register seller tax identity
| Given | When | Then |
|---|---|---|
| A merchant entering tax details | The seller tax identity (MST, name, address) is saved | It is used as the seller on issued invoices |
GRP - Tax Groups Built
Feature ID: tax/GRP · Phase: P1 · PRDs: - · Dev: @nx/taxation
What it does for users: owners define reusable tax-group templates that automatically apply the correct tax onto matching products, and reconcile that tax whenever a product changes.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-GRP-001 | M | Define a tax-group rule template that classifies which tax applies to which products |
| URD-GRP-002 | M | Applying a tax group provisions the correct tax onto its matching products |
| URD-GRP-003 | M | Changing or removing a product reconciles its applied tax automatically |
| URD-GRP-004 | S | A tax group is only usable when compatible with the merchant's tax method |
Acceptance
AC-GRP-01: Tax-group provisioning
| Given | When | Then |
|---|---|---|
| A tax group matching a product | The product is created or updated | The correct tax is applied onto that product |
| A product is removed | The change is processed | Its applied tax is reconciled / removed |
CFG - Invoice Configuration Built
Feature ID: tax/CFG · Phase: P1 · PRDs: - · Dev: @nx/invoice
What it does for users: owners set up the merchant's invoicing - connect a provider with encrypted credentials, configure serial/category/policy per invoice type, route each sale channel to a config, and share profiles across branches.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-CFG-001 | M | Create a merchant invoice profile linked to the seller tax identity |
| URD-CFG-002 | M | Connect a provider (VNPAY / VNIS via iiapi) with credentials stored encrypted |
| URD-CFG-003 | M | Configure per invoice type the serial, category, tax method, and issuance policy |
| URD-CFG-004 | M | Route each sale channel to the provider config that should issue its invoices |
| URD-CFG-005 | M | Configure a retry policy (max retries + delay schedule) for failed issuance |
| URD-CFG-006 | S | Share an invoice profile across branches (private / all-branches / whitelist) |
| URD-CFG-007 | S | Guided onboarding wizard for step-by-step provider setup |
Acceptance
AC-CFG-01: Connect a provider
| Given | When | Then |
|---|---|---|
| An invoice profile linked to the seller tax identity | A provider is connected with credentials | Credentials are stored encrypted and the profile can issue invoices |
| A sale channel | It is routed to a provider config | That config issues the channel's invoices |
INV - Invoice Lifecycle Built
Feature ID: tax/INV · Phase: P1 · PRDs: PRD-INV-001 · PRD-INV-003 · Dev: @nx/invoice
What it does for users: a completed payment queues and issues a legal e-invoice via the provider, captures its number and tax-authority code, retries failures, submits to the tax authority, and records every event in an immutable audit trail - with adjustment, replacement, and cancellation.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-INV-001 | M | Queue an invoice for issuance automatically on a successful payment |
| URD-INV-002 | M | Issue the invoice via the provider and capture its number + tax-authority code |
| URD-INV-003 | M | Track invoice status (pending → processing → success / failed / cancelled) |
| URD-INV-004 | M | Retry a failed issuance per the configured policy |
| URD-INV-005 | M | Submit the issued invoice to the tax authority (CQT via T-VAN) when enabled, and track its status |
| URD-INV-006 | M | Record an immutable audit trail entry for every invoice event |
| URD-INV-007 | M | Adjust an issued invoice (correction linked to the original) |
| URD-INV-008 | M | Replace or cancel an issued invoice with a reason |
| URD-INV-009 | S | Process inbound provider webhooks with signature validation to update status |
| URD-INV-010 | M | Only an issued (SUCCESS) invoice can be adjusted or cancelled; the correction always links back to the original (PRD-INV-003) |
| URD-INV-011 | M | An adjustment creates a new correction invoice (adjustment origin) linked to the original and is processed asynchronously via the issuance queue, claimed under an optimistic lock so a retried job issues it at most once |
| URD-INV-012 | M | The correction carries its own line items, description, and totals, and is issued through the provider referencing the original issuance |
| URD-INV-013 | M | Adjustment is supported for VAT, POS-VAT, and ticket-VAT invoice types; an unsupported type is refused |
| URD-INV-014 | M | Cancellation marks the invoice cancelled with a required reason; for an issued invoice it also calls the provider cancellation |
| URD-INV-015 | M | Cancellation is idempotent (re-cancelling is a no-op) and is blocked while the invoice is being processed |
| URD-INV-016 | S | Every adjustment and cancellation writes an immutable audit entry and notifies connected clients in real time |
Acceptance
AC-INV-01: Issue on payment
| Given | When | Then |
|---|---|---|
| A successful payment for an order | The payment-success event is received | An invoice is queued for issuance |
| The provider accepts | Issuance completes | Invoice number + tax-authority code are recorded; status is success |
| The provider rejects | Issuance fails | A retry is scheduled per policy |
| Max retries exceeded | Last retry fails | Status is failed; the failure is recorded in the audit trail |
AC-INV-03: Tax-authority submission
| Given | When | Then |
|---|---|---|
| Tax-authority submission is enabled | An invoice is issued | The invoice is submitted to CQT via T-VAN |
| CQT accepts | The response returns | The invoice status is updated to accepted |
| CQT rejects | The response returns | The status records the rejection reason |
AC-INV-04: Adjust an issued invoice
| Given | When | Then |
|---|---|---|
| An issued (SUCCESS) invoice | An adjustment is requested with a description and adjustment items | A linked correction invoice is created (PENDING) and queued |
| The queued adjustment is processed | The worker issues it via the provider referencing the original | Its status becomes SUCCESS, an audit entry is recorded, and clients update live |
| The original is not in SUCCESS state | An adjustment is requested | It is refused - only issued invoices can be adjusted |
AC-INV-05: Cancel an invoice
| Given | When | Then |
|---|---|---|
| An issued (SUCCESS) invoice | Cancellation is requested with a reason | The provider cancellation is called, the invoice is marked cancelled, and the reason + an audit entry are recorded |
| An invoice currently processing | Cancellation is requested | It is refused until processing completes |
| An already-cancelled invoice | Cancellation is requested again | The request is a no-op (idempotent) |
REQ - Invoice Request & Buyer Claim Built
Feature ID: tax/REQ · Phase: P1 · PRDs: - · Dev: @nx/invoice
What it does for users: a cashier collects buyer info and issues the invoice directly, or the buyer self-serves via a receipt QR with a claim token and deadline; invoices and claim links are delivered by QR, email, or SMS.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-REQ-001 | M | Capture buyer info (name, tax code, address, email) for an invoice |
| URD-REQ-002 | M | Direct flow: cashier collects buyer info and issues the invoice |
| URD-REQ-003 | S | Buyer self-service: receipt QR with a claim token and deadline |
| URD-REQ-004 | S | Claim lifecycle: pending → claimed / expired |
| URD-REQ-005 | S | Deliver the invoice / claim link by receipt QR, email, or SMS |
Acceptance
AC-REQ-01: Buyer self-service claim
| Given | When | Then |
|---|---|---|
| A receipt with a valid claim QR | Buyer opens the link before the deadline | Buyer can submit their info |
| Buyer submits info | Submission succeeds | The invoice is issued with the buyer details |
| The deadline has passed | Buyer opens the link | The claim is expired and no invoice is issued |
MOD - Issuance Modes Built
Feature ID: tax/MOD · Phase: P1 · PRDs: - · Dev: @nx/invoice
What it does for users: invoices can be issued in real time on payment, manually by a cashier at the counter, in scheduled batches, or by the buyer self-claiming via QR.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-MOD-001 | M | Real-time: issue immediately on payment |
| URD-MOD-002 | S | Manual: cashier-initiated issuance at the counter |
| URD-MOD-003 | S | Scheduled: batch issuance by a scheduled job |
| URD-MOD-004 | S | Buyer self-service: buyer claims and issues via QR |
Acceptance
AC-MOD-01: Real-time issuance
| Given | When | Then |
|---|---|---|
| Real-time mode is configured | A payment succeeds | The invoice is issued immediately |
DCL - Tax Declaration (HKD 1-3B) Planned
Feature ID: tax/DCL · Phase: P2 (Jul-Aug) · PRDs: PRD-DCL-001 · Dev: @nx/ledger · @nx/taxation
What it does for users: a household business in the 1-3B band keeps its tax book and files its tax from inside KICKO - book S2a from real sales, PIT by its industry's rates, the official 01/CNKD form, submitted via T-VAN - no accountant needed.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-DCL-001 | M | Book S2a reflects the merchant's real sales per tax group |
| URD-DCL-002 | M | Tax rates are determined by the merchant's industry (configurable mapping) |
| URD-DCL-003 | M | PIT is computed from revenue per the merchant's applicable rates |
| URD-DCL-004 | M | Declaration form 01/CNKD is generated (PDF/XML) for a period |
| URD-DCL-005 | M | The declaration is submitted via T-VAN and its status tracked to authority acknowledgement |
| URD-DCL-006 | M | Client screens: review the book → preview 01/CNKD → submit |
| URD-DCL-007 | S | Submission history per period is kept |
Acceptance
AC-DCL-01: One full tax period
| Given | When | Then |
|---|---|---|
| A 1-3B merchant with a month of sales | They review S2a, preview and submit 01/CNKD | T-VAN accepts; status reaches "acknowledged"; the filing is archived per period |
ISS - Invoice Issuance Experience Planned
Feature ID: tax/ISS · Phase: P2 (Jul) · PRDs: PRD-ISS-001 · Dev: @nx/invoice
What it does for users: a merchant actually issues e-invoices in daily operation - one action at the POS at payment, a place to see and manage every invoice, fixes via adjustment/replacement, and company VAT invoices carrying the buyer's MST. (The backend lifecycle and provider integration are built - this increment puts them in users' hands.)
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-ISS-001 | M | Cashier issues the e-invoice right at the POS at payment (MTT) - one action |
| URD-ISS-002 | M | Invoice screens: list + detail with provider status and tax-authority code |
| URD-ISS-003 | M | Adjustment and replacement invoices can be issued for an issued invoice |
| URD-ISS-004 | M | A company VAT invoice carries the buyer's MST + company name |
| URD-ISS-005 | M | Failed issuance is visible and retryable |
| URD-ISS-006 | S | The issued invoice can be printed/shared with the customer (link/PDF) |
| URD-ISS-007 | S | Provider connection (VNPAY) is verifiable end-to-end from the config screens |
Acceptance
AC-ISS-01: Issue in the real flow
| Given | When | Then |
|---|---|---|
| A paid sale at the POS | Cashier issues the invoice | Invoice issued with provider number + authority code, visible in the list |
| The buyer is a business customer with MST | The invoice is issued | It carries the buyer's MST and company name |
| The provider fails | Issuance runs | The failure is visible and can be retried without re-creating the sale |
7. Constraints & Non-Goals
Constraints
| ID | Constraint |
|---|---|
| C-01 | One active invoice profile per merchant |
| C-02 | One active config mapping per sale channel |
| C-03 | Provider credentials are stored encrypted |
| C-04 | The invoice audit trail is immutable |
| C-05 | A claim token is unique and bound to a single invoice request |
| C-06 | All records use soft-delete; nothing is physically removed |
Non-Goals
- Multiple invoice providers beyond the current iiapi / T-VAN set
- PDF rendering of the invoice (produced provider-side)
- Tax-rate calculation at sale time (owned by the pricing engine)
- Tax declaration / filing automation
8. Version History
| Date | Author | Description | Ver |
|---|---|---|---|
| 2026-02-26 | P. Do - Product Owner | Initial user stories | v0.1 |
| 2026-02-27 | QE | Code-level assessment, requirement adjustments | v0.2 |
| 2026-04-16 | P. Do - Product Owner | VNPAY IIAPI + T-VAN + buyer-claim model | v0.3 |
| 2026-05-30 | Migration | Restructured to module-docs convention; AREA codes realigned to taxation + invoice build | v0.4 |
| 2026-06-04 | Claude (AI pair) | Reorganize by feature (Feature Spine) | v0.5 |