{% extends 'base.html.twig' %} {# ══════════════════════════════════════════════════════════════════ Template — Feuille de présence mensuelle (saisie) ══════════════════════════════════════════════════════════════════ Utilisé à la fois par l'employé connecté (PointageController) et par l'administrateur (AdminController) via les variables : saveRoute / saveParams : route + paramètres de sauvegarde pdfRoute / pdfParams : route + paramètres d'export PDF isAdmin : booléen — affiche les tarifs unitaires et autorise la modification des observations Variables attendues : targetUser : User — employé affiché feuille : Pointage[] — lignes du mois (une par jour) year, month : int — période affichée totaux : array — cumuls mensuels (hj, hn, repas…) weeklyTotals : array — sous-totaux par semaine ISO statuts : StatutPointage[] — toutes les valeurs de l'enum tarifs : array|null — tarifs d'indemnités (si définis) totalAPayer : float — montant total calculé feuilleM : FeuilleMensuelle|null — km + observations Fonctionnalités interactives (JavaScript en bas de page) : - Calcul HJ/HN en temps réel dès que les heures changent - Calcul du kilométrage mensuel (fin - début) - Bouton "Sauvegarder" flottant (position: fixed) toujours visible Accessibilité mobile : - Toutes les colonnes sont forcées visibles (.pointage-scroll) - Scroll horizontal dans le conteneur du tableau - Sticky sur thead (en-tête) et tfoot (totaux) ══════════════════════════════════════════════════════════════════ #} {% block title %}Feuille de présence — {{ targetUser.nomComplet }}{% endblock %} {% block page_title %}Feuille de présence — {{ targetUser.nomComplet }}{% endblock %} {% set moisNoms = {1:'Janvier',2:'Fevrier',3:'Mars',4:'Avril',5:'Mai',6:'Juin', 7:'Juillet',8:'Aout',9:'Septembre',10:'Octobre',11:'Novembre',12:'Decembre'} %} {% set jourNomsFr = {'1':'lundi','2':'mardi','3':'mercredi','4':'jeudi','5':'vendredi','6':'samedi','7':'dimanche'} %} {% block body %} {# --- Navigation mois --- #}
{% set prevMonth = month - 1 %} {% set prevYear = year %} {% if prevMonth < 1 %}{% set prevMonth = 12 %}{% set prevYear = year - 1 %}{% endif %} {% set nextMonth = month + 1 %} {% set nextYear = year %} {% if nextMonth > 12 %}{% set nextMonth = 1 %}{% set nextYear = year + 1 %}{% endif %} {% if is_granted('ROLE_ADMIN') and saveParams.userId is defined %} {% else %} {% endif %}
{{ moisNoms[month] }} {{ year }}
Exporter PDF
{# --- Formulaire de saisie --- #}
{% if targetUser.matricule %}[{{ targetUser.matricule }}]{% endif %} {{ targetUser.nomComplet }} {% if targetUser.poste %}— {{ targetUser.poste }}{% endif %}
HJ : {{ '%.2f'|format(totaux.hj) }} HN : {{ '%.2f'|format(totaux.hn) }} {% if totaux.standBye > 0 %}S.By : {{ '%.2f'|format(totaux.standBye) }}{% endif %}
{{ moisNoms[month] }} {{ year }}  | FEUILLE DE PRÉSENCE
{% for pointage in feuille %} {% set dateStr = pointage.date|date('Y-m-d') %} {% set statutVal = pointage.statut.value %} {% set isOff = pointage.statut.jourOff %} {% set dowN = pointage.date|date('N') %} {# JOUR #} {# DATE #} {# STATUT (sm+) #} {# CHANTIER (lg+) #} {# OBSERVATION / NOTES (lg+) #} {# HORAIRES DÉBUT-FIN #} {# PAUSE (sm+) — durée de la pause repas en minutes, 30 min par défaut #} {# REPAS (sm+) #} {# HJ — calculé côté client #} {# HN (sm+) — calculé côté client #} {# STAND BYE (lg+) #} {# TRAJET KM (lg+) #} {# TRAJET HEURE (lg+) #} {# DÉPLACEMENT NT (lg+) #} {# KM VP (lg+) #} {# ── Ligne sous-total semaine ── #} {% if dowN == '7' or loop.last %} {% set weekKey = pointage.date|date('o') ~ '-' ~ pointage.date|date('W') %} {% set wk = weeklyTotals[weekKey] ?? {'hj': 0, 'hn': 0} %} {% endif %} {% endfor %}
JOUR DATE Statut Chantier, client, lieu Observation HORAIRES
Début — Fin
Pause
( min )
Repas HJ
6h-22h
HN
22h-6h
Stand-by
( en h )
Trajet
KM
Trajet
Heure
Dépl.
NT
Km VP
{{ jourNomsFr[dowN] }}{{ pointage.date|date('d') }} {% if not isOff %} {% else %}{% endif %} {% if not isOff %} {% else %}{% endif %} {% if not isOff %} {% else %} {% endif %} {% if not isOff %} {% else %} {% endif %} {% if not isOff %} {% else %} {% endif %} {{ isOff ? '—' : (pointage.heuresJour > 0 ? '%.2f'|format(pointage.heuresJour) : '') }} {{ isOff ? '—' : (pointage.heuresNuit > 0 ? '%.2f'|format(pointage.heuresNuit) : '') }} {% if not isOff %} {% else %} {% endif %} {% if not isOff %} {% else %} {% endif %} {% if not isOff %} {% else %} {% endif %} {% if not isOff %} {% else %} {% endif %} {% if not isOff %} {% else %} {% endif %}
Sem. {{ pointage.date|date('W') }} Total : {{ '%.2f'|format(wk['hj']) }} {{ '%.2f'|format(wk['hn']) }}
TOTAL {{ totaux.repas }} {{ '%.2f'|format(totaux.hj) }} {{ '%.2f'|format(totaux.hn) }} {{ '%.2f'|format(totaux.standBye) }} {{ totaux.trajetKm }} {{ '%.2f'|format(totaux.trajetHeures) }} {{ totaux.deplacementNt }} {{ totaux.kmVp }}
{# bouton bas masqué — remplacer d-none par d-flex pour réactiver #}
{# ── Récapitulatif du mois ── #}
{{ '%.2f'|format(totaux.hj) }}
Heures Jour
{{ '%.2f'|format(totaux.hn) }}
Heures Nuit
{{ '%.2f'|format(totaux.standBye) }}
Stand-by
{{ totaux.trajetKm }}
Trajet KM
{{ '%.2f'|format(totaux.trajetHeures) }}
Trajet Heures
{{ totaux.kmVp }}
Km VP
{# ── Section indemnités + total à payer + km véhicule (visible par tous) ── #} {% if tarifs is defined %}
Indemnités & Total à payer
{# -- Tableau calcul indemnités -- #}
{% if isAdmin is defined and isAdmin %}{% endif %} {% set tarifRepas = tarifs.repas ?? 0 %} {% set tarifDepl = tarifs.deplacement ?? 0 %} {% set tarifKm = tarifs.kilometre ?? 0 %} {% set montantRepas = totaux.repas * tarifRepas %} {% set montantDepl = totaux.deplacementNt * tarifDepl %} {% set montantKm = totaux.kmVp * tarifKm %} {% if isAdmin is defined and isAdmin %}{% endif %} {% if isAdmin is defined and isAdmin %}{% endif %} {% if isAdmin is defined and isAdmin %}{% endif %}
Indemnité QuantitéTarif unitaireMontant
Repas {{ totaux.repas }}{{ tarifRepas|number_format(2, ',', ' ') }} €{{ montantRepas|number_format(2, ',', ' ') }} €
Déplacement NT {{ totaux.deplacementNt }}{{ tarifDepl|number_format(2, ',', ' ') }} €{{ montantDepl|number_format(2, ',', ' ') }} €
Kilomètres VP {{ totaux.kmVp }}{{ tarifKm|number_format(4, ',', ' ') }} €{{ montantKm|number_format(2, ',', ' ') }} €
TOTAL À PAYER : {{ totalAPayer|number_format(2, ',', ' ') }} €
{# Récapitulatif heures #}
Récapitulatif heures (effectives)
Jour (HJ) Nuit (HN) Routes Stand-by
{{ '%.2f'|format(totaux.hj) }} {{ '%.2f'|format(totaux.hn) }} {{ '%.2f'|format(totaux.trajetHeures) }} {{ '%.2f'|format(totaux.standBye) }}
{# -- Kilométrage véhicule + Observations -- #}
Kilométrage véhicule
Immatriculation
Début de mois
Fin de mois
Total {% if feuilleM and feuilleM.kmTotal is not null %} {{ feuilleM.kmTotal }} km {% else %}—{% endif %}
{% if isAdmin is defined and isAdmin %} {% else %}
{{ feuilleM and feuilleM.observations ? feuilleM.observations : '' }}
{% endif %}
{% if isAdmin is defined and isAdmin %} {% endif %}
{# /row #}
{% endif %} {% endblock %} {% block javascripts %} {% endblock %}