mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 11:06:40 +07:00
Track individual coins (identity + quantity) in a dedicated tab, backed by CoinGecko's Demo API (AURUM_COINGECKO_API_KEY). A holding is just another Asset under the hood (asset_class=crypto) with its value written as a regular AssetValuation — the existing Net Worth aggregation needs zero changes to pick it up. Prices never refresh in the background (no scheduler in this stack, same reasoning as recurring transactions): a "Refresh prices" button forces a sync, and GET /crypto/holdings lazily re-syncs at most once every 24h. CoinGecko outages leave existing values untouched (error_key: "unreachable") instead of failing the request. Backup/restore now carries CryptoHolding rows too, so a restore doesn't silently strip a holding's coin identity. Backend: 75/75 tests passing (9 new), including a real identity-map staleness bug the tests caught in the raw-Core-upsert + ORM re-read pattern, fixed via populate_existing=True. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01855PiW5Wd8n4aRW4n9kByY
73 lines
2.0 KiB
Python
73 lines
2.0 KiB
Python
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.api.routes import (
|
|
accounts,
|
|
advice,
|
|
assets,
|
|
backup,
|
|
budgets,
|
|
cash_flow,
|
|
categories,
|
|
crypto,
|
|
dashboard,
|
|
goals,
|
|
insights,
|
|
net_worth,
|
|
recurring,
|
|
reports,
|
|
settings as settings_routes,
|
|
tags,
|
|
transactions,
|
|
)
|
|
from app.core.config import APP_VERSION, get_settings
|
|
from app.db.seed import seed_default_account, seed_default_app_settings, seed_default_categories
|
|
from app.db.session import AsyncSessionLocal
|
|
|
|
settings = get_settings()
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
async with AsyncSessionLocal() as session:
|
|
await seed_default_categories(session)
|
|
await seed_default_account(session)
|
|
await seed_default_app_settings(session)
|
|
yield
|
|
|
|
|
|
app = FastAPI(title="Aurum API", version=APP_VERSION, lifespan=lifespan)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins_list,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
app.include_router(dashboard.router, prefix="/api")
|
|
app.include_router(accounts.router, prefix="/api")
|
|
app.include_router(categories.router, prefix="/api")
|
|
app.include_router(transactions.router, prefix="/api")
|
|
app.include_router(assets.router, prefix="/api")
|
|
app.include_router(net_worth.router, prefix="/api")
|
|
app.include_router(backup.router, prefix="/api")
|
|
app.include_router(reports.router, prefix="/api")
|
|
app.include_router(insights.router, prefix="/api")
|
|
app.include_router(settings_routes.router, prefix="/api")
|
|
app.include_router(budgets.router, prefix="/api")
|
|
app.include_router(advice.router, prefix="/api")
|
|
app.include_router(goals.router, prefix="/api")
|
|
app.include_router(recurring.router, prefix="/api")
|
|
app.include_router(cash_flow.router, prefix="/api")
|
|
app.include_router(tags.router, prefix="/api")
|
|
app.include_router(crypto.router, prefix="/api")
|
|
|
|
|
|
@app.get("/api/health")
|
|
async def health() -> dict[str, str]:
|
|
return {"status": "ok"}
|