Files
pointeuse-optimisator/app/templates/_ligne.html
Jacquin Antoine 77ae115c4f Retour décalé après astreinte : la présence obligatoire couverte compte comme effectuée
Quand le repos de 11h décale le retour au bureau (ex. 11:00), les heures de
présence obligatoire couvertes (ex. 09:00→11:00) sont créditées à la colonne
Travaillé au lieu d'être retirées des heures dues, qui restent complètes.
Le solde est inchangé, mais le calcul est explicite : badge « +2h00 repos »
sous le total (plages couvertes au survol) et rappel dans le bloc astreinte.
Rien n'est crédité sans heures dues (week-end, férié, congé), et le crédit
ne dépasse pas le nominal du jour.

Corrige aussi la perte des interventions postées sans description (le zip
s'arrêtait sur la liste vide des descriptions).

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-09-09 21:05:50 +02:00

194 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% set matin_cg = 'matin' in j.conge or 'jour' in j.conge %}
{% set aprem_cg = 'aprem' in j.conge or 'jour' in j.conge %}
{% set matin_requis = not matin_cg and j.du_min > 0 and j.matin_nominal_min > 0 %}
{% set aprem_requis = not aprem_cg and j.du_min > 0 and j.aprem_nominal_min > 0 %}
{% set borne_matin = [plages.matin_debut, j.retour or plages.matin_debut] | max %}
{% set borne_aprem = [plages.aprem_debut, j.retour or plages.aprem_debut] | max %}
{% set matin_warn = matin_requis and (
(j.matin_entree and j.matin_entree > borne_matin) or
(j.matin_sortie and j.matin_sortie < plages.matin_fin)
) %}
{% set aprem_warn = aprem_requis and (
(j.aprem_entree and j.aprem_entree > borne_aprem) or
(j.aprem_sortie and j.aprem_sortie < plages.aprem_fin)
) %}
<tr id="row-{{ j.date }}"{% if nom in ['Samedi', 'Dimanche'] or j.ferie %} class="we"{% endif %}>
<td class="col-jour">
<span class="jour-nom">{{ nom }}</span>
<span class="jour-date">{{ j.date[8:] }}/{{ j.date[5:7] }}</span>
{% if j.ferie %}<span class="ferie-badge" title="Jour férié : dû 0, astreinte comptée 0h00 → 0h00">férié</span>{% endif %}
<!-- Auto-enregistrement : la sauvegarde se déclenche à la validation d'un
champ du jour (voir script de semaine.html), ce témoin en suit l'état. -->
<span class="autosave" id="save-{{ j.date }}" data-date="{{ j.date }}"
hx-post="/pointage/{{ j.date }}" hx-swap="none"
hx-include="[data-date='{{ j.date }}']" hx-trigger="save-day"></span>
</td>
<td class="c-matin">
<div id="cg-matin-{{ j.date }}" data-label="Matin" class="td-fill{% if matin_cg %} cg{% elif matin_warn %} warn{% endif %}">
<div class="time-pair">
<input class="time-input" type="time" name="matin_entree"
data-date="{{ j.date }}" value="{{ j.matin_entree or '' }}">
<span class="time-sep">→</span>
<input class="time-input" type="time" name="matin_sortie"
data-date="{{ j.date }}" value="{{ j.matin_sortie or '' }}">
</div>
</div>
</td>
<td class="c-aprem">
<div id="cg-aprem-{{ j.date }}" data-label="Après-midi" class="td-fill{% if aprem_cg %} cg{% elif aprem_warn %} warn{% endif %}">
<div class="time-pair">
<input class="time-input" type="time" name="aprem_entree"
data-date="{{ j.date }}" value="{{ j.aprem_entree or '' }}">
<span class="time-sep">→</span>
<input class="time-input" type="time" name="aprem_sortie"
data-date="{{ j.date }}" value="{{ j.aprem_sortie or '' }}">
</div>
</div>
</td>
<td class="col-calc" data-label="Travaillé">
<span id="calc-{{ j.date }}-trav">
<span class="calc-num">{{ j.travaille if j.travaille_min else '—' }}</span>
{% if j.couvert_min %}<span class="calc-couvert" title="Présence obligatoire couverte par le repos de 11h ({{ j.couvert_detail }}) : comptée comme effectuée">+{{ j.couvert_h }} repos</span>{% endif %}
</span>
</td>
<td class="col-calc" data-label="Δ jour">
<span id="calc-{{ j.date }}-delta">
<span class="{% if j.travaille_min and j.delta_min > 0 %}delta-pos{% elif j.travaille_min and j.delta_min < 0 %}delta-neg{% else %}delta-zero{% endif %}">
{%- if j.travaille_min -%}
{% if j.delta_min > 0 %}+{% endif %}{{ j.delta }}
{%- else %}—{%- endif %}
</span>
</span>
</td>
<td class="col-cumul" data-label="Δ sem.">
<span id="calc-{{ j.date }}-cumul">
{%- if j.cumul_visible -%}
<span class="{% if j.delta_cumul_min > 0 %}delta-pos{% elif j.delta_cumul_min < 0 %}delta-neg{% else %}delta-zero{% endif %}">
{% if j.delta_cumul_min > 0 %}+{% elif j.delta_cumul_min < 0 %}-{% endif %}{{ j.delta_cumul if j.delta_cumul_min != 0 else '0h00' }}
</span>
{%- else -%}
<span class="delta-zero">—</span>
{%- endif %}
</span>
</td>
<td class="col-cible" data-label="Cible">
<span id="calc-{{ j.date }}-cible">
{%- if j.cible_matin or j.cible_aprem -%}
{%- if j.cible_matin -%}<span class="cible-num">M {{ j.cible_matin_entree }} → {{ j.cible_matin }}</span>{%- endif -%}
{%- if j.cible_matin and j.cible_aprem %} {% endif -%}
{%- if j.cible_aprem -%}<span class="cible-num">A {{ j.cible_aprem_entree }} → {{ j.cible_aprem }}</span>{%- endif -%}
{%- else -%}
<span class="delta-zero">—</span>
{%- endif %}
</span>
</td>
<td class="col-conge" data-label="Congé">
<div id="cg-btn-{{ j.date }}" class="cg-cell">
<details class="cg-menu">
<summary class="cg-trigger" title="Congés, jour férié, astreinte">
<span class="cg-state">
{%- if 'jour' in j.conge %}<span class="cg-chip st-jour">J</span>{% endif -%}
{%- if 'matin' in j.conge %}<span class="cg-chip st-ma">MA</span>{% endif -%}
{%- if 'aprem' in j.conge %}<span class="cg-chip st-am">AM</span>{% endif -%}
{%- if j.ferie %}<span class="cg-chip st-ferie">F</span>{% endif -%}
{%- if plages.astreinte_active and j.astreinte %}<span class="cg-chip st-as">AS</span>{% endif -%}
{%- if not (j.conge or j.ferie or (plages.astreinte_active and j.astreinte)) %}<span class="cg-none">—</span>{% endif -%}
</span>
<span class="cg-caret">▾</span>
</summary>
<div class="cg-pop">
<button hx-post="/conge/{{ j.date }}/matin" hx-swap="none"
class="cg-opt{% if 'matin' in j.conge %} on{% endif %}">
<span class="cg-opt-chip ma">MA</span> Congé matin
</button>
<button hx-post="/conge/{{ j.date }}/aprem" hx-swap="none"
class="cg-opt{% if 'aprem' in j.conge %} on{% endif %}">
<span class="cg-opt-chip am">AM</span> Congé après-midi
</button>
<button hx-post="/conge/{{ j.date }}/jour" hx-swap="none"
class="cg-opt{% if 'jour' in j.conge %} on{% endif %}">
<span class="cg-opt-chip jour">J</span> Journée entière
</button>
<div class="cg-opt-sep"></div>
<button hx-post="/ferie/{{ j.date }}/toggle" hx-swap="none"
class="cg-opt{% if j.ferie %} on{% endif %}"
title="Jour férié : dû 0, astreinte comptée 0h00 → 0h00">
<span class="cg-opt-chip ferie">F</span> Jour férié
</button>
{% if plages.astreinte_active %}
<button hx-post="/astreinte/{{ j.date }}/toggle" hx-swap="none"
class="cg-opt{% if j.astreinte %} on{% endif %}"
title="Jour d'astreinte (18h → 18h, ou 0h → 0h sam/dim/férié)">
<span class="cg-opt-chip as">AS</span> Jour d'astreinte
</button>
{% endif %}
</div>
</details>
</div>
</td>
</tr>
{% if j.astreinte_qualifiee %}
{% set nb_as = (j.astreinte_events or []) | length %}
<tr class="as-row{% if nom in ['Samedi', 'Dimanche'] %} we{% endif %}">
<td colspan="8">
<div id="as-block-{{ j.date }}" class="as-block" data-date="{{ j.date }}" data-label="Astreinte">
<div class="as-head">
<button type="button" class="as-toggle" data-date="{{ j.date }}" aria-expanded="false"
onclick="asToggle(this)">
<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é (durée arrondie au quart d'heure supérieur), retour arrondi au quart d'horloge supérieur : :00, :15, :30 ou :45">retour ≥ {{ j.retour }}</span>{% endif %}
{% if j.couvert_min %}<span class="as-hint" title="Présence obligatoire couverte par le repos ({{ j.couvert_detail }}) : comptée comme effectuées dans la colonne Travaillé">+{{ j.couvert_h }} de présence comptées</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="Durée réelle des interventions arrondie au quart d'heure supérieur (2, 5 ou 12 min → 15 ; 22 ou 28 → 30), même sans tomber sur un quart d'heure de l'horloge — compteur séparé, hors heures de semaine">astreinte : {{ j.astreinte_h }}</span>{% endif %}
</div>
<div class="as-body">
<div class="as-grid" id="as-events-{{ j.date }}">
<span class="as-th">Début</span><span class="as-th">Fin</span><span class="as-th">Description</span>
{% for ev in j.astreinte_events or [] %}
<div class="as-event">
<input class="time-input" type="time" name="astreinte_debut"
data-date="{{ j.date }}" value="{{ ev.debut or '' }}">
<input class="time-input" type="time" name="astreinte_fin"
data-date="{{ j.date }}" value="{{ ev.fin or '' }}">
<div class="as-desc-cell">
<input type="text" class="as-desc" name="astreinte_desc"
data-date="{{ j.date }}" maxlength="200" placeholder="description"
value="{{ ev.desc or '' }}">
<button type="button" class="as-del" title="Supprimer"
onclick="this.closest('.as-event').remove()">×</button>
</div>
</div>
{% else %}
<div class="as-event">
<input class="time-input" type="time" name="astreinte_debut"
data-date="{{ j.date }}" value="">
<input class="time-input" type="time" name="astreinte_fin"
data-date="{{ j.date }}" value="">
<div class="as-desc-cell">
<input type="text" class="as-desc" name="astreinte_desc"
data-date="{{ j.date }}" maxlength="200" placeholder="description" value="">
<button type="button" class="as-del" title="Supprimer"
onclick="this.closest('.as-event').remove()">×</button>
</div>
</div>
{% endfor %}
</div>
<button type="button" class="as-add" onclick="asAddEvent('{{ j.date }}')">+ intervention</button>
</div>
</div>
</td>
</tr>
{% else %}
<tr class="as-row{% if nom in ['Samedi', 'Dimanche'] %} we{% endif %}"><td colspan="8"><div id="as-block-{{ j.date }}" class="as-block"></div></td></tr>
{% endif %}