ADR-0001. Hai lớp provider-adapter: @nx/iiapi và @nx/t-van
| Trường | Giá trị |
|---|---|
| Status | Accepted |
| Date | 2026-04-01 |
| Deciders | Phat Nguyen |
| Supersedes | - |
Bối cảnh
- Hoá đơn điện tử Việt Nam đến cơ quan thuế qua các kênh khác nhau: provider HĐĐT trực tiếp (VNIS, VNPAY) và gateway transaction-VAN (T-VAN).
- Hai kênh có cấu trúc SDK, mô hình xác thực và cách lưu thông tin xác thực khác nhau (theo từng merchant so với một kết nối nền tảng duy nhất).
- DB mã hoá enum provider riêng (
InvoiceProviders), không được để enum iiapi (IIAPIProviders) lọt vào tầng lưu trữ. - Thông tin xác thực khác nhau theo từng kênh: VNIS dùng một hàng
Configurationcấp nền tảng; VNPAY dùng các hàngInvoiceProvidertheo từng merchant; T-VAN dùng một hàngConfigurationcấp nền tảng.
Quyết định
Chúng ta sẽ bọc mỗi kênh trong package adapter riêng và đăng ký chúng bằng các component riêng:
@nx/iiapi(VNIS + VNPAY) đăng ký bởiInvoiceProviderConnectionComponent.@nx/t-van(gateway T-VAN, provider VNPAY) đăng ký bởiTVanConnectionComponent.
Enum provider DB↔iiapi được bắc cầu bởi InvoiceProviderMapper (src/common/providers.ts), sẽ ném lỗi khi gặp provider không xác định. Tầng lưu trữ chỉ lưu các giá trị InvoiceProviders.
Hệ quả
| Ưu | Nhược |
|---|---|
| Mỗi kênh phát triển độc lập | Phải bảo trì hai component đăng ký + hai đường khởi động |
| Tầng lưu trữ tách khỏi enum của nhà cung cấp | Mapper phải cập nhật khi thêm provider mới |
| Mô hình thông tin xác thực theo merchant và theo nền tảng tách bạch rõ ràng | Hiện chỉ ánh xạ VNPAY - các provider khác ném lỗi cho tới khi được thêm |
| Thêm provider = mở rộng mapper + adapter, không đổi schema | Hai đường nạp thông tin xác thực (hàng Configuration so với hàng provider) |
Phương án đã cân nhắc
| Phương án | Ưu | Nhược | Vì sao loại |
|---|---|---|---|
| Một adapter cho mọi kênh | Ít component hơn | Ép một cấu trúc SDK lên các API không tương thích | Các kênh quá khác nhau (trực tiếp so với VAN) |
| Lưu enum iiapi trực tiếp trong DB | Không cần mapper | Enum nhà cung cấp lọt vào tầng lưu trữ; phát sinh nhiều migration | Ràng schema vào package bên thứ ba |
| Cấu hình T-VAN theo từng merchant | Đối xứng với VNPAY | T-VAN hiện chỉ là một gateway nền tảng duy nhất | Quá mức cần thiết so với nhu cầu hiện tại |
Tham chiếu
src/common/providers.ts(InvoiceProviderMapper)src/components/invoice-provider-connection/component.tssrc/components/tvan-connection/component.tssrc/migrations/data/configuration.ts(VNIS_DEFAULT_CONNECTION,TVAN_DEFAULT_CONNECTION)