fix: address account valuation review findings
This commit is contained in:
@@ -185,9 +185,13 @@ def register_account_valuation(
|
||||
return fail("not_found", "account not found")
|
||||
if currency_norm != (account["currency"] or "KRW").upper():
|
||||
return fail("validation_error", "valuation currency must match account currency")
|
||||
if (valuation_kind or "balance").strip().lower() in {"loan", "loan_balance"} and str(account["type"]).lower() != "loan":
|
||||
effective_kind = (valuation_kind or "balance").strip().lower()
|
||||
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 definition is not None and str(account["type"]).lower() != "loan":
|
||||
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:
|
||||
return fail("validation_error", "representative liability definition requires a loan account")
|
||||
seen: set[str] = set()
|
||||
if supersedes_id:
|
||||
@@ -314,16 +318,46 @@ def correct_account_valuation(valuation_id: str, amount: int, correction_reason:
|
||||
preserved = {name: fields[name] if name in fields else source[name] for name in (
|
||||
"currency", "valuation_kind", "source_type", "source_ref", "verification_status", "memo", "as_of_at", "timezone",
|
||||
"cost_basis", "net_contributed", "reported_principal_kind", "reported_principal_label", "profit", "return_rate", "return_basis", "principal", "interest", "fee", "representative_liability_definition")}
|
||||
try:
|
||||
effective = {
|
||||
"amount": _strict_int(amount, "amount", allow_none=False),
|
||||
"account_id": source["account_id"],
|
||||
"basis_date": source["basis_date"],
|
||||
"currency": (preserved["currency"] or "KRW").strip().upper(),
|
||||
"valuation_kind": (preserved["valuation_kind"] or "balance").strip().lower(),
|
||||
"source_type": (preserved["source_type"] or "manual").strip().lower() or "manual",
|
||||
"source_ref": preserved["source_ref"].strip() if isinstance(preserved["source_ref"], str) else "",
|
||||
"verification_status": (preserved["verification_status"] or "unverified").strip().lower(),
|
||||
"memo": preserved["memo"] or "",
|
||||
"as_of_at": preserved["as_of_at"],
|
||||
"timezone": preserved["timezone"],
|
||||
"cost_basis": _strict_int(preserved["cost_basis"], "cost_basis"),
|
||||
"net_contributed": _strict_int(preserved["net_contributed"], "net_contributed"),
|
||||
"reported_principal_kind": preserved["reported_principal_kind"],
|
||||
"reported_principal_label": preserved["reported_principal_label"],
|
||||
"profit": _strict_int(preserved["profit"], "profit"),
|
||||
"return_rate": _strict_float(preserved["return_rate"], "return_rate"),
|
||||
"return_basis": preserved["return_basis"],
|
||||
"principal": _strict_int(preserved["principal"], "principal"),
|
||||
"interest": _strict_int(preserved["interest"], "interest"),
|
||||
"fee": _strict_int(preserved["fee"], "fee"),
|
||||
"representative_liability_definition": preserved["representative_liability_definition"].strip() if preserved["representative_liability_definition"] else None,
|
||||
"supersedes_id": valuation_id,
|
||||
"correction_reason": correction_reason.strip(),
|
||||
}
|
||||
except (TypeError, ValueError, AttributeError) as exc:
|
||||
return fail("validation_error", str(exc))
|
||||
if idempotency_key:
|
||||
prior = conn.execute("SELECT * FROM account_valuations WHERE account_id=? AND idempotency_key=?", (source["account_id"], idempotency_key)).fetchone()
|
||||
if prior:
|
||||
expected = {"amount": amount, "supersedes_id": valuation_id, "correction_reason": correction_reason.strip()}
|
||||
expected.update(preserved)
|
||||
if all(prior[k] == v for k, v in expected.items() if k in prior.keys()):
|
||||
if all(prior[key] == value for key, value in effective.items()):
|
||||
return ok(valuation=_valuation(prior), reused=True)
|
||||
return fail("idempotency_conflict", "idempotency_key already has a different payload", valuation=_valuation(prior))
|
||||
if conn.execute("SELECT 1 FROM account_valuations WHERE supersedes_id=?", (valuation_id,)).fetchone():
|
||||
return fail("correction_conflict", "valuation already has a correction")
|
||||
child = conn.execute("SELECT * FROM account_valuations WHERE supersedes_id=?", (valuation_id,)).fetchone()
|
||||
if child is not None:
|
||||
if all(child[key] == value for key, value in effective.items()):
|
||||
return ok(valuation=_valuation(child), reused=True)
|
||||
return fail("correction_conflict", "correction payload conflicts with existing correction", valuation=_valuation(child))
|
||||
return register_account_valuation(
|
||||
source["account_id"], source["basis_date"], amount,
|
||||
**preserved,
|
||||
|
||||
Reference in New Issue
Block a user