From 7fbd4029c794f0aa8851bb7c647402a4a287b4e3 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 8 Jun 2026 17:37:11 +0200 Subject: [PATCH] docs(heures) : documenter l'export PDF jour --- CLAUDE.md | 1 + doc/hours-day-export.md | 25 +++++++++++++++++++++++++ frontend/data/documentation-content.ts | 9 +++++++++ 3 files changed, 35 insertions(+) create mode 100644 doc/hours-day-export.md diff --git a/CLAUDE.md b/CLAUDE.md index 9af7a88..513bda2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,6 +35,7 @@ - Employee contract history: `employee_contract_periods`, resolved by `EmployeeContractResolver` - **Écrans Heures / Heures Conducteurs (vue jour)** : le libellé nature (CDI/CDD/Intérim) sous le nom de l'employé est résolu **à la date filtrée** via `WorkHourDayContext.contractNature` (alimenté par `EmployeeContractResolver::resolveNatureForEmployeeAndDate`), pas via `Employee.currentContractNature` (qui est résolu à aujourd'hui). Idem pour le **mode de suivi (TIME/PRESENCE), les heures hebdo et le libellé de contrat** sur la vue Jour : résolus à la date filtrée via `WorkHourDayContext` (`trackingMode`/`weeklyHours`/`contractType`/`contractName`, peuplés depuis `EmployeeContractResolver::resolveForEmployeeAndDate`), pas via `employee.contract` (résolu à aujourd'hui). Côté front, `resolveDayContract()` (`useHoursPage.ts`) pilote l'affichage et `handleSave` (heures vs présence par date). - **Exports heures annuelles** (par salarié `EmployeeYearlyHoursPrintProvider` + tous `EmployeeYearlyHoursBulkPrintProvider`, via `YearlyHoursExportBuilder`) : **tous les jours sous contrat sont affichés**, même vides ou non saisis (jusqu'à aujourd'hui). Seuls les jours hors contrat sont omis (`buildSegments` : un seul filtre `!$hasData && null === $contract`). Ne pas réintroduire de saut des jours de semaine vides. Samedis/dimanches grisés (`#c0c0c0`) dans les templates `employee-yearly-hours/print*.html.twig`. NB : l'export *tous employés* sur l'année peut dépasser `memory_limit=256M` (Dompdf) — limitation pré-existante, voir avec l'infra si besoin. +- **Export heures vue Jour** (`WorkHourDayExportProvider`, endpoint `GET /work-hours/day-export?workDate=&siteIds=`, `ROLE_ADMIN`) : bouton « Exporter » à droite du titre « Heures ». PDF A4 portrait d'**une seule journée**, **regroupé par site**, colonnes de la vue Jour **sans « Valider »**. Mêmes employés que l'écran : non-conducteurs, sous contrat à la date, sites cochés (lignes vides incluses). Calcul des cellules mutualisé via `YearlyHoursExportBuilder::buildDayRowsForEmployees` (Jour/Nuit/Total incluent crédit absence + crédit virtuel férié). Gabarit `templates/work-hour-day-export/print.html.twig`. - **Écran Calendrier** : un employé est affiché uniquement si au moins une de ses périodes de contrat (`employee.contractHistory`) intersecte le mois affiché (`[1er ; dernier jour]`). Filtre côté frontend dans `visibleEmployees` (`pages/calendar.vue`). **L'impression PDF des absences applique le même filtre** côté backend (`AbsencePrintProvider::hasContractInRange` sur la période `[from, to]`) : un salarié parti en avril n'apparaît pas sur une impression de mai. **Le récap salaire applique le même filtre** (`SalaryRecapPrintProvider::hasContractInRange` sur le mois imprimé) : un salarié sans contrat sur le mois (ex. parti en février) n'apparaît pas sur le récap de juin. - **Planning jours travaillés** (`EmployeeContractPeriod.workDaysHours` : JSON `{iso_day: minutes}`) : obligatoire pour tout contrat TIME **hors 35h/39h/INTERIM** (ex. 4h, 25h, 28h). Somme = `weeklyHours × 60`. Utilisé par `HolidayVirtualHoursResolver` (crédit férié) et `WorkedHoursCreditPolicy` (crédit absence) pour ne créditer que les jours effectivement travaillés. Validation : `EmployeeContractPeriodValidator::assertWorkDaysHours`. - Absences: stored per day (auto-split), AM/PM/full day, clear corresponding hour slots diff --git a/doc/hours-day-export.md b/doc/hours-day-export.md new file mode 100644 index 0000000..e211204 --- /dev/null +++ b/doc/hours-day-export.md @@ -0,0 +1,25 @@ +# Export PDF des heures — vue Jour + +Bouton **Exporter** à droite du titre « Heures », visible **uniquement pour les +administrateurs** (`ROLE_ADMIN`). + +## Comportement +- Ouvre un drawer : un champ **date** (préremplit la date affichée) et des **cases à + cocher des sites** (présélectionnées sur le filtre courant). +- Génère un **PDF A4 portrait** d'une seule journée, **regroupé par site**. + +## Données +- Mêmes employés que la vue Jour : **non-conducteurs**, **sous contrat** à la date + choisie, des sites cochés. Les employés sous contrat sans saisie apparaissent (lignes + vides). +- Colonnes : Nom · Statut · Début matin · Fin matin · Début après-midi · Fin après-midi · + Début soir · Fin soir · Jour · Nuit · Total. **Pas de colonne « Valider ».** +- Jour / Nuit / Total : identiques à l'écran (crédit d'absence `countAsWorkedHours` et + crédit virtuel férié inclus). + +## Technique +- Endpoint : `GET /work-hours/day-export?workDate=YYYY-MM-DD&siteIds=1,2,3` (`ROLE_ADMIN`). +- Provider : `App\State\WorkHourDayExportProvider`. +- Calcul des cellules : `YearlyHoursExportBuilder::buildDayRowsForEmployees` (source + unique de vérité, partagée avec les exports annuels). +- Gabarit : `templates/work-hour-day-export/print.html.twig`. diff --git a/frontend/data/documentation-content.ts b/frontend/data/documentation-content.ts index 8b16866..74e6a39 100644 --- a/frontend/data/documentation-content.ts +++ b/frontend/data/documentation-content.ts @@ -81,6 +81,15 @@ export const documentationSections: DocSection[] = [ { type: 'list', content: 'Jour : total des heures dans la plage 06:00–21:00\nNuit : total des heures dans les plages 00:00–06:00 et 21:00–24:00\nTotal : somme des heures de jour et de nuit' }, ], }, + { + id: 'export-heures-jour', + title: 'Exporter les heures (PDF par jour)', + requiredLevel: 'admin', + blocks: [ + { type: 'paragraph', content: 'Le bouton « Exporter », à droite du titre « Heures », ouvre un panneau permettant de générer un PDF des heures d\'une journée. Choisissez la date et les sites concernés.' }, + { type: 'paragraph', content: 'Le PDF est organisé par site et reprend les colonnes de la vue Jour (nom, statut, horaires matin/après-midi/soir, jour, nuit, total), sans la colonne de validation. Les employés sous contrat ce jour-là apparaissent même sans saisie.' }, + ], + }, { id: 'commentaire-semaine', title: 'Commentaires de semaine (admin)',