Cibles : reprise ancrée au présent et rafraîchissement en direct

L'heure de reprise de pause n'est qu'indicative : le jour même, une
fois l'heure désirée passée, la cible d'un après-midi non commencé
ancre la reprise à maintenant et la sortie s'ajuste au reste à faire —
suivre les cibles mène au solde 0 exact, et aucune cible ne recommande
de reprendre dans le passé.

La page semaine rafraîchit cibles, panneau Aujourd'hui et compteurs
toutes les 30 s, et immédiatement au retour sur l'onglet (les
minuteurs des navigateurs sont gelés en arrière-plan, l'affichage ne
peit plus rester périmé).

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
This commit is contained in:
Jacquin Antoine
2026-09-11 14:29:50 +02:00
parent 45b450c1ca
commit e797098e79
5 changed files with 99 additions and 15 deletions

View File

@ -6,7 +6,7 @@ DEFAULT_PLAGES = {
"matin_fin": "12:00", # présence obligatoire jusqu'à cette heure le matin
"aprem_debut": "14:00", # présence obligatoire à partir de cette heure l'après-midi
"aprem_fin": "17:00", # présence obligatoire jusqu'à cette heure l'après-midi (plancher de sortie)
"pause_dejeuner_fin": "13:30", # reprise par défaut projetée tant que l'entrée aprem n'est pas saisie
"pause_dejeuner_fin": "13:30", # reprise désirée (indicative) : projetée par défaut tant que l'entrée aprem n'est pas saisie, ancrée à maintenant le jour même une fois passée
"arrivee_visee": "", # arrivée du matin visée pour les préconisations (vide = matin_debut)
"depart_vise": "", # départ du soir visé, plafond souple des cibles aprem (vide = aucun)
"astreinte_forfait": "", # durée ajoutée au temps travaillé de chaque jour d'astreinte déclaré (HH:MM, vide = aucune)
@ -846,7 +846,17 @@ def compute_week(pointages: list[dict], conges: list[dict], heures_jour_min: int
slots.append({"jour": jour, "half": "matin", "nominal": nominal, "debut": debut,
"sature": sature})
if not aprem_done:
debut = hhmm_to_minutes(jour["aprem_entree"]) if jour.get("aprem_entree") else max(pause_dejeuner_fin_min, jour["retour_min"] or 0)
if jour.get("aprem_entree"):
debut = hhmm_to_minutes(jour["aprem_entree"])
else:
# La reprise de pause n'est qu'une heure désirée (indicative) :
# projection par défaut, bornée par l'heure de retour après repos.
# Le jour même, une fois l'heure passée, la reprise visée est
# ancrée à maintenant — on ne recommande pas de reprendre dans
# le passé (l'entrée restera saisissable après coup à la main).
debut = max(pause_dejeuner_fin_min, jour["retour_min"] or 0)
if jour["date"] == today:
debut = max(debut, now_min)
cap = max(0, 23 * 60 + 59 - debut)
cap_pref = min(cap, max(0, depart_vise_min - debut)) if depart_vise_min else cap
# floor_room = marge disponible pour avancer le départ en cas d'avance,