fix: preserve schema 15 compatibility for v0.1.8
This commit is contained in:
@@ -36,22 +36,6 @@ def _add_tx(day, typ, amount, category, subcategory, path):
|
||||
return result["transaction"]["id"]
|
||||
|
||||
|
||||
def _add_snapshot(name, amount, basis_date, bucket, path):
|
||||
"""Create the schema-15 account snapshot evidence used by settlement review."""
|
||||
account = _ok(service.create_ledger_account(name, type="bank", currency="KRW", liquidity_bucket=bucket, db_path=path))["account"]
|
||||
with sqlite3.connect(path) as conn:
|
||||
conn.execute(
|
||||
"INSERT OR IGNORE INTO monthly_settlement "
|
||||
"(id,month,basis_date,status,version,created_by,created_at,updated_by,updated_at) "
|
||||
"VALUES (?,?,?,?,?,?,?,?,?)",
|
||||
("monthly-2026-09", basis_date[:7], basis_date, "draft", 1, "test", "now", "test", "now"),
|
||||
)
|
||||
return _ok(service.register_account_valuation(
|
||||
account["id"], basis_date, amount, currency="KRW", monthly_settlement_id="monthly-2026-09",
|
||||
liquidity_bucket=bucket, db_path=path,
|
||||
))
|
||||
|
||||
|
||||
def test_explicit_savings_refund_and_movement_precedence(tmp_path):
|
||||
path = str(tmp_path / "policy-precedence.sqlite3")
|
||||
init_db(path)
|
||||
@@ -120,11 +104,11 @@ def test_unknown_classification_blocks_and_explicit_exclusion_unblocks(tmp_path)
|
||||
def test_policy_edit_persists_versions_and_invalidates_approval(tmp_path):
|
||||
path = str(tmp_path / "policy-approval.sqlite3")
|
||||
init_db(path)
|
||||
_ok(_add_snapshot("Synthetic cash", 100, "2026-09-30", "cash", path))
|
||||
_ok(service.create_manual_asset("Synthetic cash", 100, "2026-09-30", "cash", db_path=path))
|
||||
draft = _draft(path)
|
||||
reviewed = _ok(service.review_settlement_draft(draft["id"], db_path=path))
|
||||
assert not reviewed["cashflow_blockers"]
|
||||
_ok(service.approve_settlement_draft(draft["id"], draft["version"], reviewed["review_fingerprint"], "reviewer", "synthetic", "ref", allow_missing_exclusions=True, db_path=path))
|
||||
_ok(service.approve_settlement_draft(draft["id"], draft["version"], reviewed["review_fingerprint"], "reviewer", "synthetic", "ref", db_path=path))
|
||||
result = _ok(_capability("set_settlement_cashflow_policy")(draft["id"], draft["version"], "editor", _policy(), db_path=path))
|
||||
saved = _ok(service.get_settlement_draft(draft["id"], db_path=path))["draft"]
|
||||
assert saved["cashflow_policy"] == _policy()
|
||||
@@ -148,14 +132,23 @@ def test_review_contract_and_stored_reader_never_recomputes_live_preview(tmp_pat
|
||||
init_db(path)
|
||||
reader = _capability("get_monthly_settlement_snapshot")
|
||||
empty = reader(month="2026-09", db_path=path)
|
||||
assert empty["success"] is False and empty["error_code"] == "unsupported"
|
||||
_ok(_add_snapshot("Synthetic cash", 100, "2026-09-30", "cash", path))
|
||||
assert empty["success"] is False and empty["error_code"] == "not_found"
|
||||
_ok(service.create_manual_asset("Synthetic cash", 100, "2026-09-30", "cash", db_path=path))
|
||||
draft = _draft(path)
|
||||
reviewed = _ok(service.review_settlement_draft(draft["id"], db_path=path))
|
||||
assert "review_fingerprint" in reviewed and "review" not in reviewed
|
||||
approved = _ok(service.approve_settlement_draft(draft["id"], draft["version"], reviewed["review_fingerprint"], "reviewer", "synthetic", "ref", allow_missing_exclusions=True, db_path=path))
|
||||
final = service.finalize_settlement_draft(draft["id"], approved["draft"]["version"], reviewed["review_fingerprint"], "close-key", db_path=path)
|
||||
assert final == {"success": False, "error_code": "unsupported", "error": "run history unavailable"}
|
||||
approved = _ok(service.approve_settlement_draft(draft["id"], draft["version"], reviewed["review_fingerprint"], "reviewer", "synthetic", "ref", db_path=path))
|
||||
final = _ok(service.finalize_settlement_draft(draft["id"], approved["draft"]["version"], reviewed["review_fingerprint"], "close-key", db_path=path))
|
||||
assert "final_response" not in final and "snapshot_run_id" in final
|
||||
snapshot = _ok(reader(run_id=final["snapshot_run_id"], db_path=path))
|
||||
assert snapshot["is_closed_snapshot"] is True
|
||||
assert snapshot["snapshot_run_id"] == final["snapshot_run_id"]
|
||||
assert snapshot["total_assets"] == 100
|
||||
assert _ok(reader(month="2026-09", db_path=path))["snapshot_run_id"] == final["snapshot_run_id"]
|
||||
_ok(service.create_manual_asset("Later live cash", 900, "2026-09-30", "cash", db_path=path))
|
||||
persisted = _ok(reader(run_id=final["snapshot_run_id"], db_path=path))
|
||||
assert persisted["total_assets"] == 100 and persisted["snapshot_run_id"] == final["snapshot_run_id"]
|
||||
assert "live_authority" not in persisted.values()
|
||||
|
||||
|
||||
def test_month_boundaries_refund_month_negative_total_and_fx_blocker(tmp_path):
|
||||
@@ -199,7 +192,7 @@ def test_policy_capabilities_are_checked_at_call_time(tmp_path):
|
||||
init_db(path)
|
||||
assert callable(_capability("set_settlement_cashflow_policy"))
|
||||
assert callable(_capability("get_monthly_settlement_snapshot"))
|
||||
assert _capability("get_monthly_settlement_snapshot")(month="", run_id="", db_path=path)["error_code"] == "unsupported"
|
||||
assert _capability("get_monthly_settlement_snapshot")(month="", run_id="", db_path=path)["error_code"] == "not_found"
|
||||
|
||||
|
||||
def _private_cashflow_review(path, policy=None):
|
||||
@@ -257,7 +250,7 @@ def test_inactive_category_uses_raw_fallback_through_public_close(tmp_path):
|
||||
path = str(tmp_path / "inactive-category-fallback.sqlite3")
|
||||
init_db(path)
|
||||
# A close run requires a nonempty asset valuation; cashflow-only drafts cannot finalize.
|
||||
_ok(_add_snapshot("Synthetic close cash", 100, "2026-09-30", "cash", path))
|
||||
_ok(service.create_manual_asset("Synthetic close cash", 100, "2026-09-30", "cash", db_path=path))
|
||||
cases = [
|
||||
# SQL fallback is category-based: ordinary legacy categories become expense,
|
||||
# while canonical legacy categories retain their established classifications.
|
||||
@@ -290,9 +283,15 @@ def test_inactive_category_uses_raw_fallback_through_public_close(tmp_path):
|
||||
assert row["category_cashflow_kind"] is None and row["category_active"] is None
|
||||
assert reviewed["expense_total"] == 123 # 11 + 13 + 17 + 19 - 5 + 31 + 37
|
||||
assert reviewed["income_total"] == 29
|
||||
approved = _ok(service.approve_settlement_draft(draft["id"], draft["version"], reviewed["review_fingerprint"], "reviewer", "synthetic", "ref", allow_missing_exclusions=True, db_path=path))
|
||||
closed = service.finalize_settlement_draft(draft["id"], approved["draft"]["version"], reviewed["review_fingerprint"], "inactive-category-close", db_path=path)
|
||||
assert closed == {"success": False, "error_code": "unsupported", "error": "run history unavailable"}
|
||||
approved = _ok(service.approve_settlement_draft(draft["id"], draft["version"], reviewed["review_fingerprint"], "reviewer", "synthetic", "ref", db_path=path))
|
||||
closed = _ok(service.finalize_settlement_draft(draft["id"], approved["draft"]["version"], reviewed["review_fingerprint"], "inactive-category-close", db_path=path))
|
||||
snapshot = _ok(service.get_monthly_settlement_snapshot(run_id=closed["snapshot_run_id"], db_path=path))
|
||||
persisted = {row["id"]: row for row in snapshot["source_snapshot"]["transactions"]}
|
||||
for txid in ids:
|
||||
assert persisted[txid]["sourceprovenance"] == "fallback"
|
||||
assert persisted[txid]["category_active"] is None
|
||||
assert persisted[txid]["category_cashflow_kind"] is None
|
||||
assert snapshot["expense_total"] == 123 and snapshot["income_total"] == 29
|
||||
|
||||
|
||||
def test_explicit_decision_classifies_only_unresolved_inactive_fallback(tmp_path):
|
||||
|
||||
Reference in New Issue
Block a user