2026-03-04 14:01:00 -05:00
|
|
|
"""Routes M6 — Commander des jetons."""
|
|
|
|
|
from datetime import date, timedelta
|
|
|
|
|
from fastapi import APIRouter, Depends
|
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
|
from sqlalchemy import select, func
|
|
|
|
|
|
|
|
|
|
from app.core.database import get_db
|
|
|
|
|
from app.core.security import get_current_membre
|
|
|
|
|
from app.models.jeton import Jeton
|
|
|
|
|
from app.models.affectation import Affectation
|
|
|
|
|
from app.models.poste import Poste
|
|
|
|
|
from app.schemas.phase5 import StockJetonsOut, TYPES_JETONS
|
|
|
|
|
from fastapi import HTTPException
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/commandes-jetons", tags=["M6 — Commander jetons"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def require_resp_jetons(membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db)):
|
|
|
|
|
"""Vérifie que le membre est responsable des jetons."""
|
|
|
|
|
result = await db.execute(
|
|
|
|
|
select(Affectation).join(Poste).where(
|
|
|
|
|
Affectation.membre_id == membre.id,
|
|
|
|
|
Affectation.statut == "actif",
|
|
|
|
|
Poste.nom.ilike("%jeton%"),
|
|
|
|
|
)
|
|
|
|
|
)
|
2026-03-13 09:53:55 -04:00
|
|
|
if not result.scalars().first():
|
2026-03-04 14:01:00 -05:00
|
|
|
raise HTTPException(status_code=403, detail="Réservé au responsable des jetons")
|
|
|
|
|
return membre
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/stock", response_model=list[StockJetonsOut])
|
|
|
|
|
async def etat_stock_jetons(
|
|
|
|
|
membre=Depends(require_resp_jetons),
|
|
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
|
|
):
|
|
|
|
|
"""M6 — État du stock de jetons (basé sur l'utilisation du dernier mois)."""
|
|
|
|
|
il_y_a_30_jours = date.today() - timedelta(days=30)
|
|
|
|
|
|
|
|
|
|
# Compter les jetons remis par type dans les 30 derniers jours
|
|
|
|
|
result = await db.execute(
|
|
|
|
|
select(Jeton.type_jeton, func.count(Jeton.id))
|
|
|
|
|
.where(
|
|
|
|
|
Jeton.groupe_id == membre.groupe_id,
|
|
|
|
|
Jeton.date_remise >= il_y_a_30_jours,
|
|
|
|
|
)
|
|
|
|
|
.group_by(Jeton.type_jeton)
|
|
|
|
|
)
|
|
|
|
|
usage = {row[0]: row[1] for row in result.all()}
|
|
|
|
|
|
|
|
|
|
stock = []
|
|
|
|
|
for t in TYPES_JETONS:
|
|
|
|
|
remis = usage.get(t["value"], 0)
|
|
|
|
|
# Suggestion simple : si plus de 2 remis dans le mois, suggérer commande
|
|
|
|
|
suggestion = "Bas — commander" if remis >= 2 else "OK"
|
|
|
|
|
# Le jeton de désir est toujours à surveiller (remis chaque semaine)
|
|
|
|
|
if t["value"] == "desir" and remis >= 4:
|
|
|
|
|
suggestion = "Bas — commander"
|
|
|
|
|
|
|
|
|
|
stock.append(StockJetonsOut(
|
|
|
|
|
type_jeton=t["value"],
|
|
|
|
|
label=f"{t['emoji']} {t['label']}",
|
|
|
|
|
remis_dernier_mois=remis,
|
|
|
|
|
stock_suggestion=suggestion,
|
|
|
|
|
))
|
|
|
|
|
return stock
|