groupe-meditation/backend/app/routers/reunions.py
2026-03-13 09:53:55 -04:00

113 lines
3.6 KiB
Python

"""Routes S4 — Rapport de réunion."""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, desc
from app.core.database import get_db
from app.core.security import get_current_membre
from app.models.reunion import Reunion
from app.models.membre import Membre
from app.models.affectation import Affectation
from app.models.poste import Poste
from app.schemas.phase1 import ReunionCreate, ReunionOut
router = APIRouter(prefix="/reunions", tags=["S4 — Rapport de réunion"])
async def require_animateur(membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db)):
"""Vérifie que le membre est animateur ou exécutif."""
result = await db.execute(
select(Affectation).join(Poste).where(
Affectation.membre_id == membre.id,
Affectation.statut == "actif",
(Poste.nom.ilike("%animateur%") | (Poste.categorie == "executif")),
)
)
if not result.scalars().first():
raise HTTPException(status_code=403, detail="Réservé à l'animateur ou à l'exécutif")
return membre
@router.post("/", response_model=ReunionOut)
async def creer_rapport_reunion(
req: ReunionCreate,
membre=Depends(require_animateur),
db: AsyncSession = Depends(get_db),
):
"""S4 — L'animateur note le thème et les annonces."""
reunion = Reunion(
groupe_id=membre.groupe_id,
type=req.type,
date_reunion=req.date_reunion,
animateur_id=membre.id,
theme=req.theme,
annonces=req.annonces,
note=req.note,
)
db.add(reunion)
await db.flush()
return ReunionOut(
id=reunion.id,
type=reunion.type,
date_reunion=reunion.date_reunion,
animateur_prenom=membre.prenom,
theme=reunion.theme,
annonces=reunion.annonces,
note=reunion.note,
cree_le=reunion.cree_le,
)
@router.get("/", response_model=list[ReunionOut])
async def liste_reunions(
limite: int = 20,
membre=Depends(get_current_membre),
db: AsyncSession = Depends(get_db),
):
"""Lister les réunions récentes du groupe."""
result = await db.execute(
select(Reunion)
.where(Reunion.groupe_id == membre.groupe_id)
.order_by(desc(Reunion.date_reunion))
.limit(limite)
)
reunions = result.scalars().all()
out = []
for r in reunions:
anim = await db.get(Membre, r.animateur_id) if r.animateur_id else None
out.append(ReunionOut(
id=r.id,
type=r.type,
date_reunion=r.date_reunion,
animateur_prenom=anim.prenom if anim else None,
theme=r.theme,
annonces=r.annonces,
note=r.note,
cree_le=r.cree_le,
))
return out
@router.get("/{reunion_id}", response_model=ReunionOut)
async def detail_reunion(
reunion_id: str,
membre=Depends(get_current_membre),
db: AsyncSession = Depends(get_db),
):
result = await db.execute(
select(Reunion).where(Reunion.id == 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")
anim = await db.get(Membre, reunion.animateur_id) if reunion.animateur_id else None
return ReunionOut(
id=reunion.id,
type=reunion.type,
date_reunion=reunion.date_reunion,
animateur_prenom=anim.prenom if anim else None,
theme=reunion.theme,
annonces=reunion.annonces,
note=reunion.note,
cree_le=reunion.cree_le,
)