Skip to content

ADR-0001. Two provider-adapter layers: @nx/iiapi and @nx/t-van

FieldValue
StatusAccepted
Date2026-04-01
Decidersinvoice-team
Supersedes

Context

  • Vietnamese e-invoicing reaches the tax authority through different channels: a direct e-invoice provider (VNIS, VNPAY) and a transaction-VAN (T-VAN) gateway.
  • The two channels have different SDK shapes, auth models, and credential storage (per-merchant vs single platform connection).
  • The DB encodes its own provider enum (InvoiceProviders), which must not leak the iiapi enum (IIAPIProviders) into persistence.
  • Credentials differ per channel: VNIS uses a platform Configuration row; VNPAY uses per-merchant InvoiceProvider rows; T-VAN uses a platform Configuration row.

Decision

We will wrap each channel in its own adapter package and register them with separate components:

  • @nx/iiapi (VNIS + VNPAY) registered by InvoiceProviderConnectionComponent.
  • @nx/t-van (T-VAN gateway, VNPAY provider) registered by TVanConnectionComponent.

The DB↔iiapi provider enums are bridged by InvoiceProviderMapper (src/common/providers.ts), which throws on unknown providers. Persistence only ever stores InvoiceProviders values.

Consequences

ProsCons
Each channel evolves independentlyTwo registration components + boot paths to maintain
Persistence decoupled from vendor enumsMapper must be updated when a new provider is added
Per-merchant vs platform credential models cleanly separatedOnly VNPAY is mapped today — others throw until added
Adding a provider = extend mapper + adapter, no schema changeTwo credential-loading paths (Configuration row vs provider row)

Alternatives Considered

OptionProsConsWhy rejected
Single adapter for all channelsFewer componentsForces one SDK shape onto incompatible APIsChannels too different (direct vs VAN)
Store iiapi enum directly in DBNo mapperVendor enum leaks into persistence; migration churnCouples schema to a third-party package
Per-merchant T-VAN configSymmetric with VNPAYT-VAN is a single platform gateway todayOver-engineered for current need

References

  • src/common/providers.ts (InvoiceProviderMapper)
  • src/components/invoice-provider-connection/component.ts
  • src/components/tvan-connection/component.ts
  • src/migrations/data/configuration.ts (VNIS_DEFAULT_CONNECTION, TVAN_DEFAULT_CONNECTION)

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