fire-planner/tests/test_db_schema.py
2026-05-07 17:06:19 +00:00

111 lines
3.8 KiB
Python

"""Smoke-test the ORM schema — every table must round-trip a row."""
from datetime import date
from decimal import Decimal
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from fire_planner.db import (
AccountSnapshot,
McPath,
McRun,
ProjectionYearly,
Scenario,
ScenarioSummary,
)
async def test_account_snapshot_roundtrip(session: AsyncSession) -> None:
snap = AccountSnapshot(
external_id="wealthfolio:account-1:2026-04-25",
snapshot_date=date(2026, 4, 25),
account_id="account-1",
account_name="ISA",
account_type="ISA",
currency="GBP",
market_value=Decimal("123456.78"),
market_value_gbp=Decimal("123456.78"),
)
session.add(snap)
await session.commit()
result = await session.execute(select(AccountSnapshot))
rows = result.scalars().all()
assert len(rows) == 1
assert rows[0].external_id == "wealthfolio:account-1:2026-04-25"
async def test_scenario_roundtrip(session: AsyncSession) -> None:
scen = Scenario(
external_id="cyprus-vpw-leave-y3-glide-rising",
jurisdiction="cyprus",
strategy="vpw",
leave_uk_year=3,
glide_path="rising",
spending_gbp=Decimal("100000"),
nw_seed_gbp=Decimal("1000000"),
savings_per_year_gbp=Decimal("100000"),
config_json={"horizon_years": 60},
)
session.add(scen)
await session.commit()
result = await session.execute(select(Scenario))
rows = result.scalars().all()
assert len(rows) == 1
assert rows[0].jurisdiction == "cyprus"
async def test_mc_run_roundtrip(session: AsyncSession) -> None:
run = McRun(
scenario_id=1,
n_paths=10000,
seed=42,
success_rate=Decimal("0.9412"),
p10_ending_gbp=Decimal("250000"),
p50_ending_gbp=Decimal("3500000"),
p90_ending_gbp=Decimal("12000000"),
median_lifetime_tax_gbp=Decimal("750000"),
elapsed_seconds=Decimal("42.351"),
)
session.add(run)
await session.commit()
result = await session.execute(select(McRun))
rows = result.scalars().all()
assert len(rows) == 1
assert rows[0].n_paths == 10000
async def test_remaining_tables_smoke(session: AsyncSession) -> None:
session.add(
McPath(mc_run_id=1,
path_idx=0,
bucket="median",
year_idx=0,
portfolio_gbp=Decimal("1000000"),
withdrawal_gbp=Decimal("100000"),
tax_paid_gbp=Decimal("0"),
real_portfolio_gbp=Decimal("1000000")))
session.add(
ProjectionYearly(mc_run_id=1,
year_idx=0,
p10_portfolio_gbp=Decimal("800000"),
p25_portfolio_gbp=Decimal("900000"),
p50_portfolio_gbp=Decimal("1000000"),
p75_portfolio_gbp=Decimal("1100000"),
p90_portfolio_gbp=Decimal("1200000"),
p50_withdrawal_gbp=Decimal("100000"),
p50_tax_gbp=Decimal("0"),
survival_rate=Decimal("1")))
session.add(
ScenarioSummary(scenario_id=1,
mc_run_id=1,
jurisdiction="uk",
strategy="trinity",
leave_uk_year=0,
glide_path="static",
spending_gbp=Decimal("100000"),
success_rate=Decimal("0.95"),
p10_ending_gbp=Decimal("200000"),
p50_ending_gbp=Decimal("3000000"),
p90_ending_gbp=Decimal("10000000"),
median_lifetime_tax_gbp=Decimal("800000")))
await session.commit()