Skip to content

Finance Service

@nx/finance is the bookkeeping engine. It owns accounts (wallets) and a double-entry ledger built from journal vouchers (RECEIPT / PAYMENT / TRANSFER / ADJUSTMENT), each posting balanced DEBIT/CREDIT FinanceTransaction lines. It is event-driven first: most postings are created automatically by reacting to Kafka topics from sale, inventory, and merchant CDC — direct REST is reserved for manual vouchers, account management, and reporting.

1. Quick Reference

PropertyValue
Package@nx/finance
CodeSVC-00040-FINANCE
TypeMicroservice
RuntimeBun
Base ClassVerifierApplication
Locationpackages/finance
Base Path/v1/api/finance
Dev Port31040
Container Port3000 (external 31040)
Snowflake ID4
DB Schemafinance (6 tables)
Binding Namespace@nx/finance

2. Purpose & Scope

IncludedExcluded
Accounts / wallets (CASH, BANK, QR_CODE, MOBILE_POS) + internal control accounts (INVENTORY, COGS)Payment provider/gateway processing (owned by @nx/mq-pay)
Double-entry vouchers (RECEIPT / PAYMENT / TRANSFER / ADJUSTMENT) with DEBIT/CREDIT ledger linesSale-order lifecycle (owned by @nx/sale)
Per-merchant/type voucher numbering (PT/PC/PCK/PKT)Stock quantities / costing math (owned by @nx/inventory)
Income/expense category hierarchy (14 seeded system categories)Tax invoice issuance (owned by @nx/invoice)
Auto-posting from PAYMENT_SUCCESS, PURCHASE_ORDER_RECEIVED, INVENTORY_ISSUED_FOR_SALE, INVENTORY_ADJUSTEDLoyalty / customer points (owned by @nx/sale)
Default-account reconciliation on merchant CDC + onboarding stepMulti-currency conversion (single-currency per voucher; exchangeRate reserved)
Payment-integration credential storage (masked, per-merchant/terminal)
Voucher void via balanced reversal

3. Tech Stack

External:

LibraryPurpose
@venizia/ignisIoC container, DI, BaseService, BaseController, ControllerFactory
@venizia/ignis-helpersLogger, KafkaProducerHelper / KafkaConsumerHelper, WebSocketEmitter, float()
@platformatic/kafkaKafka client (producer + consumer)
honoHTTP server (via IGNIS)
@hono/zod-openapiOpenAPI generator from Zod schemas
@scalar/hono-api-referenceOpenAPI explorer at /doc
drizzle-ormDB access via PostgresCoreDataSource
pgPostgreSQL driver
lodashUtilities

Internal:

PackagePurpose
@nx/coreSchemas, repositories (re-exported), VerifierApplication, FinanceVoucherService, FinanceAccountService, PaymentIntegrationService, KafkaTopics/CDCKafkaTopics, all finance constants
@nx/assetApplicationAssetBanksVNComponent — Vietnamese bank reference data

4. Project Structure

packages/finance/
├── src/
│   ├── application.ts                 # VerifierApplication subclass
│   ├── index.ts                       # bootstrapApplication()
│   ├── migrate.ts                     # bootstrapMigration()
│   ├── common/
│   │   ├── keys.ts                    # BindingKeys (Kafka producer/consumer, Redis cache)
│   │   ├── rest-paths.ts              # 5 RestPaths
│   │   └── types.ts                   # local types
│   ├── components/
│   │   ├── kafka/                     # ApplicationKafkaComponent (producer + 5-topic consumer)
│   │   └── websocket/                 # ApplicationWebSocketComponent + FinanceSocketEventService
│   ├── controllers/                   # 5 controller folders (account, category, transaction, voucher, payment-integration)
│   ├── datasources/                   # PostgresCoreDataSource
│   ├── migrations/processes/          # 3 migrations (categories, permissions, role-permissions)
│   ├── models/                        # zod request/response schemas
│   ├── repositories/                  # re-exports from @nx/core
│   ├── resources/                     # app-info.json, banner.txt
│   └── services/                      # FinanceWorkerService, FinanceIntegrationService
├── package.json
└── tsconfig.json

5. Architecture

Detail: see Architecture.

6. Domain Snapshot

Full ERD + per-entity tables: see Domain Model.

7. Surface Summary

REST controllers — full reference rendered live from /v1/api/finance/doc/openapi.json (live spec — Scalar viewer at /doc, gateway portal):

ControllerBase pathNotes
FinanceAccountController/finance-accountsCRUD + overview; merchant-scoped via Casbin GROUP policies (non-admins see only granted merchants)
FinanceCategoryController/finance-categoriesCRUD (read-oriented; system + custom categories)
FinanceTransactionController/finance-transactionsCRUD (ledger lines; mostly read)
FinanceVoucherController/finance-vouchersRead-only CRUD (count/find/findById/findOne) + custom actions: createDraft, updateDraft, deleteDraft, approve, issueDirect, voidVoucher, overview
PaymentIntegrationController/payment-integrationsProvider / merchant-config / terminal-config; credentials masked in responses

Async surface — full reference in API Events:

DirectionChannelCount
InboundKafka (4 domain + 1 CDC)5 topics
OutboundKafka0 (producer initialized for future use; nothing published)
OutboundWebSocketemitter registered (finance-ws-emitter); no domain topics wired yet

8. Components

ComponentFilePurpose
ApplicationKafkaComponentsrc/components/kafka/component.tsIdempotent producer (acks=ALL, lz4) + consumer (autocommit off, fallback latest) subscribed to 5 topics, dispatched to FinanceWorkerService
ApplicationWebSocketComponentsrc/components/websocket/component.tsRedis-backed WebSocketEmitter (single or cluster) + FinanceSocketEventService
ApplicationAssetBanksVNComponentfrom @nx/assetVietnamese bank reference data
Cache RedisuseCacheRedis() (parent)Authorization permission cache

9. Services

ServiceFileOne-liner
FinanceWorkerServicesrc/services/finance-worker.service.tsKafka event handlers — turns sale/inventory/merchant events into vouchers; reconciles default + control accounts on merchant CDC
FinanceIntegrationServicesrc/services/finance-integration.service.tsMasks payment-integration credentials in account responses; builds/attaches integration bundles
FinanceVoucherService@nx/coreDouble-entry posting engine: issueDirect, draft lifecycle, void (balanced reversal), getOverview, balance/posting-sequence math
FinanceAccountService@nx/coreAccount create-with-opening-balance, update, getOverview
PaymentIntegrationService@nx/corePayment-integration CRUD + credential encryption

10. Repositories

All re-exported from @nx/core (src/repositories/index.ts). Owned tables in the finance schema; the rest are cross-package reads.

RepositoryTable / SourceNotes
FinanceAccountRepositoryfinance.FinanceAccount+ assertAccountsOwnedByMerchant
FinanceTransactionRepositoryfinance.FinanceTransactionledger lines
FinanceCategoryRepositoryfinance.FinanceCategorysystem + custom
FinanceVoucherRepositoryfinance.FinanceVoucher+ next-number lookups, findExistingForSource(Event), getOverview
FinanceVoucherSequenceRepositoryfinance.FinanceVoucherSequence+ next (per merchant/type/yearMonth)
PaymentIntegrationRepositoryfinance.PaymentIntegrationmasked credentials
ConfigurationRepository@nx/corereads DEFAULT_FINANCE_ACCOUNTS system config
MerchantRepository / OrganizerRepository@nx/coremerchant CDC reconciliation + onboarding step
PurchaseOrderRepository / VendorRepository@nx/coreresolve PO + vendor party for PAYMENT voucher
PermissionRepository / RoleRepository / PolicyDefinitionRepository@nx/coreseeds + merchant-scoped account filtering

11. Entry Points

FilePurpose
src/index.tsService entry → bootstrapApplication()
src/migrate.tsMigration entry → bootstrapMigration()
src/application.tsApplication extends VerifierApplication

12. Configuration

Env vars + seeded data: see Configuration.

13. Operations

Deployment + observability + security + runbook: see Operations.

Concepts — why/how:

Reference — lookup:

Decisions:

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