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