Le forfait d'astreinte ne compte plus dans les heures travaillées
Le temps travaillé, l'écart du jour et le solde de la semaine ne
restituent plus que les heures pointées. Le forfait des jours AS reste
suivi à part : ligne du jour et récapitulatif d'astreinte, libellés et
documentation ajustés en conséquence.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@ -194,9 +194,10 @@ jour, pleine largeur : un menu dépliant fermé par défaut (seuls l'heure de re
|
||||
et le total restent visibles). Déplié, il offre autant de lignes que nécessaire
|
||||
(**+ intervention**) sur trois colonnes : **début**, **fin** et description
|
||||
libre. Une fin antérieure au début (fin < début) désigne une intervention à
|
||||
cheval sur minuit. Une durée forfaitaire peut être ajoutée au temps travaillé de
|
||||
chaque jour d'astreinte déclaré (page **Réglages**, « Forfait par jour
|
||||
d'astreinte »).
|
||||
cheval sur minuit. Une durée forfaitaire peut être attribuée à chaque jour
|
||||
d'astreinte déclaré (page **Réglages**, « Forfait par jour d'astreinte ») :
|
||||
elle ne compte jamais dans les heures travaillées, elle est suivie à part dans
|
||||
le récapitulatif d'astreinte.
|
||||
|
||||
La semaine affiche aussi **samedi et dimanche** (heures dues nulles, lignes
|
||||
grisées) : on peut y déclarer des astreintes, y saisir les interventions et les
|
||||
|
||||
@ -458,7 +458,9 @@ 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
|
||||
travaille = heures_travaillees(p, retour_min) + forfait
|
||||
# Le forfait d'astreinte ne compte jamais dans les heures travaillées :
|
||||
# il est suivi à part dans le récapitulatif d'astreinte.
|
||||
travaille = heures_travaillees(p, retour_min)
|
||||
du = heures_dues(p["date"], conges, heures_jour_min, plages, retour_min, jour_ferie)
|
||||
du_full = du + matin_ex + aprem_ex
|
||||
matin_nom, aprem_nom = nominaux_du_jour(conges_date, du_full, matin_ex, aprem_ex, jour_ferie)
|
||||
|
||||
11
app/main.py
11
app/main.py
@ -335,7 +335,7 @@ def _build_jour_ctx(date, conges, h_jour, user_id):
|
||||
matin_ex, aprem_ex = exclusion_retour(conges_date, retour_min, plages, jour_ferie)
|
||||
forfait = (hhmm_to_minutes(plages["astreinte_forfait"]) if plages.get("astreinte_forfait") else 0) \
|
||||
if date in astreintes else 0
|
||||
trav = heures_travaillees(p, retour_min) + forfait
|
||||
trav = heures_travaillees(p, retour_min) # forfait d'astreinte : hors heures travaillées
|
||||
du = heures_dues(date, conges, h_jour, plages, retour_min, jour_ferie)
|
||||
du_full = du + matin_ex + aprem_ex
|
||||
matin_nom, aprem_nom = nominaux_du_jour(conges_date, du_full, matin_ex, aprem_ex, jour_ferie)
|
||||
@ -492,8 +492,8 @@ def _as_block_html(date, jour):
|
||||
hint = (f'<span class="as-hint" title="11h de repos consécutif après la dernière activité, fin arrondie au quart d\'heure entamé">'
|
||||
f'retour ≥ {_e(jour["retour"])}</span>')
|
||||
if jour.get("forfait_min"):
|
||||
hint += (f'<span class="as-hint" title="Forfait réglé dans Réglages, ajouté au temps travaillé">'
|
||||
f'forfait + {_e(jour["forfait_h"])}</span>')
|
||||
hint += (f'<span class="as-hint" title="Forfait du jour AS déclaré (réglé dans Réglages) : suivi dans le récapitulatif d'astreinte, hors heures travaillées">'
|
||||
f'forfait {_e(jour["forfait_h"])}</span>')
|
||||
total = ""
|
||||
if jour.get("astreinte_min"):
|
||||
total = (f'<span class="as-total" title="Décompte par quarts d'heure de l'horloge entamés (:00, :15, :30, :45), chacun compté 15 min entières — compteur séparé, hors heures de semaine">'
|
||||
@ -1125,8 +1125,9 @@ def settings_plages_save(
|
||||
|
||||
@app.post("/settings/astreinte-forfait", response_class=HTMLResponse)
|
||||
def settings_astreinte_forfait(request: Request, astreinte_forfait: str = Form("")):
|
||||
"""Durée forfaitaire ajoutée au temps travaillé de chaque jour d'astreinte
|
||||
déclaré (réglage par utilisateur, stocké avec ses plages)."""
|
||||
"""Durée forfaitaire attribuée à chaque jour d'astreinte déclaré (réglage par
|
||||
utilisateur, stocké avec ses plages) : suivie dans le récapitulatif
|
||||
d'astreinte, jamais comptée dans les heures travaillées."""
|
||||
user_id = _get_user(request)
|
||||
if not user_id:
|
||||
return RedirectResponse("/login", status_code=302)
|
||||
|
||||
@ -131,7 +131,7 @@
|
||||
<span class="as-caret">▸</span> {{ nb_as }} intervention{{ 's' if nb_as != 1 else '' }}
|
||||
</button>
|
||||
{% if j.retour_min is not none %}<span class="as-hint" title="11h de repos consécutif après la dernière activité, fin arrondie au quart d'heure entamé">retour ≥ {{ j.retour }}</span>{% endif %}
|
||||
{% if j.forfait_min %}<span class="as-hint" title="Forfait réglé dans Réglages, ajouté au temps travaillé">forfait + {{ j.forfait_h }}</span>{% endif %}
|
||||
{% if j.forfait_min %}<span class="as-hint" title="Forfait du jour AS déclaré (Réglages) : suivi dans le récapitulatif d'astreinte, hors heures travaillées">forfait {{ j.forfait_h }}</span>{% endif %}
|
||||
{% if j.astreinte_min %}<span class="as-total" title="Décompte par quarts d'heure de l'horloge entamés (:00, :15, :30, :45), chacun compté 15 min entières — compteur séparé, hors heures de semaine">astreinte : {{ j.astreinte_h }}</span>{% endif %}
|
||||
</div>
|
||||
<div class="as-body">
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
<div class="as-jour">
|
||||
<div class="as-jour-head">
|
||||
<span class="as-jour-date">{{ j.jour }} {{ j.date[8:] }}/{{ j.date[5:7] }}</span>
|
||||
{% if j.forfait_min %}<span class="as-forfait" title="Forfait du jour AS déclaré (réglé dans Réglages) : ajouté au temps travaillé de la semaine, hors compteurs d'astreinte">forfait + {{ j.forfait_h }}</span>{% endif %}
|
||||
{% if j.forfait_min %}<span class="as-forfait" title="Forfait du jour AS déclaré (réglé dans Réglages) : suivi dans le récapitulatif d'astreinte, jamais compté dans les heures travaillées ni dans les compteurs pondérés">forfait {{ j.forfait_h }}</span>{% endif %}
|
||||
{% if j.total_min %}<span class="as-jour-total">astreinte {{ j.total_h }} → {{ j.total_pondere_h }} pondérées</span>{% endif %}
|
||||
</div>
|
||||
{% for ev in j.events %}
|
||||
@ -76,7 +76,7 @@
|
||||
{% endfor %}
|
||||
<div class="as-totaux">
|
||||
{% for c in result.astreinte.categories %}<span class="as-cat">{{ c.nom }} : {{ c.min_h }} ×{{ c.facteur_txt }} = {{ c.pondere_h }}</span>{% endfor %}
|
||||
{% if result.astreinte.total_forfait_min %}<span class="as-forfait" title="Forfaits des jours AS déclarés : ajoutés au temps travaillé, hors compteurs d'astreinte">forfaits + {{ result.astreinte.total_forfait_h }} <em>(dans le travaillé)</em></span>{% endif %}
|
||||
{% if result.astreinte.total_forfait_min %}<span class="as-forfait" title="Forfaits des jours AS déclarés : suivis à part, jamais comptés dans les heures travaillées">forfaits {{ result.astreinte.total_forfait_h }} <em>(hors heures travaillées)</em></span>{% endif %}
|
||||
<span class="as-grand">total {{ result.astreinte.total_h }} → {{ result.astreinte.total_pondere_h }} pondérées</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -125,9 +125,10 @@ function asDelRatio(btn) { btn.closest('.as-ratio-edit').remove(); }
|
||||
<div class="settings-card">
|
||||
<span class="hist-label">Forfait par jour d'astreinte</span>
|
||||
<p class="settings-p">
|
||||
Durée ajoutée automatiquement au temps travaillé de chaque jour d'astreinte
|
||||
déclaré (bouton <b>AS</b>), en plus des interventions saisies. Elle compte dans
|
||||
le bilan de la semaine ; le lendemain de l'astreinte n'est pas concerné.
|
||||
Durée forfaitaire attribuée à chaque jour d'astreinte déclaré (bouton <b>AS</b>),
|
||||
en plus des interventions saisies. Elle ne compte jamais dans les heures
|
||||
travaillées : elle est suivie à part dans le récapitulatif d'astreinte de la
|
||||
semaine ; le lendemain de l'astreinte n'est pas concerné.
|
||||
Vide = pas de forfait.
|
||||
</p>
|
||||
|
||||
|
||||
@ -555,9 +555,10 @@ def test_compute_week_astreinte_samedi_dimanche(freeze_today):
|
||||
|
||||
# ── Forfait par jour d'astreinte déclaré ───────────────────────────────────────
|
||||
|
||||
def test_compute_week_forfait_ajoute_au_travaille_du_jour_declare(freeze_today):
|
||||
"""Forfait 1h00 réglé : ajouté au travaillé du jour AS déclaré uniquement
|
||||
(pas du lendemain), sans toucher aux heures dues."""
|
||||
def test_compute_week_forfait_hors_heures_travaillees(freeze_today):
|
||||
"""Forfait 1h00 réglé : attribué au jour AS déclaré uniquement (pas du
|
||||
lendemain), mais jamais compté dans les heures travaillées — seulement
|
||||
suivi dans le récapitulatif d'astreinte."""
|
||||
plages = {**PLAGES, "astreinte_forfait": "01:00"}
|
||||
pointages = [
|
||||
_pointage("2026-07-13", "09:00", "12:24", "13:30", "17:54"),
|
||||
@ -567,10 +568,10 @@ def test_compute_week_forfait_ajoute_au_travaille_du_jour_declare(freeze_today):
|
||||
result = compute_week(pointages, [], HEURES_JOUR_MIN, plages, ["2026-07-14"])
|
||||
mardi = result["jours"][1]
|
||||
assert mardi["forfait_min"] == 60
|
||||
assert mardi["travaille_min"] == HEURES_JOUR_MIN + 60
|
||||
assert mardi["travaille_min"] == HEURES_JOUR_MIN # pointé seul, forfait exclu
|
||||
assert result["jours"][2]["forfait_min"] == 0 # lendemain : rien
|
||||
assert result["jours"][0]["forfait_min"] == 0 # jour sans astreinte
|
||||
assert result["total_travaille"] == "16h36" # 2 × 7h48 + 1h
|
||||
assert result["total_travaille"] == "15h36" # 2 × 7h48, forfait exclu
|
||||
# récapitulatif d'astreinte : le jour AS apparaît avec son forfait même sans
|
||||
# intervention ; le forfait est rappelé mais hors compteurs pondérés
|
||||
ast = result["astreinte"]
|
||||
|
||||
Reference in New Issue
Block a user