"""Routes G5 — Planifier les rotations hebdomadaires.""" from datetime import date, timedelta from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, delete from app.core.database import get_db from app.core.security import require_executif, get_current_membre from app.models.rotation import Rotation from app.models.poste import Poste from app.models.membre import Membre from app.schemas.phase3 import RotationCreate, RotationOut router = APIRouter(prefix="/rotations", tags=["G5 — Rotations"]) async def _to_out(r: Rotation, db: AsyncSession) -> RotationOut: poste = await db.get(Poste, r.poste_id) mbr = await db.get(Membre, r.membre_id) if poste and poste.groupe_id != r.groupe_id: poste = None if mbr and mbr.groupe_id != r.groupe_id: mbr = None return RotationOut( id=r.id, date_reunion=r.date_reunion, poste_nom=poste.nom if poste else "?", membre_prenom=mbr.prenom if mbr else "?", note=r.note, cree_le=r.cree_le, ) @router.get("/", response_model=list[RotationOut]) async def liste_rotations( semaines: int = 4, membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """Rotations des prochaines semaines.""" aujourdhui = date.today() fin = aujourdhui + timedelta(weeks=semaines) result = await db.execute( select(Rotation).where( Rotation.groupe_id == membre.groupe_id, Rotation.date_reunion >= aujourdhui, Rotation.date_reunion <= fin, ).order_by(Rotation.date_reunion, Rotation.poste_id) ) return [await _to_out(r, db) for r in result.scalars().all()] @router.get("/historique", response_model=list[RotationOut]) async def historique_rotations( semaines: int = 4, membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """Rotations passées.""" aujourdhui = date.today() debut = aujourdhui - timedelta(weeks=semaines) result = await db.execute( select(Rotation).where( Rotation.groupe_id == membre.groupe_id, Rotation.date_reunion >= debut, Rotation.date_reunion < aujourdhui, ).order_by(Rotation.date_reunion.desc()) ) return [await _to_out(r, db) for r in result.scalars().all()] @router.post("/", response_model=RotationOut) async def creer_rotation( req: RotationCreate, executif=Depends(require_executif), db: AsyncSession = Depends(get_db), ): """G5 — Assigner un serviteur pour une date de réunion.""" poste = await db.get(Poste, req.poste_id) mbr = await db.get(Membre, req.membre_id) if not poste or poste.groupe_id != executif.groupe_id or not poste.actif: raise HTTPException(status_code=404, detail="Poste introuvable ou aboli") if not mbr or mbr.groupe_id != executif.groupe_id or not mbr.actif: raise HTTPException(status_code=404, detail="Membre introuvable ou inactif") rotation = Rotation( groupe_id=executif.groupe_id, date_reunion=req.date_reunion, poste_id=req.poste_id, membre_id=req.membre_id, note=req.note, cree_par=executif.id, ) db.add(rotation) await db.flush() return await _to_out(rotation, db) @router.post("/batch", response_model=list[RotationOut]) async def creer_rotations_batch( rotations: list[RotationCreate], executif=Depends(require_executif), db: AsyncSession = Depends(get_db), ): """G5 — Assigner plusieurs serviteurs d'un coup pour une semaine.""" created = [] for req in rotations: poste = await db.get(Poste, req.poste_id) mbr = await db.get(Membre, req.membre_id) if not poste or poste.groupe_id != executif.groupe_id or not poste.actif: raise HTTPException(status_code=404, detail="Poste introuvable ou aboli") if not mbr or mbr.groupe_id != executif.groupe_id or not mbr.actif: raise HTTPException(status_code=404, detail="Membre introuvable ou inactif") rotation = Rotation( groupe_id=executif.groupe_id, date_reunion=req.date_reunion, poste_id=req.poste_id, membre_id=req.membre_id, note=req.note, cree_par=executif.id, ) db.add(rotation) await db.flush() created.append(await _to_out(rotation, db)) return created @router.delete("/{rotation_id}") async def supprimer_rotation( rotation_id: str, executif=Depends(require_executif), db: AsyncSession = Depends(get_db), ): """Supprimer une rotation planifiée.""" result = await db.execute( select(Rotation).where(Rotation.id == rotation_id, Rotation.groupe_id == executif.groupe_id) ) rotation = result.scalar_one_or_none() if not rotation: raise HTTPException(status_code=404, detail="Rotation introuvable") await db.delete(rotation) return {"message": "Rotation supprimée"}