groupe-meditation/backend/app/routers/config_repartition.py
2026-03-04 14:01:00 -05:00

103 lines
3.5 KiB
Python

"""Routes G8 — Configurer la répartition des contributions."""
from datetime import date
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 require_executif
from app.models.config_repartition import ConfigRepartition
from app.schemas.phase7 import (
ConfigRepartitionOut, ConfigRepartitionBatch,
DESTINATIONS, DESTINATIONS_LABELS,
)
router = APIRouter(prefix="/config-repartition", tags=["G8 — Config répartition"])
DEFAUT_REPARTITION = {
"district": 30.0,
"region": 30.0,
"bsg": 30.0,
"intergroupe": 10.0,
}
@router.get("/", response_model=list[ConfigRepartitionOut])
async def voir_repartition(
membre=Depends(require_executif),
db: AsyncSession = Depends(get_db),
):
"""G8 — Voir la répartition actuelle des contributions."""
result = await db.execute(
select(ConfigRepartition)
.where(ConfigRepartition.groupe_id == membre.groupe_id)
.order_by(desc(ConfigRepartition.actif_depuis))
)
configs = result.scalars().all()
# Garder la plus récente par destination
vu = {}
out = []
for c in configs:
if c.destination not in vu:
vu[c.destination] = True
out.append(ConfigRepartitionOut(
destination=c.destination,
destination_label=DESTINATIONS_LABELS.get(c.destination, c.destination),
pourcentage=float(c.pourcentage),
actif_depuis=c.actif_depuis,
))
# Compléter avec les défauts pour les destinations manquantes
for dest in DESTINATIONS:
if dest not in vu:
out.append(ConfigRepartitionOut(
destination=dest,
destination_label=DESTINATIONS_LABELS[dest],
pourcentage=DEFAUT_REPARTITION[dest],
actif_depuis=date.today(),
))
# Trier par destination
ordre = {d: i for i, d in enumerate(DESTINATIONS)}
out.sort(key=lambda x: ordre.get(x.destination, 99))
return out
@router.put("/", response_model=list[ConfigRepartitionOut])
async def modifier_repartition(
req: ConfigRepartitionBatch,
membre=Depends(require_executif),
db: AsyncSession = Depends(get_db),
):
"""G8 — Modifier la répartition (toutes les destinations d'un coup)."""
# Validation
total = sum(item.pourcentage for item in req.items)
if abs(total - 100.0) > 0.01:
raise HTTPException(status_code=400, detail=f"Le total doit être 100%. Actuellement: {total:.2f}%")
for item in req.items:
if item.destination not in DESTINATIONS:
raise HTTPException(status_code=400, detail=f"Destination invalide: {item.destination}")
if item.pourcentage < 0:
raise HTTPException(status_code=400, detail="Les pourcentages ne peuvent pas être négatifs")
aujourdhui = date.today()
out = []
for item in req.items:
config = ConfigRepartition(
groupe_id=membre.groupe_id,
destination=item.destination,
pourcentage=item.pourcentage,
actif_depuis=aujourdhui,
)
db.add(config)
await db.flush()
out.append(ConfigRepartitionOut(
destination=config.destination,
destination_label=DESTINATIONS_LABELS.get(config.destination, config.destination),
pourcentage=float(config.pourcentage),
actif_depuis=config.actif_depuis,
))
return out