Files
benevoles/backend/pyproject.toml
T
AdamThomasandClaude Sonnet 5 803db5e9a9 Solveur de suggestions (OR-Tools CP-SAT) — ne place jamais personne
Nouveau module `backend/app/solver/` (mêmes conventions que
`validation/` : models purs, engine pur testé, loader seul lien avec la
base). Pour chaque créneau encore sous son effectif idéal, calcule une
liste ordonnée de bénévoles candidats — c'est la coordination qui
affecte, dans l'écran habituel ; le solveur fait juste remonter ces
candidats en tête de liste (voir le câblage frontend à suivre).

- Seule contrainte dure : aucun chevauchement de créneaux pour un même
  bénévole (règle SHIFT_OVERLAP), à la fois contre l'existant et entre
  deux suggestions du même calcul. L'effectif idéal est un plafond dur.
- Tout le reste est un terme de l'objectif, pas un blocage : priorité
  forte aux créneaux sous l'effectif minimal, bonus vœu de poste, malus
  disponibilité manquante (réutilise `validation.engine.uncovered_minutes`),
  cumul de 8 h et repos (contre les affectations déjà décidées),
  répartition de la charge.
- `POST /editions/{id}/solver/suggestions` (COORDINATION/référent) :
  recalcule à la demande, ne persiste jamais d'affectation.

Dépendance `ortools`. 18 nouveaux tests (moteur + API), 172 tests au
vert, `ruff` et `alembic check` verts. Testé sur le jeu de démo (120
bénévoles, 100 créneaux) : ~0,3 s.

CLAUDE.md : nouvelle section 4 (solveur), renumérotation 5-10,
compétences retirées de « hors périmètre », journal étape 15.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
2026-09-11 08:16:17 +02:00

53 lines
993 B
TOML

[project]
name = "benevoles-backend"
version = "0.1.0"
description = "API de gestion des bénévoles d'un festival"
requires-python = ">=3.12,<3.13"
dependencies = [
"fastapi>=0.115",
"uvicorn[standard]>=0.32",
"sqlmodel>=0.0.22",
"alembic>=1.14",
"psycopg[binary]>=3.2",
"pydantic-settings>=2.6",
"python-multipart>=0.0.12",
"openpyxl>=3.1",
"pyjwt>=2.9",
"bcrypt>=4.1",
"ortools>=9.11",
]
[dependency-groups]
dev = [
"pytest>=8.3",
"pytest-cov>=6.0",
"httpx>=0.27",
"ruff>=0.8",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["app"]
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]
[tool.ruff.lint.flake8-bugbear]
extend-immutable-calls = [
"fastapi.Depends",
"fastapi.File",
"fastapi.Form",
"fastapi.Query",
]
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-ra"