feat: deliver schema 15 monthly settlement lifecycle
This commit is contained in:
+17
-7
@@ -4,7 +4,7 @@
|
||||
|
||||
계좌 평가 증거, 수동 자산, append-only 자산 마감과 기존 ledger entities의 실제 SQLite 정본을 기록한다.
|
||||
|
||||
- 포함 범위: `accounts`, `transactions`, `manual_assets`, `account_valuations`, `asset_snapshots`, `asset_snapshot_runs`, `reconciliation_sessions`, `review_decisions`, `import_batches`, `schema_meta`
|
||||
- 포함 범위: `accounts`, `transactions`, `manual_assets`, `account_valuations`, `account_snapshot`, `asset_snapshot_runs`, `reconciliation_sessions`, `review_decisions`, `import_batches`, `schema_meta`
|
||||
- 제외 범위: auth cookie/session, external price/FX store, inferred transactions, actual credentials/data
|
||||
|
||||
## 정본 엔터티
|
||||
@@ -21,7 +21,7 @@
|
||||
|---|---|---|---|---|---|---|
|
||||
| `id` | TEXT | 필수 | 없음 | generated account id | 식별자 | 아니오 |
|
||||
| `name` | TEXT | 필수 | 없음 | non-empty | 없음 | 아니오 |
|
||||
| `type` | TEXT | 필수 | `bank` | bank/card/cash/investment/loan/other | enum | 아니오 |
|
||||
| `type` | TEXT | 필수 | `bank` | bank/card/cash/investment/loan/other/real_estate | enum | 아니오 |
|
||||
| `currency` | TEXT | 필수 | `KRW` | supported currency | ISO code | 아니오 |
|
||||
| `last_balance` | INTEGER | 선택 | NULL | exact integer | currency unit | 아니오 |
|
||||
| `last_balance_basis_date` | TEXT | 선택 | `''` | YYYY-MM-DD or unknown | date of the evidence represented by `last_balance`; empty/unknown is explicit | 아니오 |
|
||||
@@ -169,11 +169,11 @@
|
||||
|
||||
## 검증
|
||||
|
||||
- 정상 데이터: `tests/test_account_valuations.py`, `tests/test_asset_snapshots.py`
|
||||
- 정상 데이터: `tests/test_account_valuation_service_actual.py`, `tests/test_account_snapshot_linking.py`
|
||||
- 경계 데이터: NULL/0, stale carry-forward, correction, empty snapshot tables
|
||||
- 오류 데이터: invalid currency/kind, missing loan definition, idempotency/correction conflict
|
||||
- 저장 후 재조회: service list/select/report and contract regression tests
|
||||
- 마이그레이션: `test_*schema*` tests plus `python -m pytest tests/test_account_valuations.py tests/test_asset_snapshots.py`
|
||||
- 마이그레이션: `test_*schema*` tests plus `python -m pytest tests/test_account_valuation_service_actual.py tests/test_account_snapshot_linking.py`
|
||||
|
||||
## settlement-drafts — 월정산 초안
|
||||
|
||||
@@ -193,6 +193,12 @@ Frozen/public evidence retains `valuation_date`, original `recorded_at`, derived
|
||||
Review fingerprint binds draft version, target/inclusion state, full valuation/manual semantic evidence, correction child, warnings, amounts/classification/date and prior run. Approved fingerprint/version become invalid on mutation or external drift. Finalize checks idempotency replay before active status, then validates version, approval, fingerprint, current evidence and correction parent, and inserts run+rows+draft completion/link in one `BEGIN IMMEDIATE`. Rollback on any SQLite failure; replay returns persisted response.
|
||||
|
||||
KRW only aggregation; non-KRW is warned/excluded, never converted. NULL is not zero; no targets yields provisional zero plus completeness and unregistered-liability warning, not a complete close. Existing snapshot rows preserve full frozen evidence, approval, date/mode/difference and actors; substitution, carried and approved-missing flags are orthogonal. `monthly_source_snapshot_id` remains a read-model alias, never a persistence field.
|
||||
# Current schema 15 and historical compatibility
|
||||
|
||||
The local development source currently declares `SCHEMA_VERSION = "15"`. The published `v0.1.7` tag remains schema 14; this working tree is a dirty development state and does not establish a published schema-15 release. Historical schema 11–14 notes below are retained as migration context, not current schema claims.
|
||||
|
||||
Schema 15 renames `account_snapshot.month_settlement_id` in place to nullable `monthly_settlement_id`, preserving rows, and maps settlement cashflow rows to the canonical `monthly_settlement(id)` parent. The mapping is single-month and fails transactionally when ambiguous or missing. `approved_cashflow_fingerprint` is nullable legacy-compatible approval metadata; it is not a reserved future physical column.
|
||||
|
||||
# Issue #18 — schema 14 comprehensive settlement additions
|
||||
|
||||
### asset_snapshot_runs cashflow field contract
|
||||
@@ -226,7 +232,7 @@ All twelve comprehensive-run columns are nullable with no SQL default. This pres
|
||||
| Column | Type | Nullability | Default |
|
||||
|---|---|---|---|
|
||||
| `id` | TEXT | NULL | none |
|
||||
| `settlement_run_id` | TEXT | NOT NULL | none |
|
||||
| `monthly_settlement_id` | TEXT | NOT NULL | none |
|
||||
| `cashflow_kind` | TEXT | NOT NULL | none |
|
||||
| `category` | TEXT | NOT NULL | `''` |
|
||||
| `subcategory` | TEXT | NOT NULL | `''` |
|
||||
@@ -234,7 +240,7 @@ All twelve comprehensive-run columns are nullable with no SQL default. This pres
|
||||
| `transaction_count` | INTEGER | NOT NULL | none |
|
||||
| `currency` | TEXT | NOT NULL | none |
|
||||
|
||||
`id` is logically required although SQLite reports no explicit NOT NULL flag for this TEXT primary key. `settlement_run_id` references `asset_snapshot_runs(id)` ON DELETE RESTRICT. The unique key is `(settlement_run_id, cashflow_kind, category, subcategory, currency)`. `transaction_count > 0` and amount/count are integers; `idx_settlement_cashflow_snapshots_run` indexes the run.
|
||||
`id` is logically required although SQLite reports no explicit NOT NULL flag for this TEXT primary key. `monthly_settlement_id` references `monthly_settlement(id)` ON DELETE RESTRICT. The unique key is `(monthly_settlement_id, cashflow_kind, category, subcategory, currency)`. `transaction_count > 0` and amount/count are integers; `idx_settlement_cashflow_snapshots_month` indexes the canonical month.
|
||||
|
||||
### Comprehensive snapshot evidence inputs
|
||||
|
||||
@@ -244,6 +250,10 @@ Asset inputs preserve `source_id`, `source_type`, `valuation_id`, `valuation_dat
|
||||
|
||||
`asset_snapshot_runs` remains the run header. Schema 13→14 adds settlement month, currency, six nullable legacy-compatible INTEGER totals (`income_total`, `expense_total`, `net_cashflow`, `total_assets`, `total_liabilities`, `net_worth`), `cashflow_policy_json`, `aggregation_version`, `snapshot_schema_version`, and `source_snapshot_json`; preserve existing basis/approval/draft/correction/idempotency fields. Old asset-only run totals remain NULL; no current-ledger backfill. Migration is additive/idempotent; old unfinished drafts require fresh comprehensive review/approval.
|
||||
|
||||
`settlement_cashflow_snapshots`: eight columns `id`, `settlement_run_id`, `cashflow_kind`, `category`, `subcategory`, `amount`, `transaction_count`, `currency`; `cashflow_kind` is income/expense/excluded, `amount` signed INTEGER, count positive, category fields NOT NULL (empty string is explicit), FK to `asset_snapshot_runs.id` with RESTRICT, unique `(settlement_run_id,cashflow_kind,category,subcategory,currency)`, and run lookup index. Rows are grouped details for exactly one run.
|
||||
`settlement_cashflow_snapshots`: eight columns `id`, `monthly_settlement_id`, `cashflow_kind`, `category`, `subcategory`, `amount`, `transaction_count`, `currency`; `cashflow_kind` is income/expense/excluded, `amount` signed INTEGER, count positive, category fields NOT NULL (empty string is explicit), FK to `monthly_settlement.id` with RESTRICT, unique `(monthly_settlement_id,cashflow_kind,category,subcategory,currency)`, and month lookup index. Rows are grouped details for exactly one canonical month.
|
||||
|
||||
Policy is stored on draft and header. Savings means only explicit category/subcategory pairs; transfer/voucher exclusion has priority; debt_payment is expense; refund is negative expense in refund month/original category. Unknown unresolved blocks approval; asset conditional flags cannot override it. KRW only/no FX. Source JSON freezes transaction values/classification/policy/decision and selected asset evidence/provenance. Six equations are validated against same-run details; excluded/duplicate/unknown amount do not sum. Header, both detail areas, evidence, completed draft linkage/response commit atomically; rollback all on failure. Runs are immutable; corrections append after latest-parent/single-child validation.
|
||||
|
||||
### monthly_settlement approval cashflow fingerprint
|
||||
|
||||
`monthly_settlement.approved_cashflow_fingerprint` is a nullable `TEXT` field used by the current approval/finalization flow to retain the approved cashflow fingerprint. It has no default; historical monthly settlements may remain `NULL`. It is distinct from the draft `review_fingerprint`.
|
||||
|
||||
Reference in New Issue
Block a user