Files
AdamThomasandClaude Opus 5.5 d0fa1e109c
ci-cd / build-backend (push) Successful in 38s
ci-cd / build-frontend (push) Successful in 20s
ci-cd / deploy (push) Successful in 13s
Logs de diagnostic et rapprochement SumUp ↔ bénévole
- Une ligne de log par requête (route modèle, statut, durée, code d'erreur,
  compte), identifiant X-Request-ID repris dans chaque log et affiché à
  l'utilisateur sous une erreur, exceptions non gérées tracées (500 JSON)
- Journal d'accès d'uvicorn coupé : il exposait le jeton du formulaire public
- Logs métier : paiement SumUp, connexion, import, plannings, solveur
- Nom du bénévole dans la description du checkout SumUp
- Code et identifiant de transaction SumUp enregistrés au paiement
  (migration 0023), affichés sur la fiche et dans l'export Excel

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:54:35 +02:00

55 lines
1.7 KiB
Python

"""Suggestions du solveur (OR-Tools CP-SAT). Ne persiste rien : la
coordination affecte elle-même, dans l'écran habituel, en tenant compte des
bénévoles remontés en tête de liste."""
import logging
import time
import uuid
from fastapi import APIRouter, Depends
from sqlmodel import Session
from app.api.deps import get_edition
from app.api.schemas import SolverRunResult, SolverSuggestion
from app.auth.deps import require_staff
from app.db import get_session
from app.models import Account, Edition
from app.solver import build_solver_input, solve
logger = logging.getLogger("app.solver")
router = APIRouter(prefix="/editions/{edition_id}/solver", tags=["solver"])
@router.post("/suggestions", response_model=SolverRunResult)
def run_solver(
edition: Edition = Depends(get_edition),
_guard: Account = Depends(require_staff),
session: Session = Depends(get_session),
) -> SolverRunResult:
started = time.monotonic()
data = build_solver_input(session=session, edition=edition)
loaded = time.monotonic()
solution = solve(data)
logger.info(
"Solveur (édition %s) : %d créneaux, %d bénévoles, %d suggestions — "
"chargement %d ms, résolution %d ms",
edition.id,
len(data.shifts),
len(data.volunteers),
len(solution.suggestions),
(loaded - started) * 1000,
(time.monotonic() - loaded) * 1000,
)
return SolverRunResult(
suggestions=[
SolverSuggestion(
shift_id=uuid.UUID(s.shift_id),
volunteer_ids=[uuid.UUID(v) for v in s.volunteer_ids],
)
for s in solution.suggestions
],
shifts_considered=len(data.shifts),
volunteers_considered=len(data.volunteers),
)