Retrait des disponibilités et des limites de temps dans la journée
ci-cd / build-backend (push) Successful in 31s
ci-cd / build-frontend (push) Successful in 19s
ci-cd / deploy (push) Successful in 12s

Disponibilités déclarées supprimées (table `availability`, migration 0022,
API, éditeur de la fiche bénévole, badge de couverture du panneau
d'affectation, colonnes des statistiques) ainsi que les règles
OUTSIDE_AVAILABILITY, DAILY_HOURS_EXCEEDED et INSUFFICIENT_REST, les malus
de disponibilité et de repos du solveur et le filtre « Surchargés » de la
vue bénévoles. Seul le chevauchement reste contrôlé. La case « je suis
disponible » du formulaire public est conservée.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-05 21:29:58 +02:00
co-authored by Claude Opus 5.5
parent f671bb85bf
commit d722a81a87
40 changed files with 213 additions and 1845 deletions
+20 -24
View File
@@ -1,7 +1,6 @@
import datetime as dt
from tests.factories import (
declare_available_all_day,
dt_at,
make_position,
make_shift,
@@ -13,16 +12,12 @@ def _url(edition, suffix=""):
return f"/editions/{edition.id}/assignments{suffix}"
def _setup(session, edition, *, available=True):
def _setup(session, edition):
position = make_position(session, edition)
shift = make_shift(
session, edition, position, start=dt_at(10, 14), end=dt_at(10, 18)
)
volunteer = make_volunteer(session, edition, email="v@ex.fr")
if available:
declare_available_all_day(
session, edition, volunteer, dt.date(2026, 7, 10)
)
return volunteer, shift
@@ -39,16 +34,21 @@ def test_create_assignment_clean(client, edition, session, day_parts):
assert body["assignment"]["locked"] is False
def test_create_assignment_returns_warnings(client, edition, session, day_parts):
# Bénévole non déclaré disponible sur le créneau.
volunteer, shift = _setup(session, edition, available=False)
resp = client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
def test_long_day_without_rest_raises_no_warning(client, edition, session, day_parts):
# Plus de limite d'heures par jour ni de repos minimal : 14h–18h puis
# 18h–04h (14 h d'affilée) passe sans avertissement.
volunteer, shift = _setup(session, edition)
position = make_position(session, edition, name="Bar")
following = make_shift(
session, edition, position, start=dt_at(10, 18), end=dt_at(11, 4)
)
assert resp.status_code == 201
codes = {w["code"] for w in resp.json()["warnings"]}
assert "OUTSIDE_AVAILABILITY" in codes
for s in (shift, following):
resp = client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(s.id)},
)
assert resp.status_code == 201
assert resp.json()["warnings"] == []
def test_create_assignment_blocked_by_overlap(client, edition, session, day_parts):
@@ -110,7 +110,7 @@ def test_assignment_wrong_edition_is_422(client, edition, session, day_parts):
def test_validate_endpoint_does_not_persist(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition, available=False)
volunteer, shift = _setup(session, edition)
resp = client.post(
_url(edition, "/validate"),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
@@ -118,14 +118,12 @@ def test_validate_endpoint_does_not_persist(client, edition, session, day_parts)
assert resp.status_code == 200
body = resp.json()
assert body["blocking"] is False
assert any(v["code"] == "OUTSIDE_AVAILABILITY" for v in body["violations"])
assert body["violations"] == []
assert client.get(_url(edition)).json() == []
def test_patch_locked_keeps_assignment_and_returns_warnings(
client, edition, session, day_parts
):
volunteer, shift = _setup(session, edition, available=False)
def test_patch_locked_keeps_assignment(client, edition, session, day_parts):
volunteer, shift = _setup(session, edition)
aid = client.post(
_url(edition),
json={"volunteer_id": str(volunteer.id), "shift_id": str(shift.id)},
@@ -134,9 +132,7 @@ def test_patch_locked_keeps_assignment_and_returns_warnings(
resp = client.patch(_url(edition, f"/{aid}"), json={"locked": True})
assert resp.status_code == 200
assert resp.json()["assignment"]["locked"] is True
assert any(
w["code"] == "OUTSIDE_AVAILABILITY" for w in resp.json()["warnings"]
)
assert resp.json()["warnings"] == []
def test_delete_assignment(client, edition, session, day_parts):