"""Routes M1 — Rédiger un PV de réunion d'affaires.""" 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.pv_reunion import PvReunion from app.models.reunion import Reunion from app.models.membre import Membre from app.models.decision import Decision from app.models.affectation import Affectation from app.models.poste import Poste from app.schemas.phase4 import PvCreate, PvOut, PvUpdate router = APIRouter(prefix="/pv", tags=["M1 — Procès-verbal"]) async def require_secretaire(membre=Depends(get_current_membre), db=Depends(get_db)): result = await db.execute( select(Affectation).join(Poste).where( Affectation.membre_id == membre.id, Affectation.statut == "actif", (Poste.nom.ilike("%secrétaire%") | (Poste.categorie == "executif")), ) ) if not result.scalar_one_or_none(): raise HTTPException(status_code=403, detail="Réservé au secrétaire ou à l'exécutif") return membre async def _to_out(pv: PvReunion, db: AsyncSession) -> PvOut: redacteur = await db.get(Membre, pv.redacteur_id) reunion = await db.get(Reunion, pv.reunion_id) if pv.reunion_id else None return PvOut( id=pv.id, reunion_id=pv.reunion_id, redacteur_prenom=redacteur.prenom if redacteur else "?", contenu=pv.contenu, decisions=pv.decisions, approuve=pv.approuve, cree_le=pv.cree_le, date_reunion=reunion.date_reunion if reunion else None, ) @router.get("/", response_model=list[PvOut]) async def liste_pv( limite: int = 12, membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """Lister les PV des réunions d'affaires.""" # Récupérer les PV via les réunions du groupe result = await db.execute( select(PvReunion) .join(Reunion, PvReunion.reunion_id == Reunion.id) .where(Reunion.groupe_id == membre.groupe_id) .order_by(desc(PvReunion.cree_le)) .limit(limite) ) return [await _to_out(pv, db) for pv in result.scalars().all()] @router.get("/{pv_id}", response_model=PvOut) async def detail_pv( pv_id: str, membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(PvReunion) .join(Reunion, PvReunion.reunion_id == Reunion.id) .where(PvReunion.id == pv_id, Reunion.groupe_id == membre.groupe_id) ) pv = result.scalar_one_or_none() if not pv: raise HTTPException(status_code=404, detail="PV introuvable") return await _to_out(pv, db) @router.post("/", response_model=PvOut) async def creer_pv( req: PvCreate, membre=Depends(require_secretaire), db: AsyncSession = Depends(get_db), ): """M1 — Rédiger un procès-verbal.""" # Vérifier la réunion 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") decisions_data = None if req.decisions: decisions_data = [d.model_dump() for d in req.decisions] pv = PvReunion( reunion_id=req.reunion_id, redacteur_id=membre.id, contenu=req.contenu.strip(), decisions=decisions_data, ) db.add(pv) await db.flush() # Créer les décisions dans la table decisions (pour C5) if req.decisions: for d in req.decisions: decision = Decision( groupe_id=membre.groupe_id, reunion_id=req.reunion_id, sujet=d.sujet, description=d.decision, statut=d.statut, proposeur=d.proposeur, secondeur=d.secondeur, date_decision=reunion.date_reunion.date() if reunion.date_reunion else None, cree_par=membre.id, ) db.add(decision) await db.flush() return await _to_out(pv, db) @router.patch("/{pv_id}", response_model=PvOut) async def modifier_pv( pv_id: str, req: PvUpdate, membre=Depends(require_secretaire), db: AsyncSession = Depends(get_db), ): """Modifier un PV existant.""" result = await db.execute( select(PvReunion) .join(Reunion, PvReunion.reunion_id == Reunion.id) .where(PvReunion.id == pv_id, Reunion.groupe_id == membre.groupe_id) ) pv = result.scalar_one_or_none() if not pv: raise HTTPException(status_code=404, detail="PV introuvable") if req.contenu is not None: pv.contenu = req.contenu.strip() if req.decisions is not None: pv.decisions = [d.model_dump() for d in req.decisions] if req.approuve is not None: pv.approuve = req.approuve await db.flush() return await _to_out(pv, db)