Skip to content

Domain Model

Nguồn schema: packages/core/src/models/schemas/ledger/ — package này không sở hữu schema Drizzle nào; nó re-export repository từ @nx/core. Mọi bảng nằm trong schema Postgres ledger.

1. ERD đầy đủ

2. Entities

Ledger

Thuộc tínhGiá trị
Tableledger.Ledger
Sourcecore/src/models/schemas/ledger/ledger/schema.ts
Soft-delete
Owner ID columnmerchantId

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePK
typetextTLedgerIdentifier (S1a-HKD..S2e-HKD)
statustextDRAFTXem enum bên dưới
periodtextYYYY-MN / YYYY-QN / YYYY-Y (vd 2026-M3, 2026-Q1, 2026-Y)
periodStart / periodEndtimestamptzBiên kỳ
merchantIdtextMerchant sở hữu
isCurrentbooleantrueCờ version hiện tại
versionnumeric(_,1)1.0Version revision
previousVersionIdtextnullVersion trước (đặt khi revise)
summaryjsonbnullTLedgerSummary (tổng theo từng mẫu)
notejsonbnullnote revision i18n { en, vi }

Enum trạng thái (LedgerStatuses):

Giá trịMô tả
DRAFTSửa được; cho phép tạo + tạo lại
200_FINALIZEDKhoá version; phải revise để thay đổi
ARCHIVEDBị thay thế bởi một revision đã finalize; chỉ đọc
400_SUBMITTEDDành chỗ — đã nộp lên cơ quan thuế (chưa hiện thực)

Index & ràng buộc:

TênCộtLoại
PK_LedgeridPrimary key
UPQ_Ledger_*merchantId, type, period, versionUnique partial (deleted_at IS NULL)
IDX_Ledger_*isCurrent · merchantId,period · merchantId,periodStart,periodEnd · merchantId,status · previousVersionId · statusBtree

LedgerJob

Thuộc tínhGiá trị
Tableledger.LedgerJob
Sourcecore/src/models/schemas/ledger/ledger-job/schema.ts
Soft-delete
Owner ID column (qua ledgerId → Ledger)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePK
ledgerIdtextSổ sở hữu (soft ref)
statustextPENDINGXem enum bên dưới
attemptCountinteger0Số lần thử trọn đời; không reset khi retry
processStartAttimestamptzMốc phát hiện kẹt
processCompletedAttimestamptz
failureReasonjsonb{ default, en?, vi?, errorCode }
enqueuedAttimestamptzLần enqueue đầu
lastEnqueuedAttimestamptzLần re-enqueue cuối

Enum trạng thái (LedgerJobStatuses): DRAFT, PENDING, PROCESSING, COMPLETED, PARTIAL, REJECTED (luồng active dùng PENDING → PROCESSING → COMPLETED|REJECTED).

Index: IDX_LedgerJob_ledgerId, IDX_LedgerJob_status, IDX_LedgerJob_status_processStartAt (quét job kẹt).

LedgerSnapshot

Thuộc tínhGiá trị
Tableledger.LedgerSnapshot
Sourcecore/src/models/schemas/ledger/ledger-snapshot/schema.ts
Soft-deletecó (+ cột user-audit)
Owner ID column (qua ledgerId)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePK
ledgerIdtextSổ sở hữu; unique
headerDatajsonbTSnapshotHeaderData (businessName, taxCode, address…)
snapshotMetajsonbTổng hợp staleness theo loại (count, maxUpdatedAt)
pulledAttimestamptzThời điểm pull
hasUnrecordedChangebooleanfalseCờ staleness (chặn finalize)
lastChangeDetectedAttimestamptz

Index: UQ_LedgerSnapshot_ledgerId (một snapshot mỗi sổ).

LedgerSnapshotEntry

Thuộc tínhGiá trị
Tableledger.LedgerSnapshotEntry
Sourcecore/src/models/schemas/ledger/ledger-snapshot-entry/schema.ts
Soft-deletecó (+ cột user-audit)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePK
snapshotIdtextSnapshot sở hữu
rowIndexintegerThứ tự hàng
originalDatajsonbnullHàng nguồn; null với entry do người dùng thêm
currentDatajsonbHàng đã sửa/hiệu lực

Index: IDX_LedgerSnapshotEntry_snapshotId.

MerchantLedgerConfig

Thuộc tínhGiá trị
Tableledger.MerchantLedgerConfig
Sourcecore/src/models/schemas/ledger/merchant-ledger-config/schema.ts
Soft-deletecó (+ cột user-audit)
Owner ID columnmerchantId

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePK
yearintegernăm hiện tạiNăm config
merchantIdtextMerchant sở hữu
taxDeclarationLevelIdtextFK-soft tới TaxDeclarationLevel
taxMethodtext
isMultiSectorbooleanfalseChọn rule multiSectorLedgerTypes
filingSchedulesjsonb[]{ purpose, periodType }[]
requiredLedgerTypesjsonb[]TLedgerIdentifier[] đã tính
confirmedAttimestamptzĐặt khi confirm
metadata.originjsonb`'migration'

Index: UPQ_MerchantLedgerConfig_merchantId_year (một config mỗi merchant-năm, partial).

TaxDeclarationLevel

Thuộc tínhGiá trị
Tableledger.TaxDeclarationLevel
Sourcecore/src/models/schemas/ledger/tax-declaration-level/schema.ts
Soft-deletecó (+ cột user-audit)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePK
codetextTIRE_0..TIRE_3
namejsonbi18n { en, vi }
descriptionjsonbi18n
revenueThresholdMin / MaxtextBiên dải doanh thu
filingScheduleRulesjsonb[]{ purpose, periodType, required, ledgerTypes[], multiSectorLedgerTypes? }[]

Index: UPQ_TaxDeclarationLevel_code (unique partial).

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

Bất biếnCách thực thi
Nhiều nhất một sổ current đã finalize mỗi (merchantId, type, period, version)Unique partial index + cờ isCurrent
revise luôn tạo một hàng DRAFT mới (version+1, isCurrent=false, đặt previousVersionId)LedgerSnapshotService.revise
Đúng một snapshot mỗi sổUQ_LedgerSnapshot_ledgerId
finalize bị chặn khi snapshot hasUnrecordedChange = trueguard LedgerSnapshotService.finalize
requiredLedgerTypes suy từ filingScheduleRules của bậc thuế × filingSchedulesisMultiSector); rỗng → [S1a-HKD]MerchantLedgerConfigService._computeRequiredLedgerTypes
Worker chỉ động LedgerJob.status — không bao giờ Ledger.statusLedgerWorkerService (ghi Ledger-status đã comment)

4. Hành vi Soft-delete

Hành viChi tiết
Mặc định đọcdeletedAt IS NULL (mọi repo qua SoftDeletableRepository)
Hard-deleteRe-pull snapshot soft-delete entry + snapshot trước đó trước khi tạo lại
Unique indexPartial (WHERE deleted_at IS NULL) nên hàng đã soft-delete không chặn tạo lại

5. Trang liên quan

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