73 lines
3.2 KiB
Python
73 lines
3.2 KiB
Python
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).parents[1]
|
|
|
|
|
|
def _text(relative_path: str) -> str:
|
|
return (ROOT / relative_path).read_text(encoding="utf-8")
|
|
|
|
|
|
def test_data_model_documents_cache_authority_and_legacy_basis_migration() -> None:
|
|
data_model = _text("docs/data-model.md")
|
|
|
|
required_contract = (
|
|
"`last_balance` is the current cache value",
|
|
"`last_balance_basis_date`",
|
|
"`last_synced_at` is the execution/sync timestamp",
|
|
"imports and account writes advance the account cache",
|
|
"`account_valuations` is the historical authority",
|
|
"older evidence never rolls back the current cache",
|
|
"additive migration",
|
|
"legacy rows with unknown basis remain unknown; no inference",
|
|
)
|
|
for marker in required_contract:
|
|
assert marker in data_model, marker
|
|
|
|
|
|
def test_interface_contract_documents_public_valuation_enums_validation_and_mapping() -> None:
|
|
interface = _text("docs/interface-contract.md")
|
|
|
|
assert "actual enums in source" not in interface
|
|
required_contract = (
|
|
"source_type: `manual`, `import`, `account_write`, `reconciliation`, `snapshot`",
|
|
"verification_status: `verified`, `unverified`, `rejected`",
|
|
"valuation_kind: `balance`, `cash_balance`, `total_value`, `loan`, `loan_balance`",
|
|
"representative_liability_definition: `principal_only`, `principal_interest_fees`",
|
|
"loan accounts require representative_liability_definition for `loan`, `loan_balance`, and `balance` aliases",
|
|
"legacy valuation-kind aliases remain accepted and map to the canonical purpose",
|
|
"validation failure returns `validation_error` and performs no write",
|
|
"loan valuations map to liabilities and non-loan valuations map to assets",
|
|
)
|
|
for marker in required_contract:
|
|
assert marker in interface, marker
|
|
|
|
|
|
def test_data_model_documents_valuation_selection_contract_and_index_mapping() -> None:
|
|
data_model = _text("docs/data-model.md")
|
|
|
|
required_contract = (
|
|
"select_account_valuation",
|
|
"account_id is mandatory",
|
|
"currency and valuation_kind/purpose are optional filters",
|
|
"basis_date exact match or <= upper bound",
|
|
"verified leaf valuations only",
|
|
"future-dated and unverified valuations are excluded",
|
|
"idx_account_valuations_account_date supports account/date selection",
|
|
"idx_account_valuations_status_date supports status/date selection",
|
|
"neither index covers account + currency + purpose",
|
|
"idempotency and single_correction indexes enforce write integrity, not selection",
|
|
)
|
|
for marker in required_contract:
|
|
assert marker in data_model, marker
|
|
|
|
|
|
def test_loan_cache_writers_document_no_inferred_valuation_history() -> None:
|
|
data_model = _text("docs/data-model.md")
|
|
interface = _text("docs/interface-contract.md")
|
|
requirement = _text("docs/requirements/req-003_account-valuation-history.md")
|
|
|
|
assert "loan cache writes without an explicit liability definition do not append" in data_model
|
|
assert "loan cache writes without an explicit liability definition do not append" in interface
|
|
assert "대출 cache write는 대표 부채 정의가 없으면 이력 후보를 추가하지 않는다" in requirement
|