Pointage enregistré et statistiques de présence
Étape 58 : le présent / absent du référent est enregistré sur
l'affectation (Assignment.attendance + heure, migration 0030,
PUT .../assignments/{id}/attendance) au lieu de disparaître au
rechargement.
Étape 59 : section « Présence » de l'écran Statistiques — créneaux en
cours et créneaux terminés, par poste, rafraîchie toutes les 30 s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a37f6c2c41
commit
c57c70569c
@@ -187,3 +187,49 @@ def test_filled_slots_never_count_overstaffing(client, edition, session):
|
||||
assert position["assigned"] == 3
|
||||
assert position["filled"] == 2
|
||||
assert position["ideal_slots"] == 4
|
||||
|
||||
|
||||
def test_attendance_splits_past_and_live_shifts_per_position(
|
||||
client, edition, session, monkeypatch
|
||||
):
|
||||
import app.api.stats as stats_api
|
||||
from app.models import AttendanceStatus
|
||||
|
||||
# Maintenant : le 10 à 20:00 — 14h–18h terminé, 18h–22h en cours,
|
||||
# 22h–02h à venir (ignoré).
|
||||
monkeypatch.setattr(stats_api, "local_now", lambda: dt_at(10, 20))
|
||||
bar = make_position(session, edition, name="Bar")
|
||||
parking = make_position(session, edition, name="Parking")
|
||||
past = make_shift(session, edition, bar, start=dt_at(10, 14), end=dt_at(10, 18))
|
||||
live = make_shift(session, edition, bar, start=dt_at(10, 18), end=dt_at(10, 22))
|
||||
later = make_shift(session, edition, parking, start=dt_at(10, 22), end=dt_at(11, 2))
|
||||
|
||||
def assign(shift, name, attendance=None):
|
||||
volunteer = make_volunteer(session, edition, first_name=name)
|
||||
session.add(
|
||||
Assignment(
|
||||
edition_id=edition.id,
|
||||
volunteer_id=volunteer.id,
|
||||
shift_id=shift.id,
|
||||
attendance=attendance,
|
||||
)
|
||||
)
|
||||
|
||||
assign(past, "A", AttendanceStatus.PRESENT)
|
||||
assign(past, "B", AttendanceStatus.ABSENT)
|
||||
assign(past, "C")
|
||||
assign(live, "D", AttendanceStatus.PRESENT)
|
||||
assign(live, "E")
|
||||
assign(later, "F", AttendanceStatus.PRESENT)
|
||||
session.commit()
|
||||
|
||||
att = client.get(_url(edition)).json()["attendance"]
|
||||
assert att["past"] == {"assigned": 3, "present": 1, "absent": 1, "unmarked": 1}
|
||||
assert att["live"] == {"assigned": 2, "present": 1, "absent": 0, "unmarked": 1}
|
||||
assert att["live_shifts"] == 1
|
||||
# Parking n'a encore aucun créneau commencé : absent du détail.
|
||||
(row,) = att["by_position"]
|
||||
assert row["name"] == "Bar"
|
||||
assert row["past"]["assigned"] == 3
|
||||
assert row["live"]["present"] == 1
|
||||
assert row["live_shifts"] == 1
|
||||
|
||||
Reference in New Issue
Block a user