""" Application FastAPI principale pour Notytex v2. """ from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from sqlalchemy import text, inspect from core.config import settings from infrastructure.database.session import async_engine, sync_engine from infrastructure.database.models import ( ClassGroup, Student, Assessment, Exercise, GradingElement, Grade, ) # Import des routes from api.routes import classes, students, assessments, config, council @asynccontextmanager async def lifespan(app: FastAPI): """ Gestion du cycle de vie de l'application. """ # Startup print(f"Starting {settings.app_name} v{settings.app_version}") yield # Shutdown await async_engine.dispose() print("Application shutdown complete") app = FastAPI( title=settings.app_name, version=settings.app_version, description="API REST pour le système de gestion scolaire Notytex", docs_url=f"{settings.api_v2_prefix}/docs", redoc_url=f"{settings.api_v2_prefix}/redoc", openapi_url=f"{settings.api_v2_prefix}/openapi.json", lifespan=lifespan, ) # Configuration CORS app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get(f"{settings.api_v2_prefix}/health") async def health_check(): """ Endpoint de santé pour vérifier que l'API est opérationnelle et connectée à la base de données. Returns: Dict avec statut, connexion DB et comptage des entités """ try: # Utiliser une connexion sync pour l'inspection des tables # car inspect() n'est pas async with sync_engine.connect() as conn: inspector = inspect(sync_engine) tables = inspector.get_table_names() # Compter les entités principales classes_count = conn.execute(text("SELECT COUNT(*) FROM class_group")).scalar() students_count = conn.execute(text("SELECT COUNT(*) FROM student")).scalar() assessments_count = conn.execute(text("SELECT COUNT(*) FROM assessment")).scalar() return { "status": "healthy", "database": "connected", "tables": len(tables), "classes": classes_count, "students": students_count, "assessments": assessments_count, } except Exception as e: return { "status": "unhealthy", "database": "disconnected", "error": str(e), } @app.get("/") async def root(): """Redirection vers la documentation API.""" return { "message": f"Bienvenue sur {settings.app_name}", "version": settings.app_version, "docs": f"{settings.api_v2_prefix}/docs", } # Enregistrement des routes app.include_router(classes.router, prefix=settings.api_v2_prefix) app.include_router(students.router, prefix=settings.api_v2_prefix) app.include_router(assessments.router, prefix=settings.api_v2_prefix) app.include_router(config.router, prefix=settings.api_v2_prefix) app.include_router(council.router, prefix=settings.api_v2_prefix)