Files
denya-onecare/app/main.py
T

78 lines
2.9 KiB
Python

"""Denya OneCare — FastAPI application entry point."""
from __future__ import annotations
import logging
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from sqlalchemy import text
from app.core.config import settings
from app.core.database import Base, async_session_factory, engine
from app.routers import auth, health, pages, tickets, whatsapp
from app.services.seed import seed_categories, seed_units, seed_users
logger = logging.getLogger(__name__)
async def ensure_legacy_schema(conn) -> None:
"""Add columns from alembic migrations that legacy create_all databases lack."""
result = await conn.execute(text("PRAGMA table_info(categories)"))
columns = {row[1] for row in result}
if "show_in_form" not in columns:
await conn.execute(
text("ALTER TABLE categories ADD COLUMN show_in_form BOOLEAN NOT NULL DEFAULT 1")
)
logger.info("Added missing categories.show_in_form column (legacy database)")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Initialise database and seed data on startup."""
logger.info("Starting Denya OneCare …")
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
await ensure_legacy_schema(conn)
async with async_session_factory() as session:
await seed_users(session)
await session.commit()
await seed_units(session, json_path=str(settings.BASE_DIR / "apartment_mapping.json"))
await session.commit()
await seed_categories(session)
await session.commit()
yield
await engine.dispose()
logger.info("Denya OneCare stopped.")
app = FastAPI(
title=settings.APP_NAME,
version="0.1.0",
lifespan=lifespan,
)
# ── CORS ─────────────────────────────────────────────────────────────
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS.split(",") if settings.CORS_ORIGINS != "*" else ["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ── Static files (uploads) ───────────────────────────────────────────
uploads_dir = Path(settings.BASE_DIR / "uploads")
uploads_dir.mkdir(parents=True, exist_ok=True)
app.mount("/uploads", StaticFiles(directory=str(uploads_dir)), name="uploads")
# ── Routers ──────────────────────────────────────────────────────────
app.include_router(health.router)
app.include_router(auth.router)
app.include_router(whatsapp.router)
app.include_router(tickets.router)
app.include_router(pages.router)