Pricing Service
@nx/pricing là một service IGNIS độc lập (REST API + Kafka CDC worker) định giá các dòng bán được: nó chọn fare thắng cho mỗi product variant, tính thuế kép, theo dõi giá vốn variant, và quản lý khuyến mãi. Service anh em gọi nó qua HTTP và import types request/response cộng vài runtime snapshot const container từ @nx/pricing/contracts — họ không mount nó như một component.
1. Tham chiếu nhanh
| Thuộc tính | Giá trị |
|---|---|
| Package | @nx/pricing |
| Code | SVC-00070-PRICING |
| Type | Microservice |
| Runtime | Bun |
| Base Class | VerifierApplication |
| Location | packages/pricing |
| Base Path | /v1/api/pricing |
| Dev Port | 31070 |
| Container Port | 3000 (ngoài 31070) |
| Snowflake ID | 7 |
| DB Schema | pricing (9 bảng) |
| Binding Namespace | @nx/pricing |
| Run Modes | api (REST + Kafka CDC consumer lúc boot) · migrate |
2. Mục đích & Phạm vi
| Bao gồm | Loại trừ |
|---|---|
| Chọn fare cho mỗi ProductVariant (default / OVERRIDE / child fare theo rule) | Lưu order (sở hữu bởi @nx/sale) |
| Tính thuế kép, gom theo priority (cấp item + order) | Phát hành hoá đơn / HĐĐT (sở hữu bởi @nx/invoice) |
| Pricing snapshot (bất biến theo từng dòng + từng order, v2) | Thay đổi stock / inventory (sở hữu bởi @nx/inventory) |
| Theo dõi giá vốn variant với khoảng ngày hiệu lực | Xử lý thanh toán (sở hữu bởi @nx/mq-pay) |
| CRUD Promotion / PromotionMethod / Rule | Tính giảm giá/phí (entity tồn tại; calculator chưa wire) |
Seed FareSet qua CDC từ sự kiện ProductVariant | Sở hữu bất kỳ DB schema nào — mọi schema nằm trong @nx/core |
Hai pipeline tính: /simulation (v1) + /simulation-v2 (v2, canonical) |
3. Tech Stack
External:
| Library | Mục đích |
|---|---|
@venizia/ignis | IoC container, DI, BaseService, BaseController, ControllerFactory |
@venizia/ignis-helpers | Logger, toán tiền float(x, 4), Redis helper, Axios |
@platformatic/kafka | Kafka producer + CDC consumer (idempotent, lz4, SASL tuỳ chọn) |
hono + @hono/zod-openapi | HTTP server + sinh OpenAPI từ Zod |
@scalar/hono-api-reference | OpenAPI explorer tại /doc |
drizzle-orm / pg | Truy cập DB qua PostgresCoreDataSource |
lodash | get() cho đánh giá rule theo attribute-path |
Internal:
| Package | Mục đích |
|---|---|
@nx/core | Mọi schema (Fare, FareSet, Tax, TaxSet, TaxType, Rule, Cost, Promotion, PromotionMethod), VerifierApplication, CDCKafkaTopics, FareTypes, RuleOperators, IdGenerator |
4. Cấu trúc dự án
packages/pricing/
├── src/
│ ├── application.ts # subclass VerifierApplication
│ ├── index.ts # bootstrapApplication()
│ ├── migrate.ts # bootstrapMigration()
│ ├── common/ # RestPaths, BindingKeys, constants, env keys
│ ├── components/kafka/ # ApplicationKafkaComponent (producer + CDC consumer)
│ ├── contracts/ # Types publish + snapshot const container (sale import cái này)
│ ├── controllers/ # 11 REST controller
│ ├── datasources/ # PostgresCoreDataSource
│ ├── errors/ # Danh mục lỗi domain
│ ├── migrations/processes/ # 2 seed (permissions, role-permissions)
│ ├── models/ # zod request/response schema
│ ├── repositories/ # re-export + wrapper mỏng trên @nx/core
│ └── services/
│ ├── core/ # pipeline tính v1 (/simulation)
│ ├── core-v2/ # tính v2 + module pricing-snapshot (/simulation-v2)
│ ├── management/ # CRUD + service aggregate
│ └── pricing-worker.service.ts # subscriber CDC ProductVariant
├── package.json
└── tsconfig.json5. Kiến trúc
Chi tiết: xem Architecture.
6. Ảnh chụp Domain
ERD đầy đủ + bảng theo từng entity: xem Domain Model.
7. Tổng quan bề mặt
REST controllers — tham chiếu đầy đủ render trực tiếp từ /v1/api/pricing/doc/openapi.json (Scalar viewer tại /doc, portal gateway):
| Controller | Base path | Route tuỳ chỉnh |
|---|---|---|
FareController | /fares | POST /groups, POST /children |
FareSetController | /fare-sets | — |
CostController | /costs | PUT /current, GET /product-variant/{id}/current |
TaxController | /taxes | — |
TaxSetController | /tax-sets | PATCH /{id}/aggregate |
TaxTypeController | /tax-types | — |
PromotionController | /promotions | POST /aggregate, PATCH /{id}/aggregate |
PromotionMethodController | /promotion-methods | — |
RuleController | /rules | — |
SimulationController | /simulation | POST /calculate (v1, flat) |
SimulationV2Controller | /simulation-v2 | POST /calculate (v2, snapshot) |
Bề mặt async — tham chiếu đầy đủ trong API Events:
| Hướng | Kênh | Số lượng |
|---|---|---|
| Inbound | Kafka CDC (CDCKafkaTopics.PRODUCT_VARIANT) | 1 |
| Outbound | Kafka | 0 (producer bound nhưng không dùng bởi domain logic) |
| WebSocket out | — | 0 |
| BullMQ jobs | — | 0 (không BullMQ / QueueComponent) |
8. Components
| Component | File | Mục đích |
|---|---|---|
ApplicationKafkaComponent | src/components/kafka/component.ts | Producer lz4 idempotent + CDC consumer trên PRODUCT_VARIANT; dispatch tới PricingWorkerService |
| Redis cache (parent) | bound tại BindingKeys.APPLICATION_REDIS_CACHE qua useCacheRedis() | Chỉ cache permission authorization |
9. Services
| Service | File | Một dòng |
|---|---|---|
PricingService | core/pricing.service.ts | Orchestrator v1 — mỗi item: chọn fare → tính thuế → cộng (concurrency 5); áp thuế cấp order khi có merchantId |
PricingFareCalculatorService | core/pricing-fare-calculator.service.ts | Nạp FareSet active, phân loại fare, chọn thắng (OVERRIDE trước, không thì thấp nhất) |
PricingRuleEvaluatorService | core/pricing-rule-evaluator.service.ts | Đánh giá rule logic AND qua lodash get() theo attribute path |
PricingTaxCalculatorService | core/pricing-tax-calculator.service.ts | Engine thuế kép, gom theo priority; back-calc inclusive, điều kiện số lượng |
ItemPriceCalculator | core/item-price-calculator.service.ts | Helper giá theo item cho pipeline v1 |
PricingV2Service | core-v2/pricing-v2.service.ts | Orchestrator v2 → pricing snapshot đầy đủ (rule áp theo dòng + tổng order theo bearer) |
FareCalculatorService | core-v2/fare-calculator.service.ts | Chọn fare v2 tạo TAppliedPrice |
TaxCalculatorService | core-v2/tax-calculator.service.ts | Engine thuế v2 tạo TAppliedTax[] |
BaseCalculatorService | core-v2/base-calculator.service.ts | Helper money/float dùng chung cho calculator v2 |
FareService | management/fare.service.ts | CRUD aggregate Fare / fare-group / child-fare / variant-pricing |
CostService | management/cost.service.ts | CRUD giá vốn variant với khoảng ngày (getCurrentCost hardcode principalType:'ProductVariant') |
TaxSetService | management/tax-set.service.ts | CRUD aggregate TaxSet + thuế của nó |
PromotionService | management/promotion.service.ts | CRUD aggregate Promotion + method + rules |
PricingWorkerService | services/pricing-worker.service.ts | Subscriber CDC ProductVariant — seed FareSet + default fare; seed FBT override child fare |
v1 và v2 chia sẻ ~90% logic fare/tax — sửa thường cần áp cả hai. CRUD
PromotionServicetồn tại nhưng chưa có discount calculator wire vào pipeline nào.
10. Repositories
| Repository | Table | Source | Method tuỳ chỉnh |
|---|---|---|---|
FareRepository | Fare | @nx/core | findByFareId, updateChildrenCount, updateRulesCount |
FareSetRepository | FareSet | @nx/core | — |
RuleRepository | Rule | @nx/core | findByFareId |
TaxRepository | Tax | @nx/core | — |
TaxSetRepository | TaxSet | @nx/core | — |
TaxTypeRepository | TaxType | @nx/core | — |
CostRepository | Cost | @nx/core | — |
PromotionRepository | Promotion | @nx/core | — |
PromotionMethodRepository | PromotionMethod | @nx/core | — |
PermissionRepository, RoleRepository, PolicyDefinitionRepository, MigrationRepository | — | @nx/core | Authorization + bookkeeping migration |
11. Entry Points
| File | Mục đích |
|---|---|
src/index.ts | Entry service → bootstrapApplication() |
src/migrate.ts | Entry migration → bootstrapMigration() |
src/application.ts | Application extends VerifierApplication |
12. Configuration
Env vars + dữ liệu seed: xem Configuration.
13. Operations
Triển khai + observability + bảo mật + runbook: xem Operations.
14. Trang liên quan
Khái niệm — vì sao/như thế nào:
- Architecture
- Domain Model
- Integration — tiêu thụ contracts gần-như-type-only của sale + commerce CDC
Tham chiếu — tra cứu:
- API Events
- Configuration
- Operations
- REST endpoints — OpenAPI trực tiếp tại
/v1/api/pricing/doc/openapi.json
Tính năng — đào sâu:
Decisions: