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

157 lines
4.9 KiB
Python

"""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)