PRD: Tax identity & groups
| Module | Tax & Invoice (CORE-10) | PRD ID | PRD-TAX-001 |
| Status | Shipped | Owner | Tax & Invoice squad |
| Date | 2026-05-31 | Version | v1.0 |
| Packages | @nx/taxation · @nx/invoice · @nx/core | URD | TAX · GRP · CFG |
TL;DR
Lets a merchant register a valid Vietnamese tax identity (MST), classify which tax applies to which products through reusable tax groups, and connect an invoice profile to a provider - the foundation that every issued e-invoice stands on. Tax flows automatically onto matching products and stays reconciled as the catalog changes, so the merchant is tax-correct before a single invoice is ever issued.
1. Context & Problem
Selling in Vietnam requires the merchant to print a valid tax identity (MST) on every issued invoice, to apply the correct tax rule to each product, and to have a provider-backed invoicing setup before any invoice can be issued. Today none of this exists as a coherent layer: tax data lives as ad-hoc fields, products carry no tax classification, and there is no merchant invoice profile to connect a provider. Without this foundation the issuance lifecycle has nothing to stand on - there is no seller to print, no per-product tax to compute, and no profile to issue against.
This increment builds that foundation. The taxation service owns the seller tax identity, Vietnamese administrative reference data, and reusable tax groups that provision tax onto matching products; the invoice service owns the merchant invoice profile and provider configuration, kept in sync with the seller's tax identity via merchant CDC.
2. Goals & Non-Goals
Goals
- Register the seller tax identity (MST, business name, address) and make it the seller printed on issued invoices.
- Expose Vietnamese administrative reference data (provinces, wards, units) for address entry, plus tax-code resolution and format validation.
- Define reusable tax-group rule templates that classify which tax applies to which products, and provision that tax onto matching products.
- Reconcile applied tax automatically when a product is created, updated, or removed (Kafka-driven seam between taxation and commerce).
- Create the merchant invoice profile linked to the seller tax identity, with provider configuration, kept in sync via merchant CDC.
Non-Goals
- The authoritative tax-code registry (owned by the tax authority).
- Tax-rate calculation at sale time (owned by the pricing engine).
- The full invoice issuance lifecycle, retries, CQT / T-VAN submission, and audit trail - owned by Invoice Lifecycle (
INV). - Invoice request / buyer self-service claim and issuance modes (
REQ/MODfeatures). - The later
CFGrequirements (per-type serial / policy, channel routing, retry policy, profile sharing, onboarding wizard).
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Tax-identity coverage | 100% of merchants that issue invoices have a registered MST + business name + address |
| Address validity | Province / ward / unit selections resolve against VN reference data; tax codes pass format validation before save |
| Provisioning correctness | Products matched by a tax group carry the correct applied tax; zero matched products left unprovisioned |
| Reconciliation lag | Applied tax reconciles within the CDC seam window after a product create / update / remove |
| Profile readiness | Merchants with a tax identity also have an invoice profile in sync before issuance is attempted |
4. Personas & Use Cases
| Persona | Goal |
|---|---|
| Owner | Register the merchant's tax identity, define tax groups, connect the invoice profile/provider |
| Manager | Maintain tax groups and review which products carry which tax |
| Product staff | Create / edit products and trust that the correct tax is applied automatically |
Core scenarios: register the seller tax identity (with VN address lookups) → define a tax group → it provisions tax onto matching products → product changes reconcile the applied tax automatically → the invoice profile, linked to the tax identity, is connected to a provider and kept in sync.
5. User Stories
- As an owner, I want to register the merchant's tax identity (MST, name, address), so it prints as the seller on every issued invoice.
- As an owner, I want VN province / ward / unit lookups when entering an address, so the tax identity carries valid administrative data.
- As an owner, I want a tax code validated for correct Vietnamese format before it is accepted, so a malformed MST never reaches an invoice.
- As a manager, I want to define a reusable tax-group template, so the correct tax is classified and applied to the right products.
- As product staff, I want tax provisioned automatically when I create or update a product, so I don't set tax by hand on every item.
- As a manager, I want applied tax to reconcile when a product changes or is removed, so tax never drifts out of sync with the catalog.
- As an owner, I want a merchant invoice profile linked to my tax identity and a provider, so the merchant is ready to issue invoices.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Register the seller tax identity (MST, business name, address) used as the seller on issued invoices | URD-TAX-001 |
| FR-2 | Look up Vietnamese provinces, wards, and administrative units when entering addresses | URD-TAX-002 |
| FR-3 | Validate the tax code for correct Vietnamese format before it is accepted; resolve VN address and sync tax info | URD-TAX-003 |
| FR-4 | Define a tax-group rule template that classifies which tax applies to which products | URD-GRP-001 |
| FR-5 | Applying a tax group provisions the correct tax onto its matching products | URD-GRP-002 |
| FR-6 | Changing or removing a product reconciles its applied tax automatically (Kafka seam, taxation ⇄ commerce) | URD-GRP-003 |
| FR-7 | A tax group is usable only when compatible with the merchant's tax method | URD-GRP-004 |
| FR-8 | Create a merchant invoice profile linked to the seller tax identity | URD-CFG-001 |
| FR-9 | Connect a provider (VNPAY / VNIS via iiapi) with credentials stored encrypted; keep the profile in sync with tax info via merchant CDC | URD-CFG-002 |
Full requirement text and acceptance criteria live in the Tax & Invoice URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Data integrity | The merchant tax identity is authoritative; the invoice profile is kept consistent with it via merchant CDC - no divergence between the seller printed and the registered MST |
| Tenancy & authz | All operations scoped per merchant (x-merchant-id); tax-identity and provider setup are owner-gated |
| Consistency | Tax provisioning and reconciliation are CDC-driven and idempotent - replays converge on the same applied tax |
| Security | Provider credentials on the invoice profile are stored encrypted |
| Performance | VN administrative reference data resolves fast enough for live address entry |
| i18n | User-facing labels are bilingual ({ en, vi }); administrative data follows VN naming |
8. UX & Flows
Key screens (in apps/client): the tax-identity setup with VN address pickers, the tax-group editor, the per-product tax view, and the invoice-profile / provider connection form.
9. Data & Domain
| Entity | Role |
|---|---|
TaxInfo | The seller tax identity (MST, business name, address) - related from the merchant, authoritative |
TaxGroup | A reusable rule template classifying which tax applies to which products |
TaxGroupItem | The applied-tax row linking a tax group to its matching products |
Merchant taxMethod | The merchant's tax method that a tax group must be compatible with |
Product taxGroupId | The tax group provisioned onto a product |
MerchantInvoiceProfile | The merchant's invoicing setup linking the tax identity to a provider |
| Provider configuration | The connected provider (VNPAY / VNIS via iiapi) with encrypted credentials |
Conceptual only - full schema and invariants in the taxation domain model and invoice domain model.
10. Dependencies & Assumptions
Depends on
- Commerce / Merchant - the merchant record carries the tax identity entered by the owner.
- Products (Products) - tax groups provision tax onto products; product changes drive reconciliation.
- Kafka CDC - the seam that propagates product and merchant changes into taxation and invoice.
@nx/invoice- for the merchant invoice profile and provider configuration.
Assumptions
- The merchant has entered a tax identity before issuance is attempted.
- A tax method is set on the merchant so tax-group compatibility can be evaluated.
- A supported provider (VNPAY / VNIS via iiapi) is available to connect.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Tax identity and invoice profile could diverge | Profile kept in sync with the merchant tax identity via merchant CDC |
| Applied tax drifts as the catalog changes | Kafka seam reconciles tax on every product create / update / remove; idempotent so replays converge |
| Tax group incompatible with the merchant's tax method | Compatibility is enforced before a group is usable |
| Malformed MST reaching an invoice | Tax code is format-validated before it is accepted |
| Provider credential exposure | Credentials stored encrypted on the profile |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 (foundation) - see URD feature catalog |
| Rollout | All merchants; no feature flag |
| Migration | Tax group / item migrated into the tax schema; taxation runs as a dependent service |
| Launch criteria | Tax identity registers with VN address + validation; tax group provisions tax onto matching products; product change reconciles applied tax; invoice profile created and in sync with the tax identity |
| Monitoring | Provisioning / reconciliation success rate, CDC lag, tax-identity coverage, profile-sync consistency |
13. FAQ
Where does the merchant's tax identity come from? The owner enters it on the merchant; it is the authoritative seller printed on issued invoices and is mirrored into the invoice profile via merchant CDC.
Do I set tax on each product by hand? No - a tax group provisions the correct tax onto its matching products automatically, and reconciles when a product changes or is removed.
What happens when I edit or delete a product? The Kafka seam reconciles the applied tax automatically; you don't re-apply tax manually.
Can any tax group apply to any merchant? No - a tax group is usable only when compatible with the merchant's tax method.
Does this issue invoices? No - this is the tax-identity, tax-group, and invoice-profile foundation. The issuance lifecycle (queue, retries, CQT submission, audit trail) is owned by Invoice Lifecycle.
References
- URD: Tax & Invoice - Tax Identity · Tax Groups · Invoice Configuration
- Related PRD: Invoice Lifecycle & Issuance · E-invoice Provider Integration
- Module: Tax & Invoice - overview + traceability
- Developer: @nx/taxation · domain model · @nx/invoice