Forfait d'astreinte : bonifié comme réalisé en journée du jour AS

Le forfait était suivi brut, sans bonification. Considéré réalisé en
journée du jour où il est attribué, il reçoit désormais le facteur
journée correspondant : ×1 en semaine, ×1,5 le samedi, ×2 le dimanche
ou un jour férié (suit les règles de ratios configurées). Toujours hors
heures travaillées ; affiché pondéré sur la ligne du jour, dans les
totaux du récapitulatif et expliqué dans Réglages.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
This commit is contained in:
Jacquin Antoine
2026-09-10 17:05:05 +02:00
parent f50d1ef7fc
commit d760842121
7 changed files with 125 additions and 16 deletions

View File

@ -197,6 +197,32 @@ def _regles_astreinte(facteurs: list[dict] | None) -> list[dict]:
]
MIDI_MIN = 12 * 60 # minute représentative de la journée (le forfait AS y est réputé réalisé)
def regle_journee_astreinte(date_str: str, facteurs: list[dict] | None = None,
feries_declares: list[str] | set[str] | None = None) -> dict | None:
"""Règle de bonification des heures de journée du jour donné : la première
règle dont le type de jour et la fenêtre horaire couvrent midi, minute
représentative de la journée. Le forfait d'astreinte est considéré réalisé
en journée du jour où il est attribué : c'est ce facteur qui le pondère
(semaine ×1, samedi ×1,5, dimanche/férié ×2 avec les règles par défaut).
None si aucune règle ne couvre midi ce jour-là (forfait non bonifié)."""
regles = _regles_astreinte(facteurs)
jour0 = datetime.strptime(date_str, "%Y-%m-%d").date()
feries = _jours_feries(jour0.year) | _jours_feries(jour0.year + 1)
for s in (feries_declares or []):
try:
feries.add(datetime.strptime(s, "%Y-%m-%d").date())
except (TypeError, ValueError):
continue
cat = _categorie_jour(jour0, feries)
r = next((r for r in regles if cat in r["jours"] and _dans_fenetre(MIDI_MIN, r["debut"], r["fin"])), None)
if r is None:
return None
return {"nom": r["nom"], "facteur": r["facteur"], "facteur_txt": _facteur_txt(r["facteur"])}
def decompte_astreinte(date_str: str, events: list[dict], facteurs: list[dict] | None = None,
fenetre: tuple[int, int] | None = None,
feries_declares: list[str] | set[str] | None = None) -> dict:
@ -586,6 +612,7 @@ def compute_week(pointages: list[dict], conges: list[dict], heures_jour_min: int
as_total_min = 0
as_total_pondere_min = 0
as_forfait_min = 0
as_forfait_pondere_min = 0
as_cats: dict[str, dict] = {}
for p in pointages:
@ -603,8 +630,14 @@ def compute_week(pointages: list[dict], conges: list[dict], heures_jour_min: int
if jour_astreinte_qualifie(p["date"], astreintes) and events else None)
matin_ex, aprem_ex = exclusion_retour(conges_date, retour_min, plages, jour_ferie)
forfait = forfait_as_min if p["date"] in astreintes else 0
# Le forfait d'astreinte est considéré réalisé en journée du jour AS
# déclaré : il bénéficie de la bonification « journée » de ce jour
# (×1 en semaine, ×1,5 le samedi, ×2 le dimanche ou férié par défaut).
regle_journee = regle_journee_astreinte(p["date"], facteurs, feries) if forfait else None
forfait_pondere = int(forfait * (regle_journee or {"facteur": 1.0})["facteur"] + 0.5) if forfait else 0
# Le forfait d'astreinte ne compte jamais dans les heures travaillées :
# il est suivi à part dans le récapitulatif d'astreinte.
# il est suivi à part dans le récapitulatif d'astreinte, pondéré par la
# bonification journée.
#
# Les heures de présence obligatoire couvertes par le repos de 11h
# (matin_ex + aprem_ex) sont comptées comme effectuées : créditées au
@ -662,8 +695,13 @@ def compute_week(pointages: list[dict], conges: list[dict], heures_jour_min: int
"total_pondere_h": dec["total_pondere_h"] if dec else "",
"forfait_min": forfait,
"forfait_h": minutes_to_hhmm(forfait) if forfait else "",
"forfait_pondere_min": forfait_pondere,
"forfait_pondere_h": minutes_to_hhmm(forfait_pondere) if forfait_pondere else "",
"forfait_regle": regle_journee["nom"] if regle_journee else "",
"forfait_facteur_txt": regle_journee["facteur_txt"] if regle_journee else "1",
})
as_forfait_min += forfait
as_forfait_pondere_min += forfait_pondere
if dec and dec["total_min"] > 0:
as_total_min += dec["total_min"]
as_total_pondere_min += dec["total_pondere_min"]
@ -875,6 +913,8 @@ def compute_week(pointages: list[dict], conges: list[dict], heures_jour_min: int
"total_pondere_h": minutes_to_hhmm(as_total_pondere_min),
"total_forfait_min": as_forfait_min,
"total_forfait_h": minutes_to_hhmm(as_forfait_min),
"total_forfait_pondere_min": as_forfait_pondere_min,
"total_forfait_pondere_h": minutes_to_hhmm(as_forfait_pondere_min),
"categories": as_categories,
"jours": as_jours,
},