Skip to content

Architecture

1. System Context (C4 L1)

2. Container View (C4 L2)

Không có component Redis, BullMQ, hay WebSocket. Bề mặt async duy nhất là một CDC consumer.

3. Component View (C4 L3) — Phân lớp nội bộ

LayerTrách nhiệm
ControllersAuth (jwt/basic) + cổng permission + map DTO; CRUD qua ControllerFactory
ApplicationKafkaComponentSubscribe CDCKafkaTopics.PRODUCT, deserialize payload Debezium, route tới worker
TaxationWorkerServiceMap op CDC (c/u/r/d) + state sản phẩm tới provision/deprovision
TaxProvisioningServiceGhi idempotent TaxSet+Tax từ một template TaxGroup
TaxGroupServiceValidate tương thích merchant taxMethod ↔ group
RepositoriesTruy vấn Drizzle trên schema @nx/core; soft-delete

4. Chỉ mục State Machine

EntityTrạng tháiSơ đồ
TaxSetACTIVATED, DEACTIVATED, ARCHIVED→ jump

TaxSet (vòng đời provisioning)

TừSự kiệnĐếnGuards
[*]provisionForProductACTIVATEDTaxGroup tồn tại, có ≥1 item
ACTIVATEDre-provision (group khác)DEACTIVATED (cũ)chỉ khi sourceType = TaxGroup
ACTIVATEDdeprovisionForProductDEACTIVATEDchỉ khi sourceType = TaxGroup
ACTIVATEDcùng groupACTIVATED (no-op)skip idempotent

Chỉ TaxSet có nguồn từ TaxGroup được chạm tới. TaxSet tạo thủ công (override variant, sourceType chưa set) không bao giờ bị provisioning deactivate.

5. Kịch bản Runtime

5.1 CDC reconcile khi tạo/cập nhật sản phẩm

BướcChi tiết
2-3fallbackMode: latest — chỉ consume thay đổi live; không backfill lịch sử
4Dòng snake_case Debezium convert qua toCamelCaseKeys
5Sản phẩm soft-deleted (deletedAt) deprovision trước khi check taxGroup
elseProvision idempotent: cùng (sourceType=TaxGroup, sourceId) → skip

5.2 CDC delete

5.3 Provisioning thủ công qua REST

6. Mối quan tâm xuyên suốt

Mối quan tâmCách service này xử lý
AuthNJWT (Issuer = identity) + HTTP Basic; strategy ['jwt','basic'] trên mọi route
AuthZPermission resource-based seed theo từng controller; cấp cho OWNER/EMPLOYEE/CASHIER khi bootstrap
i18nCột jsonb i18n('name') ({ default, en, vi }) trên tên TaxGroup, TaxGroupItem, Tax
LoggingKey-value có cấu trúc (key: %s); scope logger.for(method) trong service
TracingKhông có tracer riêng
IdempotencyProvision skip khi TaxSet active đã có nguồn từ cùng TaxGroup (ADR-0001)
Soft-deleteSoftDeletableRepository (deletedAt); deprovision dùng status DEACTIVATED, không bao giờ hard-delete
IDsSnowflake qua IdGenerator, worker id 13 (hardcode — rủi ro collision nếu scale)

7. Trang liên quan

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