Ledger Service
@nx/ledger tạo sổ kế toán HKD (Hộ Kinh Doanh) chính thức của Việt Nam. Một worker do Kafka điều khiển lấy dữ liệu kinh doanh, render PDF (Typst) + XLSX (ExcelJS), mã hoá bằng AES-256-GCM, và upload lên S3. Nó cũng sở hữu vòng đời sổ (DRAFT → FINALIZED → revise), chỉnh sửa draft dựa trên snapshot, và cấu hình hàng năm theo từng merchant. Dữ liệu thượng nguồn đến từ các repository @nx/core (finance/sale/merchant); file được lưu qua MetaLink của @nx/asset.
1. Tham chiếu nhanh
| Thuộc tính | Giá trị |
|---|---|
| Package | @nx/ledger |
| Code | SVC-00060-LEDGER |
| Type | Microservice |
| Runtime | Bun |
| Base Class | VerifierApplication |
| Location | packages/ledger |
| Base Path | /v1/api/ledger |
| Dev Port | 31060 |
| Container Port | 3000 (ngoài 31060) |
| Snowflake ID | 6 |
| DB Schema | ledger (6 bảng) |
| Binding Namespace | @nx/ledger |
| Application Roles | api và/hoặc worker (APP_ENV_APPLICATION_ROLES, mặc định cả hai) |
2. Mục đích & Phạm vi
| Bao gồm | Loại trừ |
|---|---|
| 6 biểu mẫu sổ HKD (S1a, S2a–S2e) | Engine tính/khai thuế |
| Pipeline tạo bất đồng bộ (fetch → render → encrypt → upload) | Thanh toán / hoá đơn (sở hữu bởi @nx/payment, @nx/invoice) |
| Render PDF (Typst) + XLSX (ExcelJS) | Zod schema + Drizzle model của ledger (nằm trong @nx/core) |
Vòng đời sổ DRAFT → FINALIZED → revise (version mới) | Vận chuyển lưu trữ file (uỷ thác cho MetaLink/S3 của @nx/asset) |
| Chỉnh sửa draft dựa trên snapshot + theo dõi staleness | Nộp lên cơ quan thuế (status SUBMITTED đã dành chỗ, chưa xây) |
| Config hàng năm theo từng merchant + bậc khai thuế | — |
| Quét phục hồi job kẹt + retry/regenerate thủ công | — |
| Thông báo trạng thái job qua WebSocket thời gian thực (role worker) | — |
3. Tech Stack
External:
| Library | Mục đích |
|---|---|
@venizia/ignis | IoC container, DI, BaseService, BaseRestController, ControllerFactory |
@venizia/ignis-helpers | Logger, Kafka helpers, Redis, WebSocketEmitter, AES, BunS3Helper |
@platformatic/kafka | Kafka producer + consumer client |
@myriaddreamin/typst-ts-node-compiler | Typst NodeCompiler — render PDF |
exceljs | Builder workbook XLSX |
hono + @hono/zod-openapi + @scalar/hono-api-reference | HTTP server, OpenAPI, explorer /doc |
drizzle-orm + pg | Truy cập DB qua PostgresCoreDataSource |
lodash | Tiện ích |
Internal:
| Package | Mục đích |
|---|---|
@nx/core | VerifierApplication, schema/model ledger, repository, KafkaTopics, LedgerStatuses/LedgerIdentifiers/PeriodTypes, LedgerErrors, channel/room WS |
@nx/asset | MetaLinkService / MetaLink — upload + download file đã tạo lên S3 |
4. Cấu trúc dự án
packages/ledger/
├── src/
│ ├── application.ts # subclass VerifierApplication; wiring có cổng role
│ ├── index.ts # bootstrapApplication()
│ ├── migrate.ts # bootstrapMigration()
│ ├── common/ # constants, keys, rest-paths, roles, environments, types
│ ├── components/ # kafka (producer+consumer), recovery, websocket, stress-test*
│ ├── controllers/ # actions, crud, batch, merchant-ledger-config
│ ├── datasources/ # PostgresCoreDataSource
│ ├── helpers/ # S3Helper (singleton BunS3Helper lazy)
│ ├── migrations/processes/ # 4 seed migration
│ ├── models/ # zod request/response schema
│ ├── repositories/ # re-export từ @nx/core
│ ├── services/ # business logic + fetchers/ + generators/
│ └── utilities/ # buildPeriodString, filename helper
├── resources/templates/ # 6 Typst .typ + common.typ + previews/
├── package.json
└── tsconfig.json* stress-test/ tồn tại nhưng không được đăng ký trong application.ts.
5. 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/ledger/doc/openapi.json (Scalar viewer tại /doc, portal gateway). Chỉ đăng ký trong role api; thứ tự quan trọng (LedgerActionsController trước để tránh /:id che mất).
| Controller | Base path | Bề mặt |
|---|---|---|
LedgerActionsController | /ledgers | generate, status, retry, download, check-exists, search, snapshot pull/get, acknowledge-change, finalize, regenerate, revise |
LedgerController | /ledgers | CRUD (find/findById/findOne/count phạm vi merchant) |
LedgerBatchController | /ledgers | status/batch, generate/batch, retry/batch |
MerchantLedgerConfigController | /merchant-ledger-configs | create, list (theo merchant+year), update, confirm |
Bề mặt async — tham chiếu đầy đủ trong API Events:
| Hướng | Kênh | Số lượng |
|---|---|---|
| Inbound | Kafka ledger.generate | 1 topic (role worker) |
| Outbound | Kafka ledger.generate | 1 topic (enqueue + recovery re-enqueue) |
| Outbound | WebSocket | 1 topic (observation/ledger/job/status, role worker) |
| BullMQ | — | không |
8. Components
Đăng ký trong
configureComponents()(bỏ qua hoàn toàn khiRUN_MODE=migrate). WebSocket chỉ đăng ký trong roleworker; Kafka consumer + recovery sweep đăng ký vô điều kiện nhưng tự bỏ qua trừ khi role worker active.
| Component | File | Mục đích |
|---|---|---|
KafkaProducerComponent | src/components/kafka.component.ts | Khởi tạo producer, bind APPLICATION_KAFKA_PRODUCER |
KafkaConsumerComponent | src/components/kafka.component.ts | Chỉ worker; N consumer trên ledger.generate → LedgerWorkerService.handleGeneration() |
RecoveryComponent | src/components/recovery.component.ts | Chỉ worker; quét job kẹt định kỳ → reset PENDING + re-enqueue |
LedgerWebSocketComponent | src/components/websocket.component.ts | Chỉ worker; WebSocketEmitter qua Redis, đăng ký LedgerNotificationService |
9. Services
Luôn đăng ký (
apihoặcworker) trừ khi đánh dấu chỉ-worker.
| Service | File | Một dòng |
|---|---|---|
LedgerService | services/ledger.service.ts | CRUD/truy vấn bản ghi sổ (findExisting, findOrCreateDraft, saveSummary) |
LedgerJobService | services/ledger-job.service.ts | Máy trạng thái LedgerJob: setProcessing/Completed/Rejected, quét job kẹt |
LedgerSnapshotService | services/ledger-snapshot.service.ts | Chỉnh sửa draft: pull, getSnapshot, acknowledgeChange, finalize, revise |
MerchantLedgerConfigService | services/merchant-ledger-config.service.ts | Config theo merchant theo năm; giải loại bắt buộc, validate batch |
MetaLinkService | services/meta-link.service.ts | Upload S3/MetaLink + download đã giải mã (qua @nx/asset) |
LedgerQueueService | services/ledger-queue.service.ts | Điều phối enqueue: enqueue, batch, retry, regenerate |
LedgerDataFetcherService | services/ledger-data-fetcher.service.ts | Facade fetcher theo loại (validate, fetch) |
S1aHkdDataFetcherService | services/fetchers/ | S1a-HKD — dữ liệu thật (finance/sale/merchant/tax-info) |
S2xHkdDataFetcherService | services/fetchers/ | S2a–S2e — dữ liệu fixture (placeholder) |
LedgerDataFixtureService | services/ledger-data-fixture.service.ts | Đọc JSON fixture đã tạo sẵn |
StorageEncryptionService | services/storage-encryption.service.ts | Encrypt/decrypt AES-256-GCM |
LedgerWorkerService (worker) | services/ledger-worker.service.ts | Điều phối pipeline; chỉ động LedgerJob.status |
PdfGeneratorService (worker) | services/generators/pdf-generator.service.ts | Render PDF bằng Typst NodeCompiler (singleton lazy) |
XlsxGeneratorService (worker) | services/generators/xlsx-generator.service.ts | Builder workbook ExcelJS |
LedgerNotificationService (worker) | services/ledger-notification.service.ts | Emitter WS job-status (đăng ký bởi component WS) |
10. Repositories
Tất cả re-export từ
@nx/core; bind trongconfigureRepositories(). Package không sở hữu schema nào.
| Repository | Table / Source | Ghi chú |
|---|---|---|
LedgerRepository | ledger.Ledger | Sở hữu |
LedgerJobRepository | ledger.LedgerJob | + setProcessing, setCompletedIfProcessing, query job kẹt |
LedgerSnapshotRepository | ledger.LedgerSnapshot | Sở hữu |
LedgerSnapshotEntryRepository | ledger.LedgerSnapshotEntry | Sở hữu |
MerchantLedgerConfigRepository | ledger.MerchantLedgerConfig | Sở hữu |
TaxDeclarationLevelRepository | ledger.TaxDeclarationLevel | Sở hữu |
MetaLinkRepository | @nx/asset | Link file đã tạo |
MerchantRepository, TaxInfoRepository, VnProvinceRepository, VnWardRepository | @nx/core | Đọc xuyên package (header S1a) |
FinanceTransactionRepository, SaleOrderRepository | @nx/core | Đọc xuyên package (entries S1a) |
PermissionRepository, RoleRepository, PolicyDefinitionRepository | @nx/core | Seed authorization |
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 + roles + 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:
Tham chiếu — tra cứu:
- API Events
- Configuration
- Operations
- REST endpoints — OpenAPI trực tiếp tại
/v1/api/ledger/doc/openapi.json(Scalar viewer tại/doc, portal gateway)
Tính năng — đào sâu:
- Generation Pipeline
- HKD Templates
- Client Guide — hướng dẫn
Decisions: