Files
SIRH/doc/rtt-tab.md
T
tristan cf492f40a4 feat(rtt) : autoriser le paiement RTT rétroactif sur l'exercice précédent
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>
2026-06-08 13:39:11 +02:00

5.0 KiB
Raw Blame History

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 20002100) ;
  • 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 20002100) et expose rttStartDate.