Rattrapage hebdomadaire : arrivées et retours de midi en secours des départs

Pour tenir les heures de la semaine, les préconisations n'ajustaient que
les départs du soir : un retard trop gros était déclaré rattrapage
impossible dès minuit atteint. Deux leviers s'enchaînent désormais :
avancer les arrivées du matin (jamais avant le début de la présence
matin, le retour de repos, ni l'heure actuelle), puis les retours de midi
(jamais avant la fin de la présence matin, ou la sortie réelle du matin).
Les entrées déjà pointées restent intactes ; l'aide des Réglages
documente la cascade.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
This commit is contained in:
Jacquin Antoine
2026-09-10 17:18:54 +02:00
parent d760842121
commit c0ed99de9d
3 changed files with 150 additions and 15 deletions

View File

@ -438,3 +438,70 @@ def test_compute_week_cible_en_cours_ne_recommande_jamais_un_depart_deja_passe(m
result = compute_week(pointages, [], HEURES_JOUR_MIN, plages)
jeudi = result["jours"][3]
assert jeudi["cible_aprem"] == "17:19"
# ── Rattrapage extrême : arrivées et retours de midi ──────────────────────────
def test_rattrapage_sature_departs_arrivees_puis_retour_de_midi(freeze_today):
"""Retard qui dépasse la capacité des départs du soir (minuit) : l'arrivée
du matin est avancée (jamais avant le début de « Présence matin »), puis le
retour de midi (jamais avant la fin de « Présence matin »). Arrivée visée
10:00, lun-jeu complets courts de 105 min/jour, vendredi congé, lundi vide :
420 min de retard — 281 dans le départ du soir (→ 23:59), 60 en arrivant à
09:00 (début Présence matin), 79 en reprenant à 12:11."""
plages = {"arrivee_visee": "10:00"}
pointages = [
_pointage("2026-07-13", "09:00", "12:00", "14:00", "17:03"),
_pointage("2026-07-14", "09:00", "12:00", "14:00", "17:03"),
_pointage("2026-07-15", "09:00", "12:00", "14:00", "17:03"),
_pointage("2026-07-16", "09:00", "12:00", "14:00", "17:03"),
_pointage("2026-07-17"),
_pointage("2026-07-20"),
]
conges = [{"date": "2026-07-17", "type": "jour"}]
result = compute_week(pointages, conges, HEURES_JOUR_MIN, plages)
lundi = result["jours"][5]
assert result["extra_min"] == 420
assert lundi["cible_matin_entree"] == "09:00" # arrivée avancée jusqu'au début de Présence matin
assert lundi["cible_matin"] == "12:00"
assert lundi["cible_aprem_entree"] == "12:11" # retour de midi avancé de 79 min
assert lundi["cible_aprem"] == "23:59" # départ saturé à minuit
def test_rattrapage_par_defaut_n_avance_pas_larrivee_avant_presence_matin(freeze_today):
"""Plages par défaut : l'arrivée visée (09:00) est déjà le début de
« Présence matin », rien à avancer — le levier restant est le retour de
midi, raccourci jusqu'à la fin de « Présence matin » (12:00)."""
pointages = [
_pointage("2026-07-13", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-14", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-15", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-16", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-17"),
_pointage("2026-07-20"),
]
conges = [{"date": "2026-07-17", "type": "jour"}]
result = compute_week(pointages, conges, HEURES_JOUR_MIN)
lundi = result["jours"][5]
assert lundi["cible_matin_entree"] == "09:00" # déjà au début de Présence matin
assert lundi["cible_matin"] == "12:00"
assert lundi["cible_aprem_entree"] == "12:00" # pause réduite jusqu'à la fin de Présence matin
assert lundi["cible_aprem"] == "23:59"
def test_jour_en_cours_ne_vise_pas_une_heure_passee(freeze_today):
"""Le jour même (gelé à 10:30), ni l'arrivée du matin ni le retour de midi
ne peuvent être proposés avant maintenant : l'arrivée reste à l'heure
visée, le retour de midi est borné par la fin de « Présence matin »."""
pointages = [
_pointage("2026-07-13", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-14", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-15", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-16", "09:00", "09:30", "14:00", "14:30"),
_pointage("2026-07-17"), # aujourd'hui 10:30, rien pointé
]
result = compute_week(pointages, [], HEURES_JOUR_MIN)
vendredi = result["jours"][4]
assert vendredi["cible_matin_entree"] == "09:00" # pas d'arrivée rétroactive
assert vendredi["cible_aprem_entree"] == "12:00" # borné par Présence matin, pas avant 10:30
assert vendredi["cible_aprem"] == "23:59"