From 387cff22933402acec425d5debcbae2b607e3815 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 1 Jun 2026 21:37:26 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20spec=20vue=20jour=20r=C3=A9solution=20c?= =?UTF-8?q?ontrat=20=C3=A0=20la=20date=20affich=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- ...-day-view-per-date-tracking-mode-design.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-01-day-view-per-date-tracking-mode-design.md diff --git a/docs/superpowers/specs/2026-06-01-day-view-per-date-tracking-mode-design.md b/docs/superpowers/specs/2026-06-01-day-view-per-date-tracking-mode-design.md new file mode 100644 index 0000000..a13fc0d --- /dev/null +++ b/docs/superpowers/specs/2026-06-01-day-view-per-date-tracking-mode-design.md @@ -0,0 +1,88 @@ +# 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 : + +1. d'exposer sur la ligne du jour les champs de contrat manquants ; +2. 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 + +1. **`src/Dto/WorkHours/DayContextRow.php`** — ajouter 4 champs au constructeur et à + `toArray()` (+ mettre à jour le PHPDoc du retour de `toArray()`) : + - `trackingMode: ?string` + - `weeklyHours: ?int` + - `contractType: ?string` + - `contractName: ?string` + +2. **`src/State/WorkHourDayContextProvider.php`** — peupler ces champs depuis le + `$contract` déjà résolu (lignes 60-71) : + - `trackingMode` = `$contract?->getTrackingMode()` + - `weeklyHours` = `$contract?->getWeeklyHours()` + - `contractType` = `$contract?->getType()->value` + - `contractName` = `$contract?->getName()` + - tous `null` si pas de contrat à la date (cohérent avec `hasContractAtDate`). + +### Frontend + +3. **`frontend/services/dto/work-hour.ts`** — refléter les 4 champs sur + `WorkHourDayContextRow`. + +4. **`frontend/composables/useHoursPage.ts`** — `isPresenceTracking`, `isTimeTracking`, + `contractLabel`, `is4hContract` lisent le `dayContextByEmployeeId.get(employeeId)` + (résolu par date), avec **fallback** sur `employee.contract` si aucune ligne du jour + n'existe. Cela corrige automatiquement `handleSave` (ligne 1073), qui s'appuie sur + `isPresenceTracking`. + + Les signatures actuelles prennent un `Employee` ; on conserve la signature et on + utilise `employee.id` en 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 porte `trackingMode=TIME`/`weeklyHours=39`/ + `contractType` non-forfait sur une date **avant** la bascule, et + `trackingMode=PRESENCE`/`contractType=FORFAIT` sur 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ésout `trackingMode`/libellé **à la date + filtrée** (au même titre que `contractNature` déjà documenté).