groupe-meditation/backend/app/routers/anniversaires.py
Daniel Allaire 393f9243cb Renforcer isolation multi-tenant
- scoper les postes et permissions par groupe

- retirer les lectures district du calendrier, des evenements et anniversaires

- documenter les regles d isolation multi-groupe
2026-05-31 18:12:26 -04:00

86 lines
2.9 KiB
Python

"""Routes C3 — Anniversaires du groupe."""
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"])
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_groupe(
prochains_jours: int = 90,
membre=Depends(get_current_membre),
db: AsyncSession = Depends(get_db),
):
"""C3 — Anniversaires de sobriété du groupe courant."""
aujourdhui = date.today()
groupe = await db.get(Groupe, membre.groupe_id)
if not groupe:
return []
result = await db.execute(
select(Membre)
.where(
Membre.groupe_id == membre.groupe_id,
Membre.actif == True,
Membre.date_abstinence.isnot(None),
)
)
anniversaires = []
for m in result.scalars().all():
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