groupe-meditation/backend/app/routers/presences.py
2026-05-25 17:39:38 -04:00

145 lines
5 KiB
Python

"""Routes M2 — Présences en réunion d'affaires."""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, desc, extract
from app.core.database import get_db
from app.core.roles import require_secretaire
from app.core.reunions import date_assemblee_affaires_du_mois, jour_reunion_attendu
from app.core.security import get_current_membre
from app.models.reunion import Reunion
from app.models.groupe import Groupe
from app.models.presence import Presence
from app.models.membre import Membre
from app.schemas.phase4 import (
PresencesBatch, PresenceOut, ReunionAffairesCreate, ReunionAffairesOut,
)
router = APIRouter(prefix="/presences", tags=["M2 — Présences affaires"])
@router.post("/reunion", response_model=ReunionAffairesOut)
async def creer_reunion_affaires(
req: ReunionAffairesCreate,
membre=Depends(require_secretaire),
db: AsyncSession = Depends(get_db),
):
"""Créer une réunion d'affaires (point de départ pour présences et PV)."""
groupe = await db.get(Groupe, membre.groupe_id)
# ── Validation : réunion d'affaires prévue dans les paramètres du groupe ──
dt = req.date_reunion
if groupe.jour_reunion:
jour_attendu = jour_reunion_attendu(groupe)
if jour_attendu is not None:
ordre = groupe.assemblee_affaires_ordre or "premiere"
date_attendue = date_assemblee_affaires_du_mois(dt.year, dt.month, jour_attendu, ordre)
if dt.date() != date_attendue:
raise HTTPException(
status_code=400,
detail=f"La réunion d'affaires doit avoir lieu à la date prévue ({date_attendue.isoformat()})",
)
# Une seule réunion d'affaires par mois
result = await db.execute(
select(Reunion).where(
Reunion.groupe_id == membre.groupe_id,
Reunion.type == "affaires",
extract("year", Reunion.date_reunion) == dt.year,
extract("month", Reunion.date_reunion) == dt.month,
)
)
if result.scalars().first():
raise HTTPException(
status_code=400,
detail=f"Il y a déjà une réunion d'affaires pour {dt.strftime('%B %Y')}",
)
reunion = Reunion(
groupe_id=membre.groupe_id,
type="affaires",
date_reunion=req.date_reunion,
note=req.note,
)
db.add(reunion)
await db.flush()
return ReunionAffairesOut(id=reunion.id, date_reunion=reunion.date_reunion, note=reunion.note)
@router.get("/reunions", response_model=list[ReunionAffairesOut])
async def liste_reunions_affaires(
limite: int = 12,
membre=Depends(get_current_membre),
db: AsyncSession = Depends(get_db),
):
"""Lister les réunions d'affaires récentes avec leurs présences."""
result = await db.execute(
select(Reunion).where(
Reunion.groupe_id == membre.groupe_id,
Reunion.type == "affaires",
).order_by(desc(Reunion.date_reunion)).limit(limite)
)
reunions = result.scalars().all()
out = []
for r in reunions:
pres_result = await db.execute(
select(Presence).where(Presence.reunion_id == r.id)
)
presences = pres_result.scalars().all()
pres_out = []
for p in presences:
mbr = await db.get(Membre, p.membre_id)
pres_out.append(PresenceOut(
membre_id=p.membre_id,
membre_prenom=mbr.prenom if mbr else "?",
present=p.present,
))
out.append(ReunionAffairesOut(
id=r.id, date_reunion=r.date_reunion, note=r.note, presences=pres_out,
))
return out
@router.post("/", response_model=list[PresenceOut])
async def enregistrer_presences(
req: PresencesBatch,
membre=Depends(require_secretaire),
db: AsyncSession = Depends(get_db),
):
"""M2 — Enregistrer les présences pour une réunion d'affaires."""
# Vérifier que la réunion existe et est de type affaires
result = await db.execute(
select(Reunion).where(
Reunion.id == req.reunion_id,
Reunion.groupe_id == membre.groupe_id,
)
)
reunion = result.scalar_one_or_none()
if not reunion:
raise HTTPException(status_code=404, detail="Réunion introuvable")
# Supprimer les présences existantes pour cette réunion (pour pouvoir re-saisir)
existing = await db.execute(
select(Presence).where(Presence.reunion_id == req.reunion_id)
)
for p in existing.scalars().all():
await db.delete(p)
# Insérer les nouvelles
out = []
for item in req.presences:
pres = Presence(
reunion_id=req.reunion_id,
membre_id=item.membre_id,
present=item.present,
)
db.add(pres)
mbr = await db.get(Membre, item.membre_id)
out.append(PresenceOut(
membre_id=item.membre_id,
membre_prenom=mbr.prenom if mbr else "?",
present=item.present,
))
await db.flush()
return out