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
merchantIdtext-Merchant sở hữu
statustextACTIVATEDXem enum status
namei18n-{ default, en, vi }
typetext-Xem enum loại tài khoản
providertextBANABANA / VNPAY / e-wallet / bank
productCodetext-vd QR_MMS, PHONE_POS, INTERNAL_ACCOUNT
accountNumber / accountHoldertext-Định danh bank/e-wallet
detailsjsonb-Theo 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
metadatajsonb-isDefault, 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ả
typetext-RECEIPT / PAYMENT / TRANSFER / ADJUSTMENT
statustextDRAFTDRAFT / ISSUED / VOIDED
voucherNumbertext-Gá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)
partyTypetext-CUSTOMER / VENDOR / EMPLOYEE / INTERNAL / EXTERNAL
partyId / partyName / partyAddresstext/i18npartyName ✓-Snapshot party khi issue
reasoni18n-Diễn giải
sourceTypetext-MANUAL / SALE_ORDER / SALE_ORDER_REFUND / PURCHASE_ORDER / POS_SESSION / INVENTORY_ADJUSTMENT
sourceIdtext-id chứng từ gốc
sourceEventUidtext-Idempotency key theo từng-event (Kafka redeliver)
sessionIdtext-Quy gán ca POS
transactionDatetimestamptz-Ngày kế toán
reversalVoucherIdtext-Phiếu đối ứng khi void
issuedAt/issuedBy/voidedAt/voidedBy/voidReason--Audit vòng đời
metadatajsonb-draftLines, 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)chỉ định tường minh theo dòng; Σ DEBIT == Σ CREDITPCK
ADJUSTMENT (Phiếu kế toán)chỉ định tường minh 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ả
typetext-100_DEBIT (số dư tăng) / 200_CREDIT (số dư giảm)
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)
financeAccountIdtext-Tài khoản bị ảnh hưởng
financeCategoryIdtext-Phân loại tùy chọn
financeVoucherIdtext-Phiếu cha
lineNumberinteger-Vị trí trong phiếu
balanceBefore / balanceAfterdecimal(15,4)-Snapshot tại thời điểm post
postingSequencebigint-Con trỏ post đơn điệu theo từng tài khoản
referenceType / referenceIdtext-Liê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.