103 lines
3.5 KiB
Python
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
|