groupe-meditation/backend/app/routers/evenements.py

133 lines
4 KiB
Python
Raw Normal View History

2026-05-25 17:39:38 -04:00
"""Routes — Événements (anniversaires + ad hoc)."""
2026-04-17 04:04:04 -04:00
from datetime import date, timedelta
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
2026-05-25 17:39:38 -04:00
from sqlalchemy import select
2026-04-17 04:04:04 -04:00
from app.core.database import get_db
from app.core.security import get_current_membre, require_executif
from app.models.groupe import Groupe
from app.models.membre import Membre
from app.models.affectation import Affectation
from app.models.poste import Poste
from app.models.evenement import Evenement
router = APIRouter(prefix="/evenements", tags=["Événements"])
2026-04-17 04:04:04 -04:00
def _anniversaire_sobriete(date_abstinence: date, annee: int) -> tuple[int, date]:
2026-04-17 04:04:04 -04:00
try:
anniv = date_abstinence.replace(year=annee)
2026-04-17 04:04:04 -04:00
except ValueError:
anniv = date(annee, 3, 1)
return max(0, anniv.year - date_abstinence.year), anniv
2026-04-17 04:04:04 -04:00
@router.get("/")
async def evenements_a_venir(
jours: int = 90,
jours_avant: int = 365,
2026-04-17 04:04:04 -04:00
membre=Depends(get_current_membre),
db: AsyncSession = Depends(get_db),
):
2026-05-25 17:39:38 -04:00
"""Tous les événements : anniversaires et ad hoc."""
2026-04-17 04:04:04 -04:00
aujourdhui = date.today()
debut = aujourdhui - timedelta(days=jours_avant)
2026-04-17 04:04:04 -04:00
limite = aujourdhui + timedelta(days=jours)
groupe = await db.get(Groupe, membre.groupe_id)
if not groupe:
return []
2026-04-17 04:04:04 -04:00
evenements = []
# ── 1. Anniversaires de sobriété du groupe ──
2026-04-17 04:04:04 -04:00
result = await db.execute(
select(Membre)
2026-04-17 04:04:04 -04:00
.where(
Membre.groupe_id == membre.groupe_id,
2026-04-17 04:04:04 -04:00
Membre.actif == True,
Membre.date_abstinence.isnot(None),
)
)
for m in result.scalars().all():
for annee in range(debut.year, limite.year + 1):
annees, anniv = _anniversaire_sobriete(m.date_abstinence, annee)
if anniv < debut or anniv > limite:
continue
2026-04-17 04:04:04 -04:00
evenements.append({
"type": "anniversaire",
"date": str(anniv),
2026-04-17 04:04:04 -04:00
"titre": f"🎂 {m.prenom} — {annees} an{'s' if annees > 1 else ''}",
"detail": f"Anniversaire de sobriété · {groupe.nom}",
2026-04-17 04:04:04 -04:00
"lieu": None,
"groupe_nom": groupe.nom,
2026-04-17 04:04:04 -04:00
})
# ── 2. Événements ad hoc ──
result = await db.execute(
select(Evenement)
2026-04-17 04:04:04 -04:00
.where(
Evenement.groupe_id == membre.groupe_id,
Evenement.date_evenement >= debut,
2026-04-17 04:04:04 -04:00
Evenement.date_evenement <= limite,
)
)
for ev in result.scalars().all():
2026-04-17 04:04:04 -04:00
evenements.append({
"type": "adhoc",
"date": str(ev.date_evenement),
"titre": ev.titre,
"detail": ev.description,
"lieu": ev.lieu,
"groupe_nom": groupe.nom,
2026-04-17 04:04:04 -04:00
})
# Trier par date
evenements.sort(key=lambda e: e["date"])
return evenements
# ── CRUD événements ad hoc ──
@router.post("/")
async def creer_evenement(
titre: str,
date_evenement: date,
description: str = "",
lieu: str = "",
executif=Depends(require_executif),
db: AsyncSession = Depends(get_db),
):
"""Créer un événement ad hoc (exécutif)."""
ev = Evenement(
groupe_id=executif.groupe_id,
titre=titre.strip(),
description=description.strip() or None,
date_evenement=date_evenement,
lieu=lieu.strip() or None,
cree_par=executif.id,
)
db.add(ev)
await db.flush()
return {"message": "Événement créé", "id": str(ev.id)}
@router.delete("/{evenement_id}")
async def supprimer_evenement(
evenement_id: str,
executif=Depends(require_executif),
db: AsyncSession = Depends(get_db),
):
result = await db.execute(
select(Evenement).where(
Evenement.id == evenement_id,
Evenement.groupe_id == executif.groupe_id,
)
)
ev = result.scalar_one_or_none()
if not ev:
raise HTTPException(status_code=404, detail="Événement introuvable")
await db.delete(ev)
await db.flush()
return {"message": "Événement supprimé"}