[#SIRH-32] Ajouter l'exercice 2026/2027 dans les congés/RTT (#20)
Auto Tag Develop / tag (push) Successful in 9s
Auto Tag Develop / tag (push) Successful in 9s
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [x] Pas de régression - [x] TU/TI/TF rédigée - [x] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: #20 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #20.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# Afficher l'en-cours d'acquisition « net / brut » sur l'onglet Congés
|
||||
|
||||
**Date** : 2026-05-26
|
||||
**Ticket** : SIRH-32 (retour RH)
|
||||
**Statut** : design validé
|
||||
|
||||
## Contexte
|
||||
|
||||
Sur l'onglet **Congés** de la fiche employé, la case **« En cours d'acquisition »**
|
||||
affiche un seul nombre. Ce nombre est l'en-cours **net** : quand un salarié pose
|
||||
des congés **en anticipé** (au-delà de son report acquis), ces jours sont imputés
|
||||
sur la génération de l'exercice et **réduisent** l'en-cours affiché.
|
||||
|
||||
La RH a besoin de voir aussi le **total brut généré** sur l'exercice à ce jour,
|
||||
afin de connaître ce qui a réellement été acquis indépendamment de ce qui a déjà
|
||||
été consommé en anticipé.
|
||||
|
||||
Nouveau format demandé : `{net} / {brut}` — ex. `14,50 / 17,50`.
|
||||
|
||||
## Définitions (non-forfait, `CDI_CDD_NON_FORFAIT`)
|
||||
|
||||
Dans `EmployeeLeaveSummaryProvider::computeYearSummary` :
|
||||
|
||||
- `generatedDays` / `generatedSaturdays` = acquisition **brute** de l'exercice à
|
||||
ce jour (prorata mensuel, capée à aujourd'hui pour l'exercice courant).
|
||||
- `remainingToImpute` (+ samedis) = congés pris au-delà du report acquis, imputés
|
||||
sur la génération.
|
||||
- `accruingDays` (champ existant, **numérateur**) =
|
||||
`(generatedDays − remainingToImpute) + (generatedSaturdays − remainingSaturdaysToImpute)`
|
||||
→ en-cours **net**.
|
||||
- **Nouveau** : `accruingDaysTotal` (**dénominateur**) = `generatedDays + generatedSaturdays`
|
||||
→ brut généré à ce jour, avant imputation des congés anticipés.
|
||||
|
||||
Invariant : `accruingDays ≤ accruingDaysTotal`. La différence = jours pris en
|
||||
anticipé imputés sur la génération.
|
||||
|
||||
Côté **forfait** (`FORFAIT_218`) : pas d'acquisition « en cours »
|
||||
(`accruingDays = 0`) → `accruingDaysTotal = 0`.
|
||||
|
||||
## Changements
|
||||
|
||||
### 1. Backend
|
||||
|
||||
- `EmployeeLeaveSummaryProvider::computeYearSummary` : ajouter
|
||||
`accruingDaysTotal` au tableau retourné.
|
||||
- Branche non-forfait : `generatedDays + generatedSaturdays`.
|
||||
- Branche forfait : `0.0`.
|
||||
- `App\ApiResource\EmployeeLeaveSummary` : nouvelle propriété publique
|
||||
`float $accruingDaysTotal = 0.0`.
|
||||
- Le provider recopie `yearSummary['accruingDaysTotal']` dans
|
||||
`$summary->accruingDaysTotal` (à côté de `accruingDays`). Sur retour anticipé
|
||||
(`yearSummary === null`), la valeur reste `0.0` (comme `accruingDays`).
|
||||
|
||||
### 2. Frontend
|
||||
|
||||
- `frontend/services/dto/employee-leave-summary.ts` : ajouter
|
||||
`accruingDaysTotal: number`.
|
||||
- `frontend/components/employees/LeaveTab.vue`, case « En cours d'acquisition » :
|
||||
- **Non-forfait** : afficher `{{ formatCount(accruingDays) }} / {{ formatCount(accruingDaysTotal) }}`.
|
||||
- **Forfait** : inchangé (afficher `accruingDays` seul, soit `0`).
|
||||
- Réutiliser `isForfaitRule` (déjà présent) pour la condition.
|
||||
|
||||
### 3. Documentation
|
||||
|
||||
- `doc/leave-tab.md` : décrire le format `net / brut` de l'en-cours d'acquisition.
|
||||
- `frontend/data/documentation-content.ts` : note expliquant que l'en-cours
|
||||
affiche `net / total brut acquis` et que les congés anticipés réduisent le net.
|
||||
|
||||
## Comportements conservés
|
||||
|
||||
- Quand aucun congé anticipé n'est pris : numérateur = dénominateur
|
||||
(ex. `17,50 / 17,50`). C'est voulu — la RH veut le total visible en permanence.
|
||||
- Les autres compteurs du header (Année acquis, Pris, Reste à prendre, Samedis,
|
||||
N-1…) sont inchangés.
|
||||
- Aucun changement de calcul : `accruingDaysTotal` est une **exposition** d'une
|
||||
valeur déjà calculée (`generatedDays + generatedSaturdays`), pas une nouvelle
|
||||
règle métier.
|
||||
|
||||
## Hors périmètre
|
||||
|
||||
- Onglet RTT (pas d'en-cours d'acquisition).
|
||||
- Écran Récap congés (pas de colonne en-cours d'acquisition).
|
||||
- Header de la fiche employé (présence / jours à travailler) — inchangé.
|
||||
- Affichage de la fraction pour le forfait (pas d'en-cours → non pertinent).
|
||||
|
||||
## Tests
|
||||
|
||||
- Backend : ajouter un test sur `computeYearSummary` (via le harnais de tests
|
||||
existant du provider, par réflexion) vérifiant que `accruingDaysTotal` =
|
||||
`generatedDays + generatedSaturdays` et `≥ accruingDays` dans un cas avec congés
|
||||
anticipés. À défaut de chemin testable simple (collaborateurs `final`), couvrir
|
||||
l'arithmétique exposée et vérifier manuellement l'affichage.
|
||||
- Pas de harnais de test frontend ; vérification manuelle de l'affichage
|
||||
`net / brut` (non-forfait) et `0` (forfait).
|
||||
@@ -0,0 +1,118 @@
|
||||
# Proposer toujours l'exercice suivant dans les sélecteurs Congés et RTT
|
||||
|
||||
**Date** : 2026-05-26
|
||||
**Ticket** : SIRH-32
|
||||
**Statut** : design validé
|
||||
|
||||
## Contexte
|
||||
|
||||
Les onglets **Congés** et **RTT** de la fiche employé proposent un sélecteur
|
||||
d'exercice (`availableLeaveYears` / `availableRttYears`) dont la borne haute est
|
||||
plafonnée à l'**exercice courant**. La RH a commencé à poser des congés sur
|
||||
l'**exercice suivant**, mais ne peut pas le consulter dans la fiche employé :
|
||||
l'exercice suivant n'apparaît pas dans le menu déroulant.
|
||||
|
||||
On veut que le sélecteur propose **toujours** l'exercice suivant pour une phase
|
||||
de contrat ouverte, afin que ce besoin ne ressurgisse jamais.
|
||||
|
||||
## Faisabilité — déjà supportée côté backend
|
||||
|
||||
Aucun changement backend n'est nécessaire :
|
||||
|
||||
- `EmployeeLeaveSummaryProvider::clampYearToPhase` et son équivalent RTT ne
|
||||
plafonnent **pas** vers le haut quand la phase est ouverte (`phase.endDate`
|
||||
nul → `lastYear = null`). Une requête `?year=<exercice+1>&phaseId=<phase ouverte>`
|
||||
est donc déjà calculée correctement.
|
||||
- La validation `year` (2000–2100) couvre largement l'exercice suivant.
|
||||
|
||||
Le seul blocage est le **frontend**, qui calcule `maxYear = exercice courant`.
|
||||
|
||||
## Le changement
|
||||
|
||||
Frontend uniquement. Dans `frontend/composables/useEmployeeLeave.ts`
|
||||
(`availableLeaveYears`) et `frontend/composables/useEmployeeRtt.ts`
|
||||
(`availableRttYears`), la borne haute devient :
|
||||
|
||||
- **Phase ouverte** (pas de `phase.endDate`) :
|
||||
`maxYear = exercice courant + 1`.
|
||||
- **Phase clôturée** (`phase.endDate` présent) : **inchangé** →
|
||||
`maxYear = exercice de fin de phase` (on ne propose pas au-delà d'une phase
|
||||
terminée).
|
||||
|
||||
Le `+1` porte sur le **numéro d'exercice**, donc il est correct pour le forfait
|
||||
(année civile) comme pour le non-forfait (Juin N-1 → Mai N), via
|
||||
`computeLeaveYearForDate` / `computeRttYearForDate`.
|
||||
|
||||
### Pseudo-code de la borne
|
||||
|
||||
```
|
||||
maxYear = phase.endDate
|
||||
? computeYearForDate(phase.endDate) // phase clôturée : cap à la fin de phase
|
||||
: currentYear + 1 // phase ouverte : on propose l'exercice suivant
|
||||
```
|
||||
|
||||
La borne basse (`minYear = max(phaseStartYear, dataFloor)`) est **inchangée**.
|
||||
|
||||
## Comportements conservés
|
||||
|
||||
- **Sélection par défaut** : inchangée. L'onglet s'ouvre toujours sur l'exercice
|
||||
**courant** ; l'exercice suivant est seulement disponible dans le menu (pas de
|
||||
saut automatique sur le futur). `initSelected*Year` continue d'initialiser sur
|
||||
`current*Year`, qui reste dans la plage `[minYear ; maxYear]`.
|
||||
- **Verrouillage des éditions** : `isHistoricalYear` (`selectedYear !== currentYear`)
|
||||
reste tel quel. Sur l'exercice suivant, les boutons **Jours fractionnés**,
|
||||
**Année N-1 payés** (onglet Congés) et **+ Payer les RTT** (onglet RTT) sont
|
||||
**désactivés** — souhaitable : pas d'édition de stocks ni de paiement sur un
|
||||
exercice pas encore démarré.
|
||||
- **Aucune mention « passé » trompeuse** : le bandeau « Vous consultez
|
||||
l'historique » est piloté par la phase (`isViewingPastPhase`), pas par l'année
|
||||
sélectionnée ; sélectionner un exercice futur ne l'affiche pas.
|
||||
|
||||
## Affichage des congés posés sur l'exercice suivant (réponse Q1)
|
||||
|
||||
Le header congés (grille de compteurs de l'onglet + libellé présence du header
|
||||
de fiche) reflète **le récap de l'exercice sélectionné**. Chaque récap est
|
||||
calculé sur sa fenêtre `[from, to]` ; les absences/jours pris ne sont comptés que
|
||||
dans cette fenêtre.
|
||||
|
||||
- **Sur l'exercice courant** (vue par défaut) : les congés posés sur l'exercice
|
||||
suivant **n'apparaissent pas** dans les compteurs — comportement correct.
|
||||
- **Sur l'exercice suivant** (sélectionné) : ils s'affichent (calendrier +
|
||||
compteur « Pris »).
|
||||
|
||||
### Caveat fonctionnel
|
||||
|
||||
Sur l'exercice suivant, les compteurs **report / Année N-1 / reste** sont
|
||||
**provisoires** jusqu'à la clôture de l'exercice courant (ils en dépendent). En
|
||||
revanche, le **« Pris » et le calendrier** des congés posés sont exacts. À
|
||||
communiquer à la RH.
|
||||
|
||||
## Périmètre
|
||||
|
||||
- Onglet **Congés** et onglet **RTT** (les deux sélecteurs partagent la même
|
||||
mécanique).
|
||||
- Forfait (année civile) et non-forfait (Juin→Mai).
|
||||
|
||||
## Hors périmètre
|
||||
|
||||
- Aucune modification de la mécanique de saisie d'absences (la RH pose déjà des
|
||||
congés sur l'exercice suivant via les écrans Calendrier / Heures, indépendamment
|
||||
de ce sélecteur).
|
||||
- Pas de proposition de plusieurs exercices futurs (un seul : N+1).
|
||||
- Pas d'activation des éditions de stocks/paiement sur l'exercice futur.
|
||||
|
||||
## Documentation à mettre à jour (règle obligatoire CLAUDE.md)
|
||||
|
||||
- `doc/leave-tab.md` — plage du sélecteur.
|
||||
- `doc/rtt-tab.md` — plage du sélecteur.
|
||||
- `CLAUDE.md` — sections « Onglet Congés » et « Onglet RTT » (description de la
|
||||
plage `max(...)` → borne haute `exercice courant + 1` sur phase ouverte).
|
||||
- `frontend/data/documentation-content.ts` — documentation in-app.
|
||||
|
||||
## Tests
|
||||
|
||||
Pas de harnais de test frontend dans le projet (backend PHPUnit uniquement). La
|
||||
modification est de la logique de calcul de plage dans deux `computed` :
|
||||
vérification manuelle (dev Nuxt) que l'exercice suivant apparaît dans les deux
|
||||
sélecteurs pour une phase ouverte, et n'apparaît pas pour une phase clôturée. Les
|
||||
tests backend existants doivent rester verts (aucun changement backend).
|
||||
Reference in New Issue
Block a user