Files
jarca-ledger-mcp/dashboard/page_views/cross_transfer_review.py
T

76 lines
3.6 KiB
Python

from __future__ import annotations
# ruff: noqa: F405
import sqlite3
import pandas as pd
import streamlit as st
from jarca_ledger_mcp.adapters.streamlit import transfers_gateway
from dashboard.common import * # noqa: F403, F405
def page_cross_transfer_review(db_path: str) -> None:
c1, c2 = st.columns(2)
with c1:
if st.button("미리보기(드라이런)"):
st.session_state["cross_transfer_preview"] = transfers_gateway.preview_cross_account_transfers(db_path=db_path)
with c2:
if st.button("자동 매칭 실행"):
res = transfers_gateway.run_cross_account_transfer_match(db_path=db_path)
clear_cache()
st.session_state["cross_transfer_last_run"] = res
st.success(f"매칭 {res.get('matched_count', 0)}건 적용, 확인필요 {res.get('review_count', 0)}건")
st.rerun()
if "cross_transfer_preview" in st.session_state:
prev = st.session_state["cross_transfer_preview"]
render_section_label("🧪", "미리보기 결과")
st.info(f"예상 매칭 {prev.get('matched_count', 0)}건 / 확인필요 {prev.get('review_count', 0)}건")
if prev.get("matched_pairs"):
st.dataframe(pd.DataFrame(prev.get("matched_pairs")), width="stretch", height=250)
if prev.get("review_items"):
st.dataframe(pd.DataFrame(prev.get("review_items")), width="stretch", height=250)
st.divider()
render_section_label("📌", "확인필요 큐")
list_queue_fn = getattr(transfers_gateway, "list_cross_transfer_review_queue", None)
if callable(list_queue_fn):
queue = list_queue_fn(db_path=db_path)
rows = queue.get("transactions", [])
else:
# 호환성 보호: 구버전 서비스에서 메서드가 없을 때 직접 조회
st.info("확인필요 큐 조회 함수가 현재 서비스 모듈에 없어 직접 DB 조회로 표시합니다.")
with sqlite3.connect(db_path) as _conn:
_conn.row_factory = lambda cursor, row: {description[0]: row[idx] for idx, description in enumerate(cursor.description)}
_rows = _conn.execute(
"""
SELECT * FROM transactions
WHERE status='active'
AND source IN ('kb_bank_pdf','toss_bank_pdf')
AND memo LIKE '%cross_transfer_review:%'
ORDER BY transaction_date DESC, created_at DESC
LIMIT 300
"""
).fetchall()
rows = [dict(r) for r in _rows]
if not rows:
st.success("현재 확인필요 큐가 비어 있습니다.")
return
df = pd.DataFrame(rows)
if "cashflow_kind" in df.columns:
df["cashflow_kind"] = df["cashflow_kind"].fillna("")
st.dataframe(df[["transaction_date", "source", "type", "amount", "counterparty", "category", "subcategory", "memo", "id"]].rename(columns={"amount": "금액"}), width="stretch", height=320)
options = {
f"{r.get('transaction_date')} · {r.get('source')} · {r.get('type')} · {int(r.get('amount', 0)):,}원 · {r.get('counterparty', '')}": r
for r in rows
}
selected = st.selectbox("수동 수정할 거래", list(options.keys()))
selected_row = options[selected]
st.caption(f"현재 review_status: {selected_row.get('review_status', 'pending')}")
with st.expander("Review decision 저장/보류/재검토/해제", expanded=False):
render_review_decision_actions(transfers_gateway, "cross_transfer", selected_row["id"], f"transfer_review_decision_{selected_row['id']}", db_path, target_payload=selected_row)
update_transaction_form(selected_row, "transfer_review", db_path)