fix: address settlement display and documentation review findings

Rework Issue 18 / PR 19, source review 76: C11-F01 and D02-F02/D03-F03/D04-F04. Preserve the approved contract and add named display, schema, policy, ownership and signature regressions.
This commit is contained in:
2026-10-13 13:09:16 +00:00
parent 616bb7a744
commit ae4383ca2c
7 changed files with 296 additions and 3 deletions
+14 -2
View File
@@ -275,12 +275,24 @@ def page_monthly_settlement(db_path: str) -> None:
if not saved.get("success"):
st.info("저장된 스냅샷이 없거나 조회할 수 없습니다.")
else:
snapshot = saved.get("snapshot", saved)
st.caption(f"run {snapshot.get('run_id', '미보존')} · 버전 {snapshot.get('aggregation_version', 'legacy')} · 출처 {snapshot.get('source', '미보존')}")
snapshot = saved.get("snapshot") if isinstance(saved.get("snapshot"), dict) else saved
st.caption(f"run {snapshot.get('run_id', snapshot.get('snapshot_run_id', '미보존'))} · 버전 {snapshot.get('aggregation_version') or 'legacy'} · 출처 {snapshot.get('source', '미보존')}")
st.caption(f"close_status: {snapshot.get('close_status', '미보존')} · legacy: {snapshot.get('legacy', '미보존')} · comprehensive: {snapshot.get('is_comprehensive', '미보존')}")
if snapshot.get("close_status") == "conditional":
st.caption("조건부 마감 상태 (부분 승인 조건 적용)")
for key, label in (("income_total", "수입"), ("expense_total", "지출"), ("net_cashflow", "순현금흐름"), ("total_assets", "자산"), ("total_liabilities", "부채"), ("net_worth", "순자산")):
st.write(label, snapshot.get(key) if snapshot.get(key) is not None else "미보존")
rows = snapshot.get("cashflow_items", [])
if isinstance(rows, list): st.dataframe([{k: row.get(k) for k in ("cashflow_kind", "category", "subcategory", "amount", "transaction_count", "currency")} for row in rows if isinstance(row, dict)])
source_snapshot = snapshot.get("source_snapshot") if isinstance(snapshot.get("source_snapshot"), dict) else {}
asset_evidence = snapshot.get("items") if isinstance(snapshot.get("items"), list) else []
source_assets = source_snapshot.get("assets") if isinstance(source_snapshot.get("assets"), list) else []
safe_asset_fields = ("source_type", "source_id", "status", "valuation_id", "valuation_date", "amount", "applied_amount", "verification_status", "authority_source", "exclusion_reason", "currency", "name", "evidence_kind", "valuation_source", "selection_mode", "selection_policy")
st.markdown("**저장 자산 근거**")
st.caption("누락(missing)·제외(excluded) 항목과 저장된 사유를 표시합니다. 미보존 근거는 추정하지 않습니다.")
asset_rows = list(asset_evidence)
asset_rows.extend(source_assets)
st.dataframe([{k: row.get(k) for k in safe_asset_fields} for row in asset_rows if isinstance(row, dict)])
st.divider()
render_settlement_drafts(db_path=db_path, month=selected_month)
+7 -1
View File
@@ -210,7 +210,13 @@ def render_settlement_drafts(db_path: str | None = None, month: str = "") -> Non
items_cf = review.get("cashflow_items", [])
if isinstance(items_cf, list): st.dataframe([{k: row.get(k) for k in ("cashflow_kind", "category", "subcategory", "amount", "transaction_count", "currency")} for row in items_cf if isinstance(row, dict)])
blockers = review.get("cashflow_blockers", [])
for blocker in blockers if isinstance(blockers, list) else []: st.warning(str(blocker.get("code", "cashflow_blocked")) if isinstance(blocker, dict) else "현금흐름 블로커")
for blocker in blockers if isinstance(blockers, list) else []:
if isinstance(blocker, dict):
transaction_id = blocker.get("transaction_id")
reason = blocker.get("reason")
st.warning(f"거래 {transaction_id if isinstance(transaction_id, str) else '-'} · {reason if isinstance(reason, str) else '현금흐름 블로커'}")
else:
st.warning("현금흐름 블로커")
st.write("누락", review.get("missing_items", []))
if review.get("contains_substitutions"):
st.warning("대체 평가자료를 포함한 월정산")