feat: add persistent monthly settlement drafts and approved valuation selection
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
"""Executable reproductions reconcile static audit hypotheses with real behavior."""
|
||||
import sqlite3
|
||||
|
||||
from jarca_ledger_mcp import service as s
|
||||
from jarca_ledger_mcp.db import init_db
|
||||
|
||||
|
||||
def ok(result):
|
||||
assert result['success'], result
|
||||
return result
|
||||
|
||||
|
||||
def test_empty_draft_persists_without_closing_and_has_consistent_public_shape(tmp_path):
|
||||
path = str(tmp_path / 'empty.sqlite3')
|
||||
init_db(path)
|
||||
result = ok(s.create_settlement_draft('2026-09', 'creator', 'initial', db_path=path))
|
||||
draft = result['draft']
|
||||
assert draft['status'] == 'active' and draft['version'] == 1
|
||||
assert draft['basis_date'] == '2026-09-30' and draft['correction_of_run_id'] == ''
|
||||
assert result['items'] == [] and not result['review']['complete']
|
||||
assert result['review']['totals'] == {'total_assets': 0, 'total_liabilities': 0, 'net_worth': 0}
|
||||
assert ok(s.get_settlement_draft(draft['id'], db_path=path)) == result
|
||||
with sqlite3.connect(path) as conn:
|
||||
assert conn.execute('SELECT COUNT(*) FROM settlement_drafts').fetchone()[0] == 1
|
||||
assert conn.execute('SELECT COUNT(*) FROM asset_snapshot_runs').fetchone()[0] == 0
|
||||
assert conn.execute('SELECT COUNT(*) FROM asset_snapshots').fetchone()[0] == 0
|
||||
|
||||
|
||||
def test_initial_draft_freezes_exact_verified_selector_compatibly(tmp_path):
|
||||
path = str(tmp_path / 'selection.sqlite3')
|
||||
init_db(path)
|
||||
account = ok(s.create_ledger_account('Synthetic cash', db_path=path))['account']['id']
|
||||
verified = ok(s.register_account_valuation(account, '2026-09-30', 100, verification_status='verified', idempotency_key='verified', db_path=path))['valuation']['id']
|
||||
unverified = ok(s.register_account_valuation(account, '2026-09-30', 999, verification_status='unverified', idempotency_key='unverified', db_path=path))['valuation']['id']
|
||||
with sqlite3.connect(path) as conn:
|
||||
conn.execute("UPDATE account_valuations SET recorded_at='2026-10-01T00:00:00Z' WHERE id=?", (verified,))
|
||||
conn.execute("UPDATE account_valuations SET recorded_at='2026-10-02T00:00:00Z' WHERE id=?", (unverified,))
|
||||
selected = ok(s.select_account_valuation(account, '2026-09-30', as_of=False, db_path=path))
|
||||
assert selected['valuation']['id'] == verified
|
||||
draft = ok(s.create_settlement_draft('2026-09', 'creator', 'initial', db_path=path))
|
||||
item = next(x for x in draft['items'] if x['source_id'] == account)
|
||||
assert item['valuation_id'] == verified and item['amount'] == 100 and item['verification_status'] == 'verified'
|
||||
|
||||
|
||||
def test_refresh_manual_target_preserves_retired_history_and_allows_explicit_refreeze(tmp_path):
|
||||
path = str(tmp_path / 'retired.sqlite3')
|
||||
init_db(path)
|
||||
asset = ok(s.create_manual_asset('Synthetic property', 100, '2026-09-30', 'real_estate', db_path=path))['manual_asset']['id']
|
||||
created = ok(s.create_settlement_draft('2026-09', 'creator', 'initial', db_path=path))
|
||||
draft, original = created['draft'], created['items'][0]
|
||||
ok(s.deactivate_manual_asset(asset, db_path=path))
|
||||
retired = ok(s.refresh_settlement_draft_targets(draft['id'], draft['version'], 'refresher', db_path=path))
|
||||
row = next(x for x in retired['items'] if x['source_id'] == asset)
|
||||
assert row['id'] == original['id'] and not row['included'] and row['exclusion_reason']
|
||||
assert row['state_hash'] == original['state_hash'] and row['candidate_amount'] == 100
|
||||
refrozen = ok(s.set_settlement_draft_item(draft['id'], 'manual_asset', asset, retired['draft']['version'], 'refreezer', included=False, exclusion_reason='Synthetic retired source confirmed', db_path=path))
|
||||
row = refrozen['items'][0]
|
||||
assert row['id'] == original['id'] and not row['included'] and row['amount'] is None
|
||||
assert row['state_hash'] != original['state_hash'] and not row['review_needed']
|
||||
assert row['selected_by'] == 'refreezer'
|
||||
invalid = s.set_settlement_draft_item(draft['id'], 'manual_asset', asset, refrozen['draft']['version'], 'selector', included=True, db_path=path)
|
||||
assert not invalid['success']
|
||||
assert ok(s.get_settlement_draft(draft['id'], db_path=path))['draft']['version'] == refrozen['draft']['version']
|
||||
Reference in New Issue
Block a user