cf492f40a4
La RH peut désormais saisir un paiement RTT sur l'exercice immédiatement précédent (ex. RTT de mai réglés après la bascule du 1er juin), sans casser le report. - gate back (assertYearAllowedForPayment) : accepte courant, N-1, ou dernier exercice d'une phase clôturée - après saisie sur N-1, recalcul automatique du report d'ouverture de l'exercice courant (computeClosingBalance) dans une transaction → pas de double comptage - refus si le report de l'exercice courant est verrouillé (assertReportNotLocked) - fallback EmployeeRttSummaryProvider::resolveCarry passe sur computeClosingBalance : disponible correct même sans ligne stockée - front : bouton + Payer les RTT actif sur l'exercice précédent - docs : CLAUDE.md, doc/rtt-tab.md, documentation-content.ts Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72 lines
5.0 KiB
Markdown
72 lines
5.0 KiB
Markdown
# Onglet "RTT" — fiche employé
|
||
|
||
## Vue d'ensemble
|
||
|
||
L'onglet **RTT** de la fiche employé (`frontend/components/employees/RttTab.vue`) affiche un tableau hebdomadaire détaillé des heures supplémentaires accumulées et payées sur un exercice :
|
||
- bandeau de navigation par mois (chevrons gauche/droite) ;
|
||
- table semaine par semaine : Heure / Base 25% / 25% / Total 25% / Base 50% / 50% / Total 50% / Total / Cumul ;
|
||
- ligne Report (carry N-1 ou cumul mois précédents) ;
|
||
- ligne Total mois, ligne Payé, ligne Reste ;
|
||
- bouton « + Payer les RTT » dans le bandeau ;
|
||
- sélecteur d'exercice en pied de tableau.
|
||
|
||
L'onglet est **masqué pour les contrats FORFAIT** (filtre `showRttTab` dans `useEmployeeDetailPage`). Les FORFAIT n'accumulent pas de RTT.
|
||
|
||
## Période affichée
|
||
|
||
Toujours **Juin (Y-1) → Mai (Y)**. Le champ `EmployeeRttSummary.year` correspond à `Y` (année de fin d'exercice) ; ex. `year=2026` = `01/06/2025 → 31/05/2026`.
|
||
|
||
## Sélecteur d'année
|
||
|
||
Position : sous la table, à l'intérieur de la zone scrollable, à gauche.
|
||
|
||
Plage proposée :
|
||
- du plus récent (= exercice courant) au plus ancien. Contrairement à l'onglet Congés, le RTT **ne propose pas** l'exercice suivant (consulter un exercice RTT à venir n'a pas de sens) ; pour une phase clôturée, la borne haute reste l'exercice de fin de phase ;
|
||
- **double plancher** : `max(floor_historique_contrat, floor_data_start_date)`
|
||
- **floor_historique_contrat** : dérivé de `employee.contractHistory[].startDate` — premier exercice où l'employé avait un contrat ouvert
|
||
- **floor_data_start_date** : exercice contenant `RTT_START_DATE` (env, ex. `2026-02-23` → exercice 2026)
|
||
- la valeur est exposée par l'API `GET /employees/{id}/rtt-summary` via le champ `rttStartDate` (déjà existant — mais peuplé uniquement quand la date tombe dans l'exercice retourné, donc le composable utilise la première réponse pour borner la plage).
|
||
- format unique : `Juin 2025 → Mai 2026`, `Juin 2024 → Mai 2025`…
|
||
|
||
Comportement :
|
||
- changer d'exercice recharge `getEmployeeRttSummary?year=YYYY` (le backend valide 2000–2100) ;
|
||
- la table redéploie les semaines de l'exercice sélectionné, navigation par mois conservée.
|
||
|
||
## Verrouillage des éditions sur exercices passés
|
||
|
||
Quand `selectedYear !== currentYear` (consultation d'un exercice antérieur), le bouton **+ Payer les RTT** est désactivé — **sauf sur l'exercice immédiatement précédent** (`selectedYear === currentYear - 1`), où le paiement rétroactif est autorisé (Option B).
|
||
|
||
La consultation des exercices plus anciens reste possible, l'édition non.
|
||
|
||
### Paiement rétroactif sur l'exercice précédent (Option B)
|
||
|
||
Un paiement enregistré sur l'exercice N-1 modifie sa clôture, donc le **report d'ouverture de l'exercice courant N**. Pour éviter tout décalage / double comptage :
|
||
|
||
- garde back `EmployeeRttPaymentProcessor::assertYearAllowedForPayment` : accepte courant, **N-1**, ou dernier exercice d'une phase clôturée ;
|
||
- après enregistrement, le processor **recalcule automatiquement** la ligne `employee_rtt_balances` de l'exercice courant via `RttClosingBalanceService::computeClosingBalance(N-1)`, dans une **transaction** (le `flush` du paiement le rend visible au recalcul) ;
|
||
- si le report de l'exercice courant est **verrouillé** (`is_locked`), le paiement est **refusé** (`assertReportNotLocked`) : la RH doit déverrouiller d'abord ;
|
||
- portée volontairement limitée à N-1 (chaîne de recalcul = 1 étape). Si la ligne courante n'existe pas encore, l'affichage reste correct grâce au fallback de `EmployeeRttSummaryProvider::resolveCarry` (calcul dynamique de la clôture N-1).
|
||
|
||
## Sélecteur de phase de contrat
|
||
|
||
L'onglet RTT est visible quand la **phase de contrat sélectionnée** n'est pas FORFAIT (et non pas le contrat courant). Concrètement, sur un employé passé en FORFAIT après une période 39h :
|
||
- En vue `FORFAIT` (défaut), l'onglet RTT est masqué.
|
||
- En vue `39h` (phase passée sélectionnée via le picker `Vue contrat`), l'onglet RTT redevient visible avec les exercices Juin→Mai bornés à la phase.
|
||
|
||
Le bouton `+ Payer les RTT` est activé uniquement sur le **dernier exercice de la phase passée** (l'exercice contenant `phase.endDate`). Les exercices antérieurs sont en lecture seule.
|
||
|
||
Cf. `doc/contract-phase-view.md` pour les détails complets.
|
||
|
||
## Implémentation
|
||
|
||
- Composable : `frontend/composables/useEmployeeRtt.ts`
|
||
- État : `selectedRttYear`, computed `currentRttYear`, `availableRttYears`
|
||
- API : `setSelectedRttYear(year)`, `loadRttData()`, `resetLoaded()`
|
||
- `resetLoaded()` (appelé au changement d'employé) remet `selectedRttYear = null`.
|
||
- Composant : `frontend/components/employees/RttTab.vue`
|
||
- Props : `selectedYear`, `availableYears`, `currentYear`
|
||
- Event : `update-selected-year`
|
||
- Renommage `currentYear` (computed local de l'année du mois affiché) → `displayedMonthYear` pour éviter la collision avec la nouvelle prop.
|
||
- Page : `frontend/pages/employees/[id].vue`
|
||
- Backend : aucun changement — `EmployeeRttSummaryProvider` accepte déjà `?year=YYYY` (validation 2000–2100) et expose `rttStartDate`.
|