## Correctifs RH (branche fix/retour-rh) ### Vue Jour (Heures) - Mode saisie/présence, libellé de contrat et sauvegarde résolus **à la date affichée** (et non au contrat courant). Corrige les salariés passés 39h/35h → Forfait. ### RTT — heures supplémentaires - Proratisation du **plafond 25%/50%** pour les embauches en milieu de semaine (la bande +25% se décale au lieu de rester bloquée à 43h). Témoin Dylan : 4h à 25% + 3h à 50%. ### Récap salaire (PDF mensuel) - Forfait : congés imputés **N-1** non affichés et comptés en présence. - Colonne « Heures payés » **scindée 25% / 50%** (en-tête fusionné). - **Exclusion des salariés sans contrat** sur le mois (ex. Marine, contrat terminé). ### Exports heures annuelles (par salarié + tous) - **Tous les jours sous contrat** affichés, même vides/non saisis (corrige les lignes manquantes). - Samedis/dimanches en **gris plus foncé**. ### Panier de nuit - **Ne s'applique pas aux conducteurs** (vue semaine + récap salaire). ## Tests - 11 tests ajoutés. Suite verte hors un test legacy pré-existant dépendant de la date (`EmployeeRttSummaryProviderTest::testNoQueryParamsKeepsLegacyYearDefaulting`, non modifié par cette branche). ## À noter (hors scope) - L'export heures annuelles *tous salariés* peut dépasser `memory_limit=256M` (Dompdf) — limitation **pré-existante**, non corrigée ici. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #21 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
4.0 KiB
Vue Jour (Heures) — résolution du contrat à la date affichée
Date : 2026-06-01
Problème
Sur l'écran Heures — vue Jour (HoursDayView), l'affichage saisie d'heures (TIME)
vs cases de présence (PRESENCE), ainsi que le libellé de contrat entre parenthèses,
sont résolus à partir de employee.contract — c'est-à-dire le contrat courant
de l'employé (résolu à aujourd'hui), pas le contrat valable à la date affichée.
Conséquence pour un salarié passé d'un contrat 39h/35h (TIME) à un Forfait (PRESENCE) :
- toutes les dates passées s'affichent en cases de présence alors qu'elles relevaient d'un contrat en heures ;
- pire,
handleSave(useHoursPage.ts:1073) se base sur le même test : éditer une date passée écrit des flags de présence au lieu des heures et écrase la saisie.
La vue Semaine est déjà correcte : elle résout le trackingMode par date côté
backend via WeeklySummaryRow.trackingMode. Le périmètre de ce correctif est donc
la vue Jour uniquement.
Principe
Le provider backend WorkHourDayContextProvider::provide() résout déjà le contrat
à la date affichée (EmployeeContractResolver::resolveForEmployeeAndDate) et expose
déjà contractNature par date sur chaque ligne. Il suffit :
- d'exposer sur la ligne du jour les champs de contrat manquants ;
- de faire lire ces champs au frontend (au lieu de
employee.contract).
L'ensemble de la ligne (toggle saisie/présence + libellé 39h/Forfait + logique 4h) devient ainsi cohérent avec le contrat valable à la date affichée.
Changements
Backend
-
src/Dto/WorkHours/DayContextRow.php— ajouter 4 champs au constructeur et àtoArray()(+ mettre à jour le PHPDoc du retour detoArray()) :trackingMode: ?stringweeklyHours: ?intcontractType: ?stringcontractName: ?string
-
src/State/WorkHourDayContextProvider.php— peupler ces champs depuis le$contractdéjà résolu (lignes 60-71) :trackingMode=$contract?->getTrackingMode()weeklyHours=$contract?->getWeeklyHours()contractType=$contract?->getType()->valuecontractName=$contract?->getName()- tous
nullsi pas de contrat à la date (cohérent avechasContractAtDate).
Frontend
-
frontend/services/dto/work-hour.ts— refléter les 4 champs surWorkHourDayContextRow. -
frontend/composables/useHoursPage.ts—isPresenceTracking,isTimeTracking,contractLabel,is4hContractlisent ledayContextByEmployeeId.get(employeeId)(résolu par date), avec fallback suremployee.contractsi aucune ligne du jour n'existe. Cela corrige automatiquementhandleSave(ligne 1073), qui s'appuie surisPresenceTracking.Les signatures actuelles prennent un
Employee; on conserve la signature et on utiliseemployee.iden interne pour récupérer la ligne du jour.
Hors périmètre
- Vue Semaine (déjà par date).
- Heures Conducteurs (toujours en mode TIME, pas de toggle).
- Processor de sauvegarde backend : inchangé — le frontend enverra déjà la bonne forme (heures vs présence) par date.
Tests / vérification
- Test backend (
WorkHourDayContextProvider) : pour un employé avec historique 39h → Forfait, la ligne renvoyée portetrackingMode=TIME/weeklyHours=39/contractTypenon-forfait sur une date avant la bascule, ettrackingMode=PRESENCE/contractType=FORFAITsur une date après. - Vérification manuelle : naviguer une date avant et après la bascule sur la fiche du salarié → champs d'heures puis cases de présence, libellé cohérent.
Documentation (règle obligatoire)
doc/: section vue Jour — résolution du contrat (mode + libellé) à la date affichée.frontend/data/documentation-content.ts: note utilisateur correspondante.CLAUDE.md: préciser que la vue Jour résouttrackingMode/libellé à la date filtrée (au même titre quecontractNaturedéjà documenté).