"""Routes C3 — Anniversaires district 87-16.""" from datetime import date, timedelta from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.core.database import get_db from app.core.security import get_current_membre from app.models.membre import Membre from app.models.groupe import Groupe from app.schemas.phase5 import AnniversaireOut router = APIRouter(prefix="/anniversaires", tags=["C3 — Anniversaires district"]) def _calcul_anniversaire(date_abstinence: date, aujourdhui: date) -> tuple[int, date, int]: """Calcule les années de sobriété, le prochain anniversaire et les jours restants.""" annees = aujourdhui.year - date_abstinence.year # Anniversaire cette année try: anniv_cette_annee = date_abstinence.replace(year=aujourdhui.year) except ValueError: # 29 février anniv_cette_annee = date(aujourdhui.year, 3, 1) if anniv_cette_annee < aujourdhui: # L'anniversaire de cette année est passé try: prochain = date_abstinence.replace(year=aujourdhui.year + 1) except ValueError: prochain = date(aujourdhui.year + 1, 3, 1) annees_sobriete = annees elif anniv_cette_annee == aujourdhui: prochain = anniv_cette_annee annees_sobriete = annees else: prochain = anniv_cette_annee annees_sobriete = annees - 1 # Minimum 0 annees_sobriete = max(0, annees_sobriete) jours_restants = (prochain - aujourdhui).days return annees_sobriete, prochain, jours_restants @router.get("/", response_model=list[AnniversaireOut]) async def anniversaires_district( prochains_jours: int = 90, membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """C3 — Anniversaires de sobriété de tous les groupes du district 87-16.""" aujourdhui = date.today() # Récupérer le district du groupe du membre groupe = await db.get(Groupe, membre.groupe_id) district = groupe.district if groupe else "87-16" # Tous les membres actifs du district ayant une date d'abstinence result = await db.execute( select(Membre, Groupe.nom) .join(Groupe, Membre.groupe_id == Groupe.id) .where( Groupe.district == district, Membre.actif == True, Membre.date_abstinence.isnot(None), ) ) rows = result.all() anniversaires = [] for m, groupe_nom in rows: annees_sobriete, prochain, jours_restants = _calcul_anniversaire(m.date_abstinence, aujourdhui) # Filtrer : prochains X jours OU anniversaire aujourd'hui if 0 <= jours_restants <= prochains_jours: anniversaires.append(AnniversaireOut( membre_prenom=m.prenom, groupe_nom=groupe_nom, date_abstinence=m.date_abstinence, annees_sobriete=annees_sobriete + 1, # prochain anniversaire = +1 prochain_anniversaire=prochain, jours_restants=jours_restants, )) # Trier par jours restants (prochains en premier) anniversaires.sort(key=lambda a: a.jours_restants) return anniversaires