Seed historical net worth snapshots and trigger live price sync on demo startup

- seed.py: adds 30 weekly NetWorthSnapshot rows (Sep 2025 → Apr 2026) so the
  Net Worth chart has full history on first boot, not just today's value
- main.py: fires price_sync_job and fx_sync_job in the background immediately
  after the scheduler starts in demo mode, so portfolio valuations are live
  from the moment the container becomes healthy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-04-23 22:47:44 +00:00
parent 48c9e1acab
commit 664b530136
2 changed files with 63 additions and 1 deletions

View file

@ -12,7 +12,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.core.security import encrypt_field, hash_password from app.core.security import encrypt_field, hash_password
from app.db.models import ( from app.db.models import (
Account, Asset, Budget, Category, InvestmentHolding, Account, Asset, Budget, Category, InvestmentHolding,
InvestmentTransaction, ManualCGTDisposal, Payslip, InvestmentTransaction, ManualCGTDisposal, NetWorthSnapshot, Payslip,
TaxProfile, Transaction, User, TaxProfile, Transaction, User,
) )
@ -501,3 +501,56 @@ async def seed_demo(db: AsyncSession) -> None:
)) ))
await db.flush() await db.flush()
# ── Historical net worth snapshots (weekly, Oct 2025 → present) ───────
# Plausible progression: cash + growing investment portfolio, salary in
# each month, large purchases (car insurance Oct, Christmas Dec, etc.)
nw_history = [
# (date, total_assets, total_liabilities)
(date(2025, 9, 28), "8150.00", "0.00"),
(date(2025, 10, 5), "8320.00", "220.00"), # VWRP+AAPL bought, Amex started
(date(2025, 10, 12), "8050.00", "680.00"), # car insurance £485 hit
(date(2025, 10, 19), "8750.00", "820.00"), # salary in, investments ticked up
(date(2025, 10, 26), "9150.00", "820.00"),
(date(2025, 11, 2), "9820.00", "820.00"), # salary + BTC purchase Nov 1
(date(2025, 11, 9), "9600.00", "820.00"), # slight market dip
(date(2025, 11, 16), "9900.00", "820.00"),
(date(2025, 11, 23), "10150.00", "820.00"),
(date(2025, 11, 30), "10380.00", "820.00"),
(date(2025, 12, 7), "10620.00", "820.00"),
(date(2025, 12, 14), "10250.00", "1250.00"), # Christmas spending on Amex
(date(2025, 12, 21), "10100.00", "1350.00"), # VWRP 2nd buy + holiday spend
(date(2025, 12, 28), "10350.00", "1350.00"), # post-Xmas, markets recovering
(date(2026, 1, 4), "10950.00", "1100.00"), # new year, paid some Amex, markets up
(date(2026, 1, 11), "11350.00", "1100.00"),
(date(2026, 1, 18), "11700.00", "1100.00"),
(date(2026, 1, 25), "11500.00", "1100.00"), # small dip
(date(2026, 2, 1), "12050.00", "1100.00"), # salary in
(date(2026, 2, 8), "12450.00", "1100.00"),
(date(2026, 2, 15), "13050.00", "1100.00"), # VWRP 3rd buy + market run
(date(2026, 2, 22), "13500.00", "1100.00"),
(date(2026, 3, 1), "14050.00", "1100.00"), # salary in
(date(2026, 3, 8), "14450.00", "1100.00"),
(date(2026, 3, 15), "15000.00", "1050.00"),
(date(2026, 3, 22), "15500.00", "1042.50"),
(date(2026, 3, 29), "15650.00", "1042.50"),
(date(2026, 4, 5), "15680.00", "1042.50"),
(date(2026, 4, 12), "15710.00", "1042.50"),
(date(2026, 4, 19), "15740.00", "1042.50"),
]
for snap_date, assets_str, liabs_str in nw_history:
assets = Decimal(assets_str)
liabs = Decimal(liabs_str)
db.add(NetWorthSnapshot(
id=uuid.uuid4(),
user_id=uid,
date=snap_date,
total_assets=assets,
total_liabilities=liabs,
net_worth=assets - liabs,
base_currency="GBP",
breakdown={},
created_at=now,
))
await db.flush()

View file

@ -51,6 +51,15 @@ async def lifespan(app: FastAPI):
from app.workers.scheduler import start_scheduler, stop_scheduler from app.workers.scheduler import start_scheduler, stop_scheduler
await start_scheduler() await start_scheduler()
# Demo: sync live prices and FX rates immediately so portfolio values are fresh
if settings.is_demo:
import asyncio
from app.workers.price_sync import price_sync_job
from app.workers.fx_sync import fx_sync_job
asyncio.ensure_future(price_sync_job())
asyncio.ensure_future(fx_sync_job())
logger.info("demo_background_sync_queued")
logger.info("startup_complete", env=settings.environment) logger.info("startup_complete", env=settings.environment)
yield yield