Skip to content

Domain Model

Nguồn schema: packages/core/src/models/schemas/finance/. PostgreSQL schema finance, 6 bảng.

1. ERD đầy đủ

2. Entities

FinanceAccount

Thuộc tínhGiá trị
Bảngfinance.FinanceAccount
Nguồnpackages/core/src/models/schemas/finance/finance-account/
Soft-delete
Cột Owner IDmerchantId

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakeKhóa chính
merchantIdtextMerchant sở hữu
statustextACTIVATEDXem enum status
namei18n{ default, en, vi }
typetextXem enum loại tài khoản
providertextBANABANA / VNPAY / e-wallet / bank
productCodetextvd QR_MMS, PHONE_POS, INTERNAL_ACCOUNT
accountNumber / accountHoldertextĐịnh danh bank/e-wallet
detailsjsonbTheo từng loại (branch, swift, last4, drawer…)
unittextVNDTiền tệ tài khoản
currentBalancenumeric(15,4)0Số dư chạy duy trì theo mỗi hạch toán
postingSequenceLastValuebigint0Con trỏ ledger đơn điệu theo từng tài khoản
environmenttextproductionPhân vùng env
metadatajsonbisDefault, isExcluded, isPayable, isInternal

Enum loại tài khoản (FinanceAccountTypes):

Giá trịÝ nghĩa
100_CASHNgăn kéo tiền mặt vật lý
200_BANKTài khoản ngân hàng
300_QR_CODEChấp nhận QR (vd VNPAY QR_MMS)
400_MOBILE_POSTerminal POS di động/điện thoại (vd VNPAY PHONE_POS)
998_COGSKiểm soát nội bộ — giá vốn hàng bán (isInternal=true)
999_INVENTORYKiểm soát nội bộ — tài sản tồn kho (isInternal=true)

Enum status: ACTIVATED · DEACTIVATED · ARCHIVED.

Index chính:

TênCộtLoại
UPI_FinanceAccount_…provider_productCode_accountNumber_environmentpartialUnique (live, có provider+number)
UPI_FinanceAccount_merchantId_type_environmentpartialUnique default theo merchant/type (metadata.isDefault=true)
IDX_FinanceAccount_merchantId(_status / _provider_environment)Btree

FinanceVoucher

Thuộc tínhGiá trị
Bảngfinance.FinanceVoucher
Nguồnpackages/core/src/models/schemas/finance/finance-voucher/
Soft-delete
Cột Owner IDmerchantId

Trường (chọn lọc):

TrườngKiểuBắt buộcMặc địnhMô tả
typetextRECEIPT / PAYMENT / TRANSFER / ADJUSTMENT
statustextDRAFTDRAFT / ISSUED / VOIDED
voucherNumbertextGán khi issue (PT/PC/PCK/PKT + seq)
amountdecimal(15,4)Tổng header denormalized
unittextVNDTiền tệ phiếu (mọi dòng dùng chung)
partyTypetextCUSTOMER / VENDOR / EMPLOYEE / INTERNAL / EXTERNAL
partyId / partyName / partyAddresstext/i18npartyName ✓Snapshot party khi issue
reasoni18nDiễn giải
sourceTypetextMANUAL / SALE_ORDER / SALE_ORDER_REFUND / PURCHASE_ORDER / POS_SESSION / INVENTORY_ADJUSTMENT
sourceIdtextid chứng từ gốc
sourceEventUidtextIdempotency key theo từng-event (Kafka redeliver)
sessionIdtextQuy gán ca POS
transactionDatetimestamptzNgày kế toán
reversalVoucherIdtextPhiếu đối ứng khi void
issuedAt/issuedBy/voidedAt/voidedBy/voidReasonAudit vòng đời
metadatajsonbdraftLines, adjustmentReason, inventoryIssuance, inventoryAdjustment, refundOf

Map type / direction:

Loại phiếuQuy tắc hướng dòngTiền tố số
RECEIPT (Phiếu thu)mọi dòng DEBIT (suy ra)PT
PAYMENT (Phiếu chi)mọi dòng CREDIT (suy ra)PC
TRANSFER (Phiếu chuyển khoản)explicit theo dòng; Σ DEBIT == Σ CREDITPCK
ADJUSTMENT (Phiếu kế toán)explicit theo dòngPKT

Index chính:

TênCộtLoại
UPI_…merchantId_voucherNumberpartialUnique số theo merchant (live)
UPI_…merchantId_type_sourceType_sourceIdpartialDedup theo từng-source (loại trừ MANUAL/POS_SESSION/SALE_ORDER)
UPI_…sourceType_sourceEventUidpartialDedup theo từng-event (live, không void)

FinanceTransaction (dòng ledger)

Thuộc tínhGiá trị
Bảngfinance.FinanceTransaction
Nguồnpackages/core/src/models/schemas/finance/finance-transaction/
Soft-delete
Cột Owner IDmerchantId

Trường (chọn lọc):

TrườngKiểuBắt buộcMặc địnhMô tả
typetext100_DEBIT (balance lên) / 200_CREDIT (balance xuống)
statustextCOMPLETEDPENDING / COMPLETED / CANCELLED
amountdecimal(15,4)Số tiền dòng
unittextVNDTiền tệ (= unit tài khoản)
exchangeRatedecimal(19,6)1Dự trữ (một tiền tệ, luôn 1)
financeAccountIdtextTài khoản bị ảnh hưởng
financeCategoryIdtextPhân loại tùy chọn
financeVoucherIdtextPhiếu cha
lineNumberintegerVị trí trong phiếu
balanceBefore / balanceAfterdecimal(15,4)Snapshot tại thời điểm post
postingSequencebigintCon trỏ post đơn điệu theo từng tài khoản
referenceType / referenceIdtextLiên kết source đa hình (phản chiếu source phiếu)

Index chính: UPI_FinanceTransaction_financeAccountId_postingSequence (partial unique — một dòng cho mỗi con trỏ post của tài khoản).

FinanceCategory

Thuộc tínhGiá trị
Bảngfinance.FinanceCategory
Nguồnpackages/core/src/models/schemas/finance/finance-category/
Soft-delete
Cột Owner IDmerchantId (null = danh mục hệ thống)

Trường: identifier (unique), type (100_INCOME / 200_EXPENSE), name/description (i18n), parentId (phân cấp), status. Xem Configuration → Dữ liệu Seed cho 14 danh mục hệ thống.

FinanceVoucherSequence

Thuộc tínhGiá trị
Bảngfinance.FinanceVoucherSequence
Nguồnpackages/core/src/models/schemas/finance/finance-voucher-sequence/
Unique(merchantId, type, yearMonth)

Counter theo từng merchant / từng type / từng tháng. lastValue (bigint) được tăng dưới lock để tạo số phiếu tiếp theo.

PaymentIntegration

Thuộc tínhGiá trị
Bảngfinance.PaymentIntegration
Nguồnpackages/core/src/models/schemas/finance/payment-integration/
Soft-delete
Cột Owner IDprincipalId (Merchant / SaleChannel)

Trường (chọn lọc): financeAccountId, principalType (Merchant/SaleChannel), provider, productCode, integrationType (100_PAYMENT_PROVIDER / 200_MERCHANT_PAYMENT_CONFIG / 300_TERMINAL_PAYMENT_CONFIG), credential (encrypted), maskedValue, config (jsonb), status (ACTIVATED / ARCHIVED). Một partial unique index thực thi một dòng ACTIVATED cho mỗi tọa độ credential đầy đủ.

3. Bất biến xuyên entity

Bất biếnCách thực thi
Phiếu cân bằng: TRANSFER Σdebit == Σcredit; PAYMENT-with-asset-leg cân bằngFinanceVoucherService.assertLineDirectionForVoucherType (sai số 1e-4)
Mọi dòng phiếu dùng chung tiền tệ của phiếuassertLinesCurrencyConsistent + kiểm tra theo dòng trong postLines
account.currentBalance == tổng chạy số tiền có dấu của các dòng của nópostLines tính balanceAfter; adjustAccountState lưu
postingSequenceLastValue tăng nghiêm ngặt theo tài khoảnguard adjustAccountState + partial UPI trên (financeAccountId, postingSequence)
Một tài khoản mặc định cho mỗi (merchant, type, environment)Partial unique index nơi metadata.isDefault=true
Phiếu tự động idempotent khi Kafka redeliverPartial unique index theo từng-source / từng-event + tryIdempotentReplay
Tài khoản kiểm soát INVENTORY + COGS tồn tại trước khi hạch toán COGS_ensureInternalControlAccounts khi merchant CDC; handler throw nếu thiếu

4. Hành vi Soft-delete

Hành viChi tiết
Đọc mặc địnhdeletedAt IS NULL (model defaultFilter)
Hard-deleteChỉ deleteDraft xóa một phiếu DRAFT; phiếu đã issue không bao giờ bị xóa (void thay thế)
RestoreKhông expose
Index dedupTất cả scope WHERE deletedAt IS NULL để một dòng soft-delete không bao giờ chặn re-insert

5. Trang liên quan

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