groupe-meditation/backend/app/routers/decisions.py

111 lines
3.7 KiB
Python
Raw Normal View History

2026-03-04 14:01:00 -05:00
"""Routes C5 — Décisions en cours."""
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, require_executif
from app.models.decision import Decision
from app.models.membre import Membre
from app.schemas.phase2 import DecisionCreate, DecisionOut, DecisionUpdate
router = APIRouter(prefix="/decisions", tags=["C5 — Décisions en cours"])
async def _to_out(d: Decision, db: AsyncSession) -> DecisionOut:
resp = await db.get(Membre, d.responsable_id) if d.responsable_id else None
return DecisionOut(
id=d.id,
sujet=d.sujet,
description=d.description,
statut=d.statut,
responsable_prenom=resp.prenom if resp else None,
proposeur=d.proposeur,
secondeur=d.secondeur,
date_decision=d.date_decision,
date_completion=d.date_completion,
cree_le=d.cree_le,
)
@router.get("/", response_model=list[DecisionOut])
async def liste_decisions(
statut: str | None = None,
limite: int = 50,
membre=Depends(get_current_membre),
db: AsyncSession = Depends(get_db),
):
"""C5 — Lister les décisions du groupe avec filtre optionnel par statut."""
query = select(Decision).where(Decision.groupe_id == membre.groupe_id)
if statut:
query = query.where(Decision.statut == statut)
query = query.order_by(desc(Decision.date_decision)).limit(limite)
result = await db.execute(query)
return [await _to_out(d, db) for d in result.scalars().all()]
@router.get("/compteur")
async def compteur_decisions(
membre=Depends(get_current_membre),
db: AsyncSession = Depends(get_db),
):
"""Nombre de décisions ouvertes (pour le badge sur la tuile)."""
result = await db.execute(
select(Decision).where(
Decision.groupe_id == membre.groupe_id,
Decision.statut.in_(["en_attente", "en_cours"]),
)
)
return {"ouvertes": len(result.scalars().all())}
@router.post("/", response_model=DecisionOut)
async def creer_decision(
req: DecisionCreate,
executif=Depends(require_executif),
db: AsyncSession = Depends(get_db),
):
"""Créer une décision (exécutif — typiquement via le PV)."""
decision = Decision(
groupe_id=executif.groupe_id,
reunion_id=req.reunion_id,
sujet=req.sujet.strip(),
description=req.description,
statut=req.statut,
responsable_id=req.responsable_id,
proposeur=req.proposeur,
secondeur=req.secondeur,
date_decision=req.date_decision,
cree_par=executif.id,
)
db.add(decision)
await db.flush()
return await _to_out(decision, db)
@router.patch("/{decision_id}", response_model=DecisionOut)
async def modifier_decision(
decision_id: str,
req: DecisionUpdate,
executif=Depends(require_executif),
db: AsyncSession = Depends(get_db),
):
"""Modifier le statut d'une décision (exécutif)."""
result = await db.execute(
select(Decision).where(Decision.id == decision_id, Decision.groupe_id == executif.groupe_id)
)
decision = result.scalar_one_or_none()
if not decision:
raise HTTPException(status_code=404, detail="Décision introuvable")
if req.statut is not None:
decision.statut = req.statut
if req.description is not None:
decision.description = req.description
if req.responsable_id is not None:
decision.responsable_id = req.responsable_id
if req.date_completion is not None:
decision.date_completion = req.date_completion
await db.flush()
return await _to_out(decision, db)