Skip to content

PRD: Tax Group Configuration (Back Office)

ModuleTax & InvoicePRD IDPRD-GRP-001
StatusReady to devFEATGRP
EpicBANA-1318PlaneBANA-1740
Date2026-06-30Versionv1.1
Packages@nx/taxationURDGRP
SurfaceBO · Ops
OwnerPhát Nguyễn

TL;DR

Lets the Operations team (NEXPANDO & VNPAY) author reusable tax groups from the Back Office: each group declares a tax method (Deduction / Direct) and bundles multiple tax rate lines (tax type, rate %, included in price or not, Sale/Purchase direction, tax bearer, priority) - the tax engine provisions those lines onto products assigned to the group and reconciles them whenever a product changes.

1. Context & Problem

Every product must carry the declared set of taxes (VAT, excise, environmental…), but setting tax product-by-product is error-prone and unmaintainable. A tax group is a reusable template: declare the group's tax rate lines once, then assign the group to products during product setup - the product receives the group's full set of tax lines with no per-tax manual entry.

This increment is the Back-Office tax-group configuration screen: the Operations team authors groups through three blocks - the group list, the group form, and the tax-rate-line block on the edit screen. Provisioning tax onto products and reconciling on product change is background work in the tax engine, not an action on this screen.

2. Goals & Non-Goals

Goals

  • Author tax groups: identifier, bilingual name, tax method (Deduction / Direct), status.
  • Author tax rate lines within each group: tax type (5 classifications), rate %, included-in-price, priority, direction, tax bearer.
  • The tax engine provisions the group's tax lines onto assigned products and reconciles them when a product changes (background).
  • Constrain tax groups by the merchant's tax method - a group is assignable only where the method matches (not built yet, see FR-6).

Non-Goals

3. Success Metrics

MetricTarget / signal
Tax by templateA product assigned a group receives all of the group's tax lines, with no per-tax manual entry
ConsistencyChanging or removing a product makes the engine recompute its provisioned tax; no tax from a stale configuration remains
Compatibility🚧 A tax group is assignable only to merchants with the same tax method (not built - FR-6)

4. Personas & Use Cases

PersonaGoal in this feature
Operations team (NEXPANDO & VNPAY)Author tax groups and their rate lines so products are taxed consistently from a template

Core scenario: the Operations team creates a "Retail VAT" group under the Deduction method; after saving, they reopen the group on the edit screen to add the line "VAT 10%, included in price, Sale direction, borne by the customer"; products assigned the group receive that tax line automatically; when a product changes or is removed, the engine reconciles the provisioned tax.

5. User Stories

  • As the Operations team, I want to author a tax group with its tax rate lines, so assigned products receive their full tax set without manual entry.
  • As the Operations team, I want each tax line declared as a %, with an included-in-price flag, a Sale/Purchase direction, and a tax bearer, so each tax's obligation is described precisely.
  • As the Operations team, I want a priority on each line, so when a product matches several lines the lowest-numbered line applies first.
  • As the Operations team, I want a tax group assignable only to merchants with the same tax method, so tax cannot be misconfigured (not built yet).

6. Functional Requirements

Screen operations

#RequirementStatusURD ref
FR-1Tax group list - 4 columns, all 4 filterable, with edit / delete actions✅ builtURD-GRP-001
FR-2Create / edit a tax group - 5-field form with validation and defaults✅ builtURD-GRP-001
FR-3Tax rate lines of a group - a group holds multiple tax lines, added / edited / deleted via a dialog on the edit screen✅ builtURD-GRP-001

System behavior (background - not screen operations)

#RequirementStatusURD ref
FR-4Provision tax onto products - a product assigned a group receives all of the group's tax lines✅ built (engine)URD-GRP-002
FR-5Reconcile on product change - changing or removing a product recomputes its provisioned tax✅ built (engine)URD-GRP-003
FR-6Tax method compatibility - a tax group is assignable only to merchants with the same tax method🚧 not builtURD-GRP-004

FR-1 - Tax group list ✅

  • Columns: Name (bilingual) · Description (bilingual) · Tax method · Status.
  • Filters: all 4 columns - Name and Description by fuzzy text search; Tax method and Status by value.
  • Row actions: Edit (opens the edit screen) · Delete (confirmation dialog naming the group's identifier).

FR-2 - Create / edit a tax group ✅

FieldRequiredRule
Identifierrequiredfree text (no format / length constraint yet)
Namerequiredbilingual EN/VI, ≤ 200 characters per language
Descriptionoptionalbilingual EN/VI, ≤ 400 characters per language
Tax methodrequired2 values: Deduction (default) · Direct
Statusrequired3 values: Activated (default) · Deactivated · Archived
  • Leaving the screen with unsaved form changes → warning.
  • Saving (create and edit alike) returns to the list.

FR-3 - Tax rate lines of a group ✅

A tax group holds multiple tax rate lines; lines are managed on the group's edit screen - after creating a group you must reopen it to add lines.

FieldRequiredRule
Tax typerequiredpick 1 of 5 classifications: VAT · Excise · Environmental · Luxury · Personal income tax (PIT) - only active classifications are offered
Tax raterequiredentered as a %; stored to exactly 4 decimal places; displayed with 2 (e.g. 10.00%)
Included in pricetoggledefault not included
Priorityrequiredinteger ≥ 1 (default 1); when a product matches several lines, the lowest-numbered line applies first
DirectionrequiredSale (default) · Purchase
Tax bearerrequiredCustomer (default) · Merchant
  • Lines are added / edited via a dialog; deleting a line shows a confirmation naming the line's rate.
  • The line table shows: Tax type (colored label per classification) · Rate % · Included in price (Yes/No) · Priority · Direction · Tax bearer.
  • Above the table sits a summary line of the group's rates, e.g. VAT 10.00% incl · Environmental 2.00% excl.

FR-4 - Provision tax onto products (background) ✅

When a product is assigned a tax group (at product create or update), the tax engine provisions all of the group's tax lines onto the product. There is no action for this on the screen - the screen only authors the template.

FR-5 - Reconcile on product change (background) ✅

When a product is changed or removed, the engine recomputes its provisioned tax against the current group - a product never keeps tax from a stale configuration.

FR-6 - Tax method compatibility 🚧

Rule to build: a tax group may only be assigned to merchants with the same tax method - Deduction groups only to merchants filing under deduction, Direct groups only to merchants filing directly. Today the screen has no check at all: any group can be assigned to any merchant, and correctness rests on the Operations team. Enforcement is needed where groups are assigned, plus a warning while authoring.

Acceptance criteria

  • Creating a group without identifier, name, tax method, or status → form error, nothing saved; a name longer than 200 characters → error.
  • A new group defaults to the Deduction method and Activated status.
  • The list filters on all 4 columns; deleting a group always goes through a confirmation naming its identifier.
  • Tax lines can only be added once the group is saved (on the edit screen).
  • Entering a rate of 10 → the table shows 10.00%; the stored value keeps exactly 4 decimal places.
  • A priority of 0 or negative → error (minimum 1).
  • The tax-type dropdown offers only active classifications, covering all 5: VAT / Excise / Environmental / Luxury / PIT.
  • Deleting a tax line always goes through a confirmation naming its rate; the summary line updates accordingly.
  • 🚧 (once FR-6 is built) Assigning a Deduction group to a direct-method merchant → blocked with a message.

7. Non-Functional Requirements

AreaRequirement
ConsistencyProvisioned tax is reconciled by the engine on product change; no tax from a stale configuration remains
Compatibility🚧 A tax group is assignable only to merchants with the same tax method (FR-6, not built)
AuthzOnly Back-Office accounts with tax-configuration permission can operate this screen
i18nGroup name and description are entered bilingually (EN/VI); method / status / tax-type labels display bilingually

8. UX & Flows

How the Operations team authors a tax group:

Screen structure and the background part:

The screen lives in the Back Office "System Configuration" section.

9. Data & Domain

ConceptRole in this screen
Tax groupA reusable template: one tax method + multiple tax rate lines
Tax rate lineOne line in a group: tax type, %, included in price, priority, direction, tax bearer
Tax typeThe classification a line belongs to: VAT / Excise / Environmental / Luxury / PIT
Tax methodDeduction or Direct - declared on the group; must match the merchant's method (FR-6 🚧)
Applied taxThe tax the engine provisions onto a product from its assigned group's lines

Conceptual only - provisioning and reconciliation run in the tax engine; the data model lives in the developer docs.

10. Dependencies & Assumptions

Depends on

  • Tax identity / method (Tax identity) - the source of the merchant's tax method that FR-6 must check against.
  • Products - where tax groups are assigned and tax lands (Products).

Assumptions

  • The Operations team is authenticated with tax-configuration permission.
  • Tax classifications (VAT, Excise…) are declared and active so the tax-type dropdown has data.

11. Risks & Open Questions

Risk / questionMitigation / status
Several tax lines matching the same productEach line carries a priority; the lowest number applies first
No tax-method compatibility check yet🚧 FR-6 - currently rests on the Operations team operating correctly
Mistyped rates (percent vs decimal confusion)Rates are entered as %, and the table plus the summary line echo xx.xx% immediately for an eyeball check

12. Release Plan & Launch Criteria

AspectPlan
PhaseP1 - available in the Back Office
RolloutTax-configuration users; no feature flag
MigrationNone - it configures the existing tax engine
Launch criteriaA group can be authored with all 5 fields plus tax lines with all 6 fields; the list filters on 4 columns; assigned products receive the group's full line set; product changes are reconciled by the engine
MonitoringGroup / tax-line edits; engine reconciliation outcomes

13. FAQ

What is a tax group? A reusable template: one tax method + multiple tax rate lines (tax type, %, included in price…), assigned to products so tax applies automatically.

Why can't I add tax lines right after creating a group? Lines are managed on the edit screen - saving a group returns to the list; reopen the group to add its lines.

What happens when a product changes? The engine reconciles its provisioned tax against the current group, so no stale tax remains.

Why can't I use a tax group on a merchant? By design a group is only assignable to merchants with the same tax method - this check is not built yet (FR-6), so nothing blocks it today.

References

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