Corrige le double comptage des demi-journées en cours et plafonne les cibles matin
Trois corrections sur les préconisations : - Une demi-journée en cours (entrée pointée sans sortie, aujourd'hui) était comptée deux fois — temps écoulé dans le travaillé ET nominal complet comme capacité restante — ce qui faisait disparaître le rattrapage pendant la journée et produisait des cibles en manque du temps déjà écoulé. Le temps écoulé est réintégré au besoin planifié. - La cible matin est plafonnée à la reprise de l'après-midi ; un créneau saturé reporte son surplus sur les créneaux encore ouverts (waterfill) au lieu d'afficher une sortie matin absurde. - Une semaine entièrement pointée mais en déficit affiche désormais un bandeau "Semaine terminée avec -X de manque" au lieu de rien.
This commit is contained in:
@ -174,6 +174,75 @@ def test_compute_week_jour_courant_non_entame_rythme_normal_suffit(freeze_today)
|
||||
assert vendredi["cible_aprem"] is None
|
||||
|
||||
|
||||
def test_compute_week_demi_journee_en_cours_pas_de_double_comptage(freeze_today):
|
||||
"""Régression : une demi-journée en cours (entrée pointée sans sortie, aujourd'hui)
|
||||
était comptée deux fois — son temps écoulé dans le travaillé ET son nominal complet
|
||||
comme capacité restante — ce qui masquait le rattrapage pendant la journée.
|
||||
|
||||
Lundi en retard de 60 min, mardi-jeudi complets, vendredi (aujourd'hui, gelé à
|
||||
10:30) matin en cours depuis 09:00. Les 60 min doivent être réparties : le matin
|
||||
est plafonné par la pause déjeuner (max +36), donc 30/30 passe sans saturation.
|
||||
"""
|
||||
pointages = [
|
||||
_pointage("2026-07-13", "09:00", "12:24", "13:30", "16:54"), # -60 min
|
||||
_pointage("2026-07-14", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-15", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-16", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-17", matin_entree="09:00"), # en cours, 90 min écoulées
|
||||
]
|
||||
result = compute_week(pointages, [], HEURES_JOUR_MIN)
|
||||
vendredi = result["jours"][4]
|
||||
assert result["extra_min"] == 60
|
||||
# matin : 09:00 + 234 nominal + 30 = 13:24 ; aprem : 13:30 + 234 + 30 = 17:54
|
||||
assert vendredi["cible_matin"] == "13:24"
|
||||
assert vendredi["cible_aprem"] == "17:54"
|
||||
|
||||
|
||||
def test_compute_week_cible_matin_plafonnee_a_la_pause_dejeuner(freeze_today):
|
||||
"""La cible matin ne dépasse jamais la reprise de l'après-midi : un créneau
|
||||
saturé reçoit sa capacité max, le surplus reste non alloué (pas de cible absurde).
|
||||
|
||||
Vendredi en congé après-midi : seule sa matinée reste (nominal 234, capacité
|
||||
09:00→13:30 = 270, soit +36 max). Avec 120 min de retard, la cible est plafonnée
|
||||
à 13:30 au lieu d'un impossible 14:54.
|
||||
"""
|
||||
conges = [{"date": "2026-07-17", "type": "aprem"}]
|
||||
pointages = [
|
||||
_pointage("2026-07-13", "09:00", "12:24", "13:30", "15:54"), # -120 min
|
||||
_pointage("2026-07-14", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-15", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-16", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-17"),
|
||||
]
|
||||
result = compute_week(pointages, conges, HEURES_JOUR_MIN)
|
||||
vendredi = result["jours"][4]
|
||||
assert result["extra_min"] == 120
|
||||
assert vendredi["cible_matin"] == "13:30"
|
||||
assert vendredi["cible_aprem"] is None # congé
|
||||
|
||||
|
||||
def test_compute_week_surplus_creneau_sature_reporte_sur_les_autres(freeze_today):
|
||||
"""Quand un créneau matin sature (plafond pause déjeuner), le surplus doit se
|
||||
reporter sur les créneaux encore ouverts au lieu d'être perdu.
|
||||
|
||||
80 min de retard sur 2 demi-journées de vendredi : réparti 40/40, mais le matin
|
||||
plafonne à +36 — les 4 min restantes basculent sur l'après-midi (+44).
|
||||
"""
|
||||
pointages = [
|
||||
_pointage("2026-07-13", "09:00", "12:24", "13:30", "16:34"), # -80 min
|
||||
_pointage("2026-07-14", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-15", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-16", "09:00", "12:24", "13:30", "17:54"),
|
||||
_pointage("2026-07-17"),
|
||||
]
|
||||
result = compute_week(pointages, [], HEURES_JOUR_MIN)
|
||||
vendredi = result["jours"][4]
|
||||
assert result["extra_min"] == 80
|
||||
# matin saturé : 09:00 + 270 = 13:30 ; aprem : 13:30 + 234 + 44 = 18:08
|
||||
assert vendredi["cible_matin"] == "13:30"
|
||||
assert vendredi["cible_aprem"] == "18:08"
|
||||
|
||||
|
||||
def test_compute_week_plages_personnalisees(freeze_today):
|
||||
"""Les seuils de plage sont bien paramétrables, pas juste figés sur les défauts."""
|
||||
plages = {
|
||||
|
||||
Reference in New Issue
Block a user