"""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.roles import require_secretaire 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.schemas.phase4 import PvAdoption, PvCreate, PvOut, PvUpdate router = APIRouter(prefix="/pv", tags=["M1 — Procès-verbal"]) 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() 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) @router.patch("/{pv_id}/adopter", response_model=PvOut) async def adopter_pv( pv_id: str, req: PvAdoption, membre=Depends(require_secretaire), 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") if not req.proposeur.strip() or not req.secondeur.strip(): raise HTTPException(status_code=400, detail="Proposeur et secondeur requis") decisions = list(pv.decisions or []) decisions.append({ "sujet": "Adoption du procès-verbal précédent", "decision": "Le procès-verbal précédent est adopté.", "proposeur": req.proposeur.strip(), "secondeur": req.secondeur.strip(), "statut": "complete", }) pv.decisions = decisions pv.approuve = True await db.flush() return await _to_out(pv, db)