feat: deliver schema 15 monthly settlement lifecycle

This commit is contained in:
2026-10-17 15:19:46 +09:00
parent dda76b3bbd
commit 38a854d525
79 changed files with 4003 additions and 1831 deletions
+5 -23
View File
@@ -1,5 +1,7 @@
from __future__ import annotations
from typing import Literal
import os
from dataclasses import dataclass
from pathlib import Path
@@ -102,8 +104,8 @@ def get_ledger_backup_status(file_path: str, include_hash: bool = True, include_
return contracts.get_ledger_backup_status(file_path, include_hash=include_hash, include_integrity=include_integrity)
@mcp.tool()
def create_ledger_account(name: str, type: str = "bank", institution: str = "", currency: str = "KRW", active: bool = True, memo: str = "", account_number_masked: str = "", holder_name: str = "", last_balance: int | None = None, last_synced_at: str = "", statement_status: str = "unknown", liquidity_bucket: str = "other", last_balance_basis_date: str = "") -> dict:
"""Create an account/card/cash/investment/loan ledger account."""
def create_ledger_account(name: str, type: Literal["bank", "card", "cash", "investment", "loan", "other", "real_estate"] = "bank", institution: str = "", currency: str = "KRW", active: bool = True, memo: str = "", account_number_masked: str = "", holder_name: str = "", last_balance: int | None = None, last_synced_at: str = "", statement_status: str = "unknown", liquidity_bucket: str | None = None, last_balance_basis_date: str = "") -> dict:
"""Create a bank/card/cash/investment/loan/other/real_estate ledger account."""
return contracts.create_ledger_account(name, type, institution, currency, active, memo, account_number_masked, holder_name, last_balance, last_synced_at, statement_status, liquidity_bucket, last_balance_basis_date=last_balance_basis_date)
@mcp.tool()
@@ -112,7 +114,7 @@ def list_ledger_accounts(active_only: bool = True) -> dict:
return contracts.list_ledger_accounts(active_only)
@mcp.tool()
def update_ledger_account(account_id: str, name: str | None = None, type: str | None = None, institution: str | None = None, currency: str | None = None, active: bool | None = None, memo: str | None = None, account_number_masked: str | None = None, holder_name: str | None = None, last_balance: int | None = None, last_synced_at: str | None = None, statement_status: str | None = None, liquidity_bucket: str | None = None, last_balance_basis_date: str | None = None) -> dict:
def update_ledger_account(account_id: str, name: str | None = None, type: Literal["bank", "card", "cash", "investment", "loan", "other", "real_estate"] | None = None, institution: str | None = None, currency: str | None = None, active: bool | None = None, memo: str | None = None, account_number_masked: str | None = None, holder_name: str | None = None, last_balance: int | None = None, last_synced_at: str | None = None, statement_status: str | None = None, liquidity_bucket: str | None = None, last_balance_basis_date: str | None = None) -> dict:
"""Update selected account fields, including statement_status/liquidity_bucket for manual reconciliation."""
return contracts.update_ledger_account(account_id, name=name, type=type, institution=institution, currency=currency, active=active, memo=memo, account_number_masked=account_number_masked, holder_name=holder_name, last_balance=last_balance, last_synced_at=last_synced_at, statement_status=statement_status, liquidity_bucket=liquidity_bucket, last_balance_basis_date=last_balance_basis_date)
@@ -141,26 +143,6 @@ def get_asset_liquidity_report() -> dict:
"""Return asset liquidity, debt, and net worth from shared account/manual valuation sources."""
return contracts.get_asset_liquidity_report()
@mcp.tool()
def list_manual_assets(active_only: bool = True) -> dict:
"""List manual non-transaction assets/liabilities used for net-worth valuation."""
return contracts.list_manual_assets(active_only=active_only)
@mcp.tool()
def create_manual_asset(name: str, valuation_amount: int, valuation_date: str, liquidity_bucket: str, source_note: str, memo: str = "", currency: str = "KRW", active: bool = True) -> dict:
"""Create a manual non-transaction asset/liability valuation row."""
return contracts.create_manual_asset(name, valuation_amount, valuation_date, liquidity_bucket, source_note=source_note, memo=memo, currency=currency, active=active)
@mcp.tool()
def update_manual_asset(asset_id: str, name: str | None = None, valuation_amount: int | None = None, valuation_date: str | None = None, liquidity_bucket: str | None = None, source_note: str | None = None, memo: str | None = None, currency: str | None = None, active: bool | None = None) -> dict:
"""Update selected fields on a manual asset/liability valuation row."""
return contracts.update_manual_asset(asset_id, name=name, valuation_amount=valuation_amount, valuation_date=valuation_date, liquidity_bucket=liquidity_bucket, source_note=source_note, memo=memo, currency=currency, active=active)
@mcp.tool()
def deactivate_manual_asset(asset_id: str, hard_delete: bool = False) -> dict:
"""Deactivate a manual asset/liability by default; hard delete only for exceptional cleanup."""
return contracts.deactivate_manual_asset(asset_id, hard_delete=hard_delete)
@mcp.tool()
def preview_asset_snapshot_close(basis_date: str = "", selection_policy: str = "exact") -> dict:
"""Preview a month-end asset snapshot close without mutating the database."""
@@ -22,8 +22,6 @@ from ...service import (
create_ledger_budget as create_ledger_budget,
create_ledger_category as create_ledger_category,
create_ledger_transaction as create_ledger_transaction,
create_manual_asset as create_manual_asset,
deactivate_manual_asset as deactivate_manual_asset,
delete_category_rule as delete_category_rule,
delete_ledger_category as delete_ledger_category,
delete_ledger_transaction as delete_ledger_transaction,
@@ -66,7 +64,6 @@ from ...service import (
list_ledger_categories as list_ledger_categories,
list_ledger_import_batches as list_ledger_import_batches,
list_ledger_transactions as list_ledger_transactions,
list_manual_assets as list_manual_assets,
list_uncategorized_transactions as list_uncategorized_transactions,
preview_asset_snapshot_close as preview_asset_snapshot_close,
preview_categorization as preview_categorization,
@@ -83,7 +80,6 @@ from ...service import (
update_category_rule as update_category_rule,
update_ledger_account as update_ledger_account,
update_ledger_transaction as update_ledger_transaction,
update_manual_asset as update_manual_asset,
)
TOOL_CONTRACTS = {
@@ -112,8 +108,6 @@ __all__ = [
"create_ledger_budget",
"create_ledger_category",
"create_ledger_transaction",
"create_manual_asset",
"deactivate_manual_asset",
"delete_category_rule",
"delete_ledger_category",
"delete_ledger_transaction",
@@ -156,7 +150,6 @@ __all__ = [
"list_ledger_categories",
"list_ledger_import_batches",
"list_ledger_transactions",
"list_manual_assets",
"list_uncategorized_transactions",
"preview_asset_snapshot_close",
"preview_categorization",
@@ -173,5 +166,4 @@ __all__ = [
"update_category_rule",
"update_ledger_account",
"update_ledger_transaction",
"update_manual_asset",
]
@@ -2,18 +2,10 @@ from __future__ import annotations
from ...service import (
close_asset_snapshot as close_asset_snapshot,
create_manual_asset as create_manual_asset,
deactivate_manual_asset as deactivate_manual_asset,
list_manual_assets as list_manual_assets,
preview_asset_snapshot_close as preview_asset_snapshot_close,
update_manual_asset as update_manual_asset,
)
__all__ = [
"close_asset_snapshot",
"create_manual_asset",
"deactivate_manual_asset",
"list_manual_assets",
"preview_asset_snapshot_close",
"update_manual_asset",
]
@@ -5,6 +5,7 @@ from ...service import (
get_balance_reconciliation_report as get_balance_reconciliation_report,
get_budget_vs_actual_report as get_budget_vs_actual_report,
get_monthly_settlement_summary as get_monthly_settlement_summary,
list_monthly_settlement_overview as list_monthly_settlement_overview,
get_monthly_cashflow_report as get_monthly_cashflow_report,
get_ledger_db_status as get_ledger_db_status,
health_check_readonly as health_check,
@@ -20,6 +21,7 @@ __all__ = [
"get_balance_reconciliation_report",
"get_budget_vs_actual_report",
"get_monthly_settlement_summary",
"list_monthly_settlement_overview",
"get_monthly_cashflow_report",
"get_ledger_db_status",
"health_check",
@@ -10,6 +10,13 @@ from ...service import (
finalize_settlement_draft as finalize_settlement_draft,
get_settlement_draft as get_settlement_draft,
get_monthly_settlement_snapshot as get_monthly_settlement_snapshot,
list_monthly_settlement_history as list_monthly_settlement_history,
get_monthly_settlement_history_record as get_monthly_settlement_history_record,
get_monthly_settlement_record as get_monthly_settlement_record,
list_account_snapshots_for_settlement as list_account_snapshots_for_settlement,
link_account_snapshot as link_account_snapshot,
unlink_account_snapshot as unlink_account_snapshot,
update_account_snapshot_category as update_account_snapshot_category,
list_account_valuations as list_account_valuations,
list_settlement_drafts as list_settlement_drafts,
refresh_settlement_draft_targets as refresh_settlement_draft_targets,
@@ -21,6 +28,8 @@ from ...service import (
)
from ...application import settlement_draft_service as _draft_service
from ...application import monthly_settlement_service as _monthly_service
from ...application.transaction_report_services import get_monthly_cashflow_report as get_monthly_cashflow_report
from ...application.transaction_report_services import get_settlement_cashflow_snapshot as get_settlement_cashflow_snapshot
from ... import service as _service
@@ -33,11 +42,36 @@ def _guard(db_path: str | None) -> str:
return db_path or _resolve_db_path()
def create_monthly_settlement(month: str, created_by: str = "dashboard-admin", *, db_path=None):
return _monthly_service.create_monthly_settlement(month, created_by=created_by, db_path=_guard(db_path))
def get_monthly_cashflow(month: str, *, settlement_id=None, closed=False, db_path=None):
if closed:
return get_settlement_cashflow_snapshot(str(settlement_id), db_path=_guard(db_path))
return get_monthly_cashflow_report(month, db_path=_guard(db_path))
def review_monthly_settlement(settlement_id: str, *, db_path=None):
return _monthly_service.review_monthly_settlement(settlement_id, db_path=_guard(db_path))
def approve_monthly_settlement(settlement_id: str, expected_version: int, review_fingerprint: str, approved_by: str = "dashboard-admin", *, db_path=None):
return _monthly_service.approve_monthly_settlement(settlement_id, expected_version, review_fingerprint, approved_by=approved_by, db_path=_guard(db_path))
def close_monthly_settlement(settlement_id: str, expected_version: int, closed_by: str = "dashboard-admin", *, db_path=None):
return _monthly_service.close_monthly_settlement(settlement_id, expected_version, closed_by=closed_by, db_path=_guard(db_path))
def cancel_monthly_settlement_approval(settlement_id: str, expected_version: int, approved_by: str = "dashboard-admin", *, db_path=None):
return _monthly_service.cancel_monthly_settlement_approval(settlement_id, expected_version, approved_by=approved_by, db_path=_guard(db_path))
def _wrap(fn):
def call(*args, db_path=None, **kwargs):
if fn.__name__ == "set_settlement_cashflow_policy":
target = _draft_service
elif fn.__name__ == "get_monthly_settlement_snapshot":
elif fn.__name__ in {"get_monthly_settlement_snapshot", "list_monthly_settlement_history", "get_monthly_settlement_history_record", "get_monthly_settlement_record", "list_account_snapshots_for_settlement", "link_account_snapshot", "unlink_account_snapshot"}:
target = _monthly_service
else:
target = _draft_service if fn.__name__ in {"create_settlement_draft", "list_settlement_drafts", "get_settlement_draft", "update_settlement_draft", "refresh_settlement_draft_targets", "set_settlement_draft_item", "review_settlement_draft", "approve_settlement_draft", "finalize_settlement_draft", "cancel_settlement_draft"} else _service
@@ -54,8 +88,10 @@ for _name in (
"update_settlement_draft", "refresh_settlement_draft_targets",
"set_settlement_draft_item", "review_settlement_draft",
"approve_settlement_draft", "finalize_settlement_draft", "cancel_settlement_draft",
"cancel_monthly_settlement_approval",
"register_account_valuation", "list_account_valuations", "correct_account_valuation",
"set_settlement_cashflow_policy", "get_monthly_settlement_snapshot",
"list_monthly_settlement_history", "get_monthly_settlement_history_record", "get_monthly_settlement_record", "list_account_snapshots_for_settlement", "link_account_snapshot", "unlink_account_snapshot", "update_account_snapshot_category",
):
globals()[_name] = _wrap(getattr(_service, _name))
@@ -64,6 +100,9 @@ __all__ = [
"update_settlement_draft", "refresh_settlement_draft_targets",
"set_settlement_draft_item", "review_settlement_draft",
"approve_settlement_draft", "finalize_settlement_draft", "cancel_settlement_draft",
"cancel_monthly_settlement_approval",
"register_account_valuation", "list_account_valuations", "correct_account_valuation",
"set_settlement_cashflow_policy", "get_monthly_settlement_snapshot",
"list_monthly_settlement_history", "get_monthly_settlement_history_record", "get_monthly_settlement_record", "list_account_snapshots_for_settlement",
"get_monthly_cashflow",
]