ADR-0002. TaxInfo có thẩm quyền, nguồn từ Merchant CDC — không phải metadata.tax của commerce
| Trường | Giá trị |
|---|---|
| Status | Accepted |
| Date | 2026-04-08 |
| Deciders | invoice-team, commerce-team |
| Supersedes | — |
Bối cảnh
- Định danh thuế merchant (MST: taxCode, fullName, address, mã hành chính) được nhập trong
@nx/commercedưới dạngMerchant.metadata.tax. - Invoice service cần một bản ghi thuế đã chuẩn hoá, truy vấn được, có relation (
tax.TaxInfo) cho payload phát hành và hiển thị FE. metadata.taxlà jsonb tự do trên một service khác — không phù hợp làm bản ghi có thẩm quyền mà domain invoice đọc từ đó.- Before-image của Debezium không đáng tin cho phát hiện thay đổi (phụ thuộc REPLICA IDENTITY của bảng).
Quyết định
Chúng ta sẽ coi metadata.tax là chỉ input và tax.TaxInfo (principalType=Merchant) là bản ghi có thẩm quyền.
InvoiceWorkerService.handleMerchantCDC consume topic Merchant CDC; TaxInfoService.syncTaxInfo upsert TaxInfo. Với op=u nó diff thuế đến với TaxInfo đã lưu (không phải before-image của Debezium) và bỏ qua khi không đổi. Frontend đọc relation merchant.taxInfo, không bao giờ metadata.tax.
Hệ quả
| Ưu | Nhược |
|---|---|
| Một bản ghi thuế có thẩm quyền, có relation | Nhất quán cuối cùng — phụ thuộc độ trễ CDC |
| Phát hiện thay đổi đúng bất kể REPLICA IDENTITY | Thêm một lần đọc (nạp TaxInfo đã lưu) mỗi cập nhật |
| FE/phát hành tách khỏi hình dạng jsonb của commerce | Tồn tại hai biểu diễn "thuế" (input + có thẩm quyền) |
| Re-delivery idempotent (không đổi → skip) | Yêu cầu pipeline Debezium khoẻ mạnh |
Phương án đã cân nhắc
| Phương án | Ưu | Nhược | Vì sao loại |
|---|---|---|---|
Đọc metadata.tax trực tiếp lúc phát hành | Không cần CDC | Ràng jsonb xuyên service; không chuẩn hoá | Mong manh; FE không relation-join được |
| Tin before-image Debezium để diff | Không thêm read | Không đáng tin nếu không FULL replica identity | Gây skip/update sai |
| Gọi HTTP đồng bộ tới commerce mỗi lần phát hành | Luôn tươi mới | Latency + ràng buộc availability | Phá vỡ thiết kế event-driven |
Tham chiếu
src/services/invoice-worker.service.ts(handleMerchantCDC,_resyncMerchantTaxInfoIfChanged,_isTaxInfoUpToDate)src/services/tax-info.service.ts(syncTaxInfo)packages/core/src/models/schemas/tax/tax-info/schema.ts- Xem thêm: Integration §3.1