feat: deliver schema 15 monthly settlement lifecycle
This commit is contained in:
@@ -150,7 +150,7 @@ def test_mid_close_failure_rolls_back_all_settlement_state(tmp_path, failure_poi
|
||||
review = review_result
|
||||
ok(api("approve_settlement_draft")(draft["id"], draft["version"], review["review_fingerprint"], "synthetic-reviewer", "approved", "ref", db_path=path))
|
||||
with sqlite3.connect(path) as db:
|
||||
target = {"header":"asset_snapshot_runs", "assets":"asset_snapshots", "cashflow":"settlement_cashflow_snapshots", "completion":"settlement_drafts"}[failure_point]
|
||||
target = {"header":"asset_snapshot_runs", "assets":"account_snapshot", "cashflow":"settlement_cashflow_snapshots", "completion":"settlement_drafts"}[failure_point]
|
||||
# Missing future table is an explicit RED assertion, not a SQL error masquerading as rollback.
|
||||
assert db.execute("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?", (target,)).fetchone(), f"required comprehensive table missing: {target}"
|
||||
event = "UPDATE" if failure_point == "completion" else "INSERT"
|
||||
@@ -160,7 +160,7 @@ def test_mid_close_failure_rolls_back_all_settlement_state(tmp_path, failure_poi
|
||||
assert failed.get("success") is False
|
||||
with sqlite3.connect(path) as db:
|
||||
assert db.execute("SELECT COUNT(*) FROM asset_snapshot_runs").fetchone()[0] == 0
|
||||
assert db.execute("SELECT COUNT(*) FROM asset_snapshots").fetchone()[0] == 0
|
||||
assert db.execute("SELECT COUNT(*) FROM account_snapshot").fetchone()[0] == 0
|
||||
assert db.execute("SELECT COUNT(*) FROM settlement_cashflow_snapshots").fetchone()[0] == 0
|
||||
assert db.execute("SELECT status FROM settlement_drafts WHERE id=?", (draft["id"],)).fetchone()[0] == "active"
|
||||
|
||||
@@ -176,7 +176,7 @@ def test_close_rejects_stored_detail_sum_tampering(tmp_path):
|
||||
result = close_draft(path, draft)
|
||||
assert result.get("success") is False, result
|
||||
with sqlite3.connect(path) as db:
|
||||
for table in ("asset_snapshot_runs", "asset_snapshots", "settlement_cashflow_snapshots"):
|
||||
for table in ("asset_snapshot_runs", "account_snapshot", "settlement_cashflow_snapshots"):
|
||||
assert db.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0] == 0
|
||||
assert db.execute("SELECT status FROM settlement_drafts WHERE id=?", (draft["id"],)).fetchone()[0] == "active"
|
||||
|
||||
@@ -368,7 +368,7 @@ def test_close_rejects_persisted_header_and_asset_tampering(tmp_path, target):
|
||||
ok(service.approve_settlement_draft(draft["id"], draft["version"], review["review_fingerprint"], "reviewer", "synthetic", "ref", db_path=path))
|
||||
if target.startswith("asset_"):
|
||||
column, expression = ("amount", "amount+1") if target == "asset_amount" else ("currency", "'USD'")
|
||||
trigger = f"CREATE TRIGGER synthetic_tamper AFTER INSERT ON asset_snapshots BEGIN UPDATE asset_snapshots SET {column}={expression} WHERE id=NEW.id; END"
|
||||
trigger = f"CREATE TRIGGER synthetic_tamper AFTER INSERT ON account_snapshot BEGIN UPDATE account_snapshot SET {column}={expression} WHERE id=NEW.id; END"
|
||||
else:
|
||||
column, expression = {"header_total": ("income_total", "income_total+1"), "header_source": ("source_snapshot_json", "'{}'"), "header_policy": ("cashflow_policy_json", "'{\"savings_categories\":[{\"category\":\"Other\",\"subcategory\":\"Pair\"}],\"category_decisions\":[]}'"), "header_version": ("aggregation_version", "'unknown-version'")}[target]
|
||||
trigger = f"CREATE TRIGGER synthetic_tamper AFTER INSERT ON settlement_cashflow_snapshots BEGIN UPDATE asset_snapshot_runs SET {column}={expression} WHERE id=NEW.settlement_run_id; END"
|
||||
@@ -377,7 +377,7 @@ def test_close_rejects_persisted_header_and_asset_tampering(tmp_path, target):
|
||||
result = service.finalize_settlement_draft(draft["id"], draft["version"], review["review_fingerprint"], "tamper-close", db_path=path)
|
||||
assert result["success"] is False, "persisted header/detail must match the approved result before commit"
|
||||
with sqlite3.connect(path) as conn:
|
||||
for table in ("asset_snapshot_runs", "asset_snapshots", "settlement_cashflow_snapshots"):
|
||||
for table in ("asset_snapshot_runs", "account_snapshot", "settlement_cashflow_snapshots"):
|
||||
assert conn.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0] == 0
|
||||
assert conn.execute("SELECT status,final_run_id,final_response FROM settlement_drafts WHERE id=?", (draft["id"],)).fetchone() == ("active", "", "")
|
||||
|
||||
@@ -672,7 +672,12 @@ def test_schema_eleven_legacy_reader_returns_empty_evidence_without_writes(tmp_p
|
||||
from test_legacy_snapshot_migration import _legacy_closed_db
|
||||
path, _ = _legacy_closed_db(tmp_path)
|
||||
with sqlite3.connect(path) as conn:
|
||||
assert conn.execute("SELECT COUNT(*) FROM asset_snapshot_runs").fetchone()[0] == 0
|
||||
header = conn.execute(
|
||||
"SELECT id, close_status, correction_of_run_id, correction_reason FROM asset_snapshot_runs"
|
||||
).fetchone()
|
||||
assert tuple(header) == (
|
||||
"legacy-run-correction", "legacy_read_only", "legacy-initial", "legacy correction"
|
||||
)
|
||||
before = list(conn.iterdump())
|
||||
exact = ok(service.get_monthly_settlement_snapshot(run_id="legacy-run-correction", db_path=path))
|
||||
latest = ok(service.get_monthly_settlement_snapshot(month="2026-06", db_path=path))
|
||||
|
||||
Reference in New Issue
Block a user