fix: address account valuation review findings
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
from types import SimpleNamespace
|
||||
import sqlite3
|
||||
|
||||
from jarca_ledger_mcp import service
|
||||
from jarca_ledger_mcp.application import imports_service
|
||||
|
||||
|
||||
def _parsed(transaction, source_hash):
|
||||
return {
|
||||
"transactions": [transaction],
|
||||
"validation": {"ok": True},
|
||||
"source_hash": source_hash,
|
||||
"metadata": {"final_balance": transaction.balance_after, "account_number_masked": ""},
|
||||
"file_path": "/tmp/synthetic.pdf",
|
||||
"page_count": 1,
|
||||
}
|
||||
|
||||
|
||||
def _transaction(date, balance, row):
|
||||
return SimpleNamespace(
|
||||
transaction_date=date,
|
||||
transaction_datetime=f"{date} 10:00:00",
|
||||
amount=100,
|
||||
counterparty="상대",
|
||||
raw_summary="이체",
|
||||
branch="",
|
||||
remittance_memo="",
|
||||
balance_after=balance,
|
||||
type="income",
|
||||
page=1,
|
||||
action="입금",
|
||||
external_id=lambda source_hash: f"kb:{source_hash}:{row}",
|
||||
raw_payload=lambda: "{}",
|
||||
)
|
||||
|
||||
|
||||
def test_late_import_current_balance_is_authoritative_by_evidence_basis_date(monkeypatch, tmp_path):
|
||||
path = str(tmp_path / "ledger.sqlite3")
|
||||
account = service.create_ledger_account(
|
||||
"KB", institution="KB국민은행", db_path=path,
|
||||
)["account"]["id"]
|
||||
imports = iter(
|
||||
(
|
||||
(_transaction("2026-06-01", 700, 1), "hash-old"),
|
||||
(_transaction("2026-06-30", 900, 2), "hash-new"),
|
||||
)
|
||||
)
|
||||
monkeypatch.setattr(imports_service, "parse_kb_bank_pdf", lambda *_: _parsed(*next(imports)))
|
||||
sync_times = iter(("2026-07-01T09:00:00", "2026-07-02T09:00:00"))
|
||||
monkeypatch.setattr(imports_service, "now_iso", lambda: next(sync_times))
|
||||
|
||||
older = imports_service.import_kb_bank_pdf("older", "pw", account_id=account, db_path=path)
|
||||
newer = imports_service.import_kb_bank_pdf("newer", "pw", account_id=account, db_path=path)
|
||||
|
||||
current = service.list_ledger_accounts(active_only=False, db_path=path)["accounts"][0]
|
||||
valuations = service.list_account_valuations(account, db_path=path)["valuations"]
|
||||
|
||||
assert older["success"] and newer["success"]
|
||||
assert current["last_balance"] == 900
|
||||
assert current["last_synced_at"] == "2026-07-02T09:00:00"
|
||||
assert current["last_balance_basis_date"] == "2026-06-30"
|
||||
assert {(item["basis_date"], item["amount"]) for item in valuations} >= {
|
||||
("2026-06-01", 700),
|
||||
("2026-06-30", 900),
|
||||
}
|
||||
|
||||
|
||||
def test_account_write_sync_timestamp_does_not_infer_balance_basis_or_candidate(tmp_path):
|
||||
path = str(tmp_path / "ledger.sqlite3")
|
||||
unknown = service.create_ledger_account(
|
||||
"기준일 미상",
|
||||
last_balance=500,
|
||||
last_synced_at="2026-07-01T09:00:00+09:00",
|
||||
db_path=path,
|
||||
)
|
||||
|
||||
assert unknown["success"] is True
|
||||
assert unknown["account"]["last_balance_basis_date"] == ""
|
||||
assert service.list_account_valuations(unknown["account"]["id"], db_path=path)["count"] == 0
|
||||
|
||||
dated = service.create_ledger_account(
|
||||
"기준일 확인",
|
||||
last_balance=600,
|
||||
last_synced_at="2026-07-01T09:00:00+09:00",
|
||||
db_path=path,
|
||||
last_balance_basis_date="2026-06-30",
|
||||
)
|
||||
valuations = service.list_account_valuations(dated["account"]["id"], db_path=path)["valuations"]
|
||||
assert dated["account"]["last_balance_basis_date"] == "2026-06-30"
|
||||
assert [(item["basis_date"], item["amount"]) for item in valuations] == [("2026-06-30", 600)]
|
||||
|
||||
|
||||
def test_unknown_legacy_balance_basis_is_not_reported_as_valuation_date(tmp_path):
|
||||
path = str(tmp_path / "ledger.sqlite3")
|
||||
account = service.create_ledger_account("legacy", db_path=path)["account"]["id"]
|
||||
with sqlite3.connect(path) as conn:
|
||||
conn.execute(
|
||||
"UPDATE accounts SET last_balance=?, last_synced_at=?, last_balance_basis_date='' WHERE id=?",
|
||||
(500, "2026-07-01T09:00:00+09:00", account),
|
||||
)
|
||||
|
||||
report = service.get_asset_snapshot_report("2026-06-30", db_path=path)
|
||||
excluded = next(item for item in report["excluded_items"] if item["source_id"] == account)
|
||||
assert excluded["valuation_date"] == ""
|
||||
assert excluded["last_synced_at"] == "2026-07-01T09:00:00+09:00"
|
||||
Reference in New Issue
Block a user