Fix loan valuation definition bypasses

This commit is contained in:
2026-10-07 03:30:23 +00:00
parent 5e721b0ddd
commit b8b8811a2a
7 changed files with 155 additions and 8 deletions
@@ -92,17 +92,23 @@ def _validate_common(account_id: str, basis_date: str, amount: int, currency: st
def record_account_valuation_candidate(conn: sqlite3.Connection, account_id: str, basis_date: str, amount: int, currency: str, source_type: str, source_ref: str, idempotency_key: str, memo: str = "") -> dict[str, Any]:
"""Append an unverified candidate on a caller-owned transaction."""
account = conn.execute("SELECT currency FROM accounts WHERE id=?", (account_id,)).fetchone()
account = conn.execute("SELECT type,currency FROM accounts WHERE id=?", (account_id,)).fetchone()
if account is None:
return fail("not_found", "account not found")
if (currency or "KRW").upper() != (account["currency"] or "KRW").upper():
return fail("validation_error", "valuation currency must match account currency")
if str(account["type"]).lower() == "loan":
return fail("validation_error", "loan valuation requires representative_liability_definition")
try:
amount_int = _strict_int(amount, "amount", allow_none=False)
except (TypeError, ValueError) as exc:
return fail("validation_error", str(exc))
basis = normalize_date(basis_date)
existing = conn.execute("SELECT * FROM account_valuations WHERE account_id=? AND idempotency_key=?", (account_id, idempotency_key)).fetchone()
if existing:
incoming = {
"basis_date": basis,
"amount": int(amount),
"amount": amount_int,
"currency": (currency or "KRW").upper(),
"valuation_kind": "balance",
"source_type": source_type,
@@ -120,7 +126,7 @@ def record_account_valuation_candidate(conn: sqlite3.Connection, account_id: str
valuation_id = new_id("valuation")
conn.execute("""INSERT INTO account_valuations
(id,account_id,basis_date,amount,currency,valuation_kind,source_type,source_ref,verification_status,recorded_at,memo,idempotency_key)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?)""", (valuation_id, account_id, basis, int(amount), (currency or "KRW").upper(), "balance", source_type, source_ref or "", "unverified", now_iso(), memo, idempotency_key))
VALUES(?,?,?,?,?,?,?,?,?,?,?,?)""", (valuation_id, account_id, basis, amount_int, (currency or "KRW").upper(), "balance", source_type, source_ref or "", "unverified", now_iso(), memo, idempotency_key))
return ok(valuation=_valuation(conn.execute("SELECT * FROM account_valuations WHERE id=?", (valuation_id,)).fetchone()), reused=False)
@@ -189,6 +195,8 @@ def register_account_valuation(
is_loan_account = str(account["type"]).lower() == "loan"
if effective_kind in {"loan", "loan_balance"} and not is_loan_account:
return fail("validation_error", "loan valuation kind requires a loan account")
if is_loan_account and effective_kind not in {"balance", "loan", "loan_balance"}:
return fail("validation_error", "loan account valuation kind must represent a liability")
if is_loan_account and effective_kind in {"balance", "loan", "loan_balance"} and definition is None:
return fail("validation_error", "loan valuation requires representative_liability_definition")
if definition is not None and not is_loan_account: