Invoice Numbering
Overview
Invoice numbering is provider-side. The sequential invoice number (số hóa đơn) is allocated by VNPAY (viiAPI) and returned to BANA in the issuance response. @nx/invoice never generates or reserves numbers locally - there is no local counter (no Redis sequence, no gap/audit bookkeeping).
The only numbering input BANA supplies is the invoiceSymbol (serial / ký hiệu), read from the merchant's provider config. VNPAY assigns the next number within that symbol and returns it; BANA persists it.
What @nx/invoice Does
| Concern | Owner | Detail |
|---|---|---|
Sequential number (số hóa đơn) | VNPAY (provider) | Allocated provider-side, returned in the issuance response |
invoiceSymbol (ký hiệu) | @nx/invoice (sends) | Read from TInvoiceProviderConfig.invoiceSymbol, placed in the JSON request by _buildInvoiceRequest |
| Returned number | @nx/invoice (persists) | response.data.invoiceNumber stored on the Invoice record |
| Sequence / gap integrity | VNPAY + GDT | Enforced provider-side; not tracked in BANA |
Allocation Flow
Invoice Symbol (ký hiệu)
The symbol is GDT-defined and stored in the merchant's provider config; BANA forwards it unchanged. It is the only numbering field BANA sends.
[Position 1][Year 2-digit][Template Type][Sequence Letters]
Example: C25TAA
C = Business-issued (T = generated by tax authority)
25 = Year 2025
T = E-Invoice type (G = VAT Invoice)
AA = Serial (merchant-defined, registered with the GDT)