feat: persist review workbench decisions (#1)

Merge dcy-012 / REQ-020 / BAT-016 implementation after green CI.
This commit is contained in:
2026-07-08 10:22:53 +09:00
committed by GitHub
parent 2fc972a7bf
commit 698dd9e62e
28 changed files with 989 additions and 81 deletions
+45
View File
@@ -166,6 +166,51 @@ def get_balance_reconciliation_report(account_id: str = "", baseline_balance: in
"""Preview balance reconciliation for manual_only/partial_import accounts without mutating the DB."""
return contracts.get_balance_reconciliation_report(account_id, baseline_balance, baseline_at, source_note, memo, tolerance)
@mcp.tool()
def list_review_decisions(target_type: str = "", target_id: str = "", status: str = "", limit: int = 100) -> dict:
"""List persisted review decisions for workbench targets."""
return contracts.list_review_decisions(target_type=target_type, target_id=target_id, status=status, limit=limit)
@mcp.tool()
def upsert_review_decision(target_type: str, target_id: str, status: str = "decided", decision_type: str = "unknown", reason_code: str = "", memo: str = "", operator: str = "operator", review_after: str = "", target_payload: dict | None = None, decision_id: str = "") -> dict:
"""Create or update a non-destructive persisted review decision."""
return contracts.upsert_review_decision(target_type, target_id, status, decision_type, reason_code, memo, operator, review_after, target_payload, decision_id)
@mcp.tool()
def hold_review_decision(target_type: str, target_id: str, reason_code: str = "held", memo: str = "", operator: str = "operator", review_after: str = "") -> dict:
"""Mark a review target as held without deleting evidence."""
return contracts.hold_review_decision(target_type, target_id, reason_code, memo, operator, review_after)
@mcp.tool()
def mark_review_recheck(target_type: str, target_id: str, reason_code: str = "needs_recheck", memo: str = "", operator: str = "operator", review_after: str = "") -> dict:
"""Mark a review target as needing recheck."""
return contracts.mark_review_recheck(target_type, target_id, reason_code, memo, operator, review_after)
@mcp.tool()
def release_review_decision(target_type: str, target_id: str, memo: str = "", operator: str = "operator") -> dict:
"""Release a held/recheck review target back to pending."""
return contracts.release_review_decision(target_type, target_id, memo, operator)
@mcp.tool()
def list_reconciliation_sessions(account_id: str = "", status: str = "", basis_date: str = "", limit: int = 100) -> dict:
"""List persisted reconciliation sessions."""
return contracts.list_reconciliation_sessions(account_id=account_id, status=status, basis_date=basis_date, limit=limit)
@mcp.tool()
def upsert_reconciliation_session(account_id: str, basis_date: str, expected_balance: int | None = None, actual_balance: int | None = None, difference: int | None = None, status: str = "open", source_note: str = "", memo: str = "", operator: str = "operator", session_id: str = "") -> dict:
"""Create or update an account/basis-date reconciliation session."""
return contracts.upsert_reconciliation_session(account_id, basis_date, expected_balance, actual_balance, difference, status, source_note, memo, operator, session_id)
@mcp.tool()
def close_reconciliation_session(session_id: str = "", account_id: str = "", basis_date: str = "", memo: str = "", operator: str = "operator") -> dict:
"""Close an existing reconciliation session without destructive reset/delete."""
return contracts.close_reconciliation_session(session_id=session_id, account_id=account_id, basis_date=basis_date, memo=memo, operator=operator)
@mcp.tool()
def get_review_operating_indicators() -> dict:
"""Return workbench indicators: pending, held/recheck, unreconciled, last close, uncategorized backlog."""
return contracts.get_review_operating_indicators()
@mcp.tool()
def create_ledger_transaction(transaction_date: str = "", type: str = "expense", amount: int = 0, category: str = "", subcategory: str = "", merchant: str = "", description: str = "", account_id: str = "", payment_method: str = "", person: str = "", project: str = "", tags: list[str] | str | None = None, is_fixed: bool = False, currency: str = "KRW", posted_date: str = "", source: str = "manual", external_id: str = "", memo: str = "", dedupe: bool = True) -> dict:
"""Create an income, expense, transfer, refund, or adjustment transaction. Amount is positive KRW minor unit; type determines direction."""