fix: address settlement display and documentation review findings
Rework Issue 18 / PR 19, source review 76: C11-F01 and D02-F02/D03-F03/D04-F04. Preserve the approved contract and add named display, schema, policy, ownership and signature regressions.
This commit is contained in:
@@ -195,6 +195,53 @@ Review fingerprint binds draft version, target/inclusion state, full valuation/m
|
||||
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.
|
||||
# Issue #18 — schema 14 comprehensive settlement additions
|
||||
|
||||
### asset_snapshot_runs cashflow field contract
|
||||
|
||||
All twelve comprehensive-run columns are nullable with no SQL default. This preserves NULL on historical asset-only runs; a new comprehensive write supplies all twelve fields. SQLite reports `id` (TEXT PRIMARY KEY) nullable because DDL omits explicit NOT NULL, although a run logically requires its identifier.
|
||||
|
||||
| Column | Type | Nullability | Default |
|
||||
|---|---|---|---|
|
||||
| `settlement_month` | TEXT | NULL | none |
|
||||
| `currency` | TEXT | NULL | none |
|
||||
| `income_total` | INTEGER | NULL | none |
|
||||
| `expense_total` | INTEGER | NULL | none |
|
||||
| `net_cashflow` | INTEGER | NULL | none |
|
||||
| `total_assets` | INTEGER | NULL | none |
|
||||
| `total_liabilities` | INTEGER | NULL | none |
|
||||
| `net_worth` | INTEGER | NULL | none |
|
||||
| `cashflow_policy_json` | TEXT | NULL | none |
|
||||
| `aggregation_version` | TEXT | NULL | none |
|
||||
| `snapshot_schema_version` | INTEGER | NULL | none |
|
||||
| `source_snapshot_json` | TEXT | NULL | none |
|
||||
|
||||
### settlement_drafts cashflow field contract
|
||||
|
||||
| Column | Type | Nullability | Default |
|
||||
|---|---|---|---|
|
||||
| `cashflow_policy_json` | TEXT | NOT NULL | `'{}'` |
|
||||
| `aggregation_version` | TEXT | NOT NULL | `'comprehensive-v1'` |
|
||||
|
||||
### settlement_cashflow_snapshots cashflow field contract
|
||||
|
||||
| Column | Type | Nullability | Default |
|
||||
|---|---|---|---|
|
||||
| `id` | TEXT | NULL | none |
|
||||
| `settlement_run_id` | TEXT | NOT NULL | none |
|
||||
| `cashflow_kind` | TEXT | NOT NULL | none |
|
||||
| `category` | TEXT | NOT NULL | `''` |
|
||||
| `subcategory` | TEXT | NOT NULL | `''` |
|
||||
| `amount` | INTEGER | NOT NULL | none |
|
||||
| `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.
|
||||
|
||||
### Comprehensive snapshot evidence inputs
|
||||
|
||||
`source_snapshot_json` stores an object with `transactions` and `assets` arrays. Transaction inputs preserve `id`, `transaction_date`, `type`, original signed `amount`, `currency`, `category`, `subcategory`, `originalcashflow_kind`, applied `cashflow_kind`, `applied_amount`, `decision`, `sourceprovenance`, `category_cashflow_kind` and `category_active`. Refunds keep their original positive amount while the expense contribution in `applied_amount` is negative; unresolved classifications keep `applied_amount=NULL` and block approval. The actual stored alias is `originalcashflow_kind`, not a renamed persistence field.
|
||||
|
||||
Asset inputs preserve `source_id`, `source_type`, `valuation_id`, `valuation_date`, `basis_date`, `currency`, `authority_source`, `liquidity_bucket`, `is_liability`, `selection_mode`, `exclusion_reason`, `status`, `verification_status`, original `amount` and `applied_amount`. Missing/excluded evidence retains NULL applied amounts and its recorded status/reason; fixed included rows remain linked to the same run. The run header's `cashflow_policy_json`, `aggregation_version`, `snapshot_schema_version` and these source inputs together reproduce the original selection/aggregation decision without rereading today's ledger. A legacy asset-only run retains NULL comprehensive fields and is reported as legacy: no historical backfill or invented zero. The existing approval, draft, correction and idempotency links remain unchanged.
|
||||
|
||||
`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.
|
||||
|
||||
Reference in New Issue
Block a user