amanpay / scripts /d3_rebuild_balances.py
MHamdan's picture
CI deploy 2550795
ef983af verified
Raw
History Blame Contribute Delete
1.89 kB
#!/usr/bin/env python3
"""Rebuild D3 balance projections from the immutable journal lines (+ active holds).
Verifies the ledger balances BEFORE replacing projections; refuses to rebuild on top of an
unbalanced ledger. After rebuild, verifies projections equal the journal-derived balances.
Requires --confirm-d3 because it replaces the projection cache (never the journals).
Example:
python scripts/d3_rebuild_balances.py --db-path /tmp/amanpay-d2/amanpay.db --tenant event \
--confirm-d3 --allow-unknown-fs --json
"""
from __future__ import annotations
import argparse
import sys
from amanpay.finance.cli import add_common_args, build_runtime_for_cli, emit, resolve_tenant_id
from amanpay.finance.verification import (journal_control_totals, rebuild_projections,
verify_projections)
def main(argv=None) -> int:
p = argparse.ArgumentParser(description="Rebuild D3 balance projections from journals.")
add_common_args(p, tenant_required=False)
p.add_argument("--confirm-d3", action="store_true", required=True)
args = p.parse_args(argv)
rt = build_runtime_for_cli(args.db_path, allow_unknown_fs=args.allow_unknown_fs)
tid = resolve_tenant_id(rt, args.tenant) if args.tenant else None
# Never rebuild on top of an unbalanced ledger.
totals = journal_control_totals(rt.store, tid)
if not totals["all_balanced"]:
emit({"ok": False, "error": "ledger_unbalanced", "by_currency": totals["by_currency"]},
as_json=args.json)
rt.close()
return 1
report = rebuild_projections(rt.store, tid)
check = verify_projections(rt.store, tid)
emit({"ok": check["ok"], "rebuilt": report["rebuilt"], "mismatches": len(check["mismatches"])},
as_json=args.json)
rt.close()
return 0 if check["ok"] else 1
if __name__ == "__main__":
sys.exit(main())