Files
SIRH/doc/leave-rollover.md
tristan f493ea237b
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Ajout des notification + page employé (#6)
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

- [ ] Pas de régression
- [ ] TU/TI/TF rédigée
- [ ] TU/TI/TF OK
- [ ] CHANGELOG modifié

Reviewed-on: #6
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-03-10 12:35:17 +00:00

7.3 KiB

Rollover Conges - Regles et Mise en Production

Document de reference pour expliquer le fonctionnement metier du report N-1 et preparer le lancement en production.

1) Objectif

Eviter les recalculs "depuis le debut du contrat" et fiabiliser les soldes.

Principe:

  • le solde est stocké par exercice
  • au changement d'exercice, on ouvre la nouvelle période avec un "solde d'ouverture" (report N-1)
  • un indicateur de cloture (contractPaidLeaveSettled) permet de couper la continuité entre 2 contrats

2) Exercices metier

  • CDI / CDD non forfait:
    • exercice: 1er juin au 31 mai
    • year = annee de fin d'exercice (ex: 2026 = 01/06/2025 -> 31/05/2026)
  • FORFAIT:
    • exercice: 1er janvier au 31 decembre
    • year = annee civile
  • INTERIM:
    • hors perimetre conges

3) Logique de compteurs

  • acquis:
    • correspond au report N-1 (solde d'ouverture)
  • en cours d'acquisition:
    • correspond aux droits generes sur l'exercice en cours
  • pris:
    • non forfait: absences type C (conge)
    • forfait: toutes absences
  • restant:
    • acquis + en_cours - pris (borne a 0 dans l'affichage)

4) Effet du "solde de tout compte"

Le champ de cloture contractPaidLeaveSettled est saisi lors de la fermeture d'une periode contrat.

  • false:
    • continuite des droits entre contrats
  • true:
    • pas de reprise des droits precedents
    • reset de continuite au lendemain de la date de cloture

5) Table cible

Table employee_leave_balances (une ligne par employe et exercice):

  • employee_id
  • rule_code (CDI_CDD_NON_FORFAIT ou FORFAIT_218)
  • year
  • opening_days
  • opening_saturdays
  • accrued_days
  • accrued_saturdays (optionnel selon implementation)
  • taken_days
  • taken_saturdays
  • closing_days
  • closing_saturdays
  • is_locked
  • created_at, updated_at

Contrainte unique recommandee:

  • (employee_id, rule_code, year)

Etat implementation:

  • la table est creee
  • le calcul de synthese conges lit en priorite opening_days/opening_saturdays de cette table quand une ligne existe pour (employee, rule_code, year)
  • si aucune ligne n'existe, le calcul reste base sur le report dynamique N-1
  • la commande app:leave:rollover calcule aussi le report dynamique N-1 si la ligne N-1 n'est pas encore persistée (pas de reset a 0 par defaut)

Definition des colonnes

  • employee_id:
    • identifiant employe (FK vers employees)
    • une ligne de solde par employe / regle / exercice
  • rule_code:
    • code de regle appliquee (CDI_CDD_NON_FORFAIT, FORFAIT_218)
    • permet de savoir quelles regles de calcul sont utilisees
  • year:
    • annee d'exercice
    • non forfait: annee de fin d'exercice (2026 = 01/06/2025 -> 31/05/2026)
    • forfait: annee civile (2026 = 01/01/2026 -> 31/12/2026)
  • opening_days:
    • report N-1 en jours (solde d'ouverture)
  • opening_saturdays:
    • report N-1 "samedis" (0 pour forfait)
  • accrued_days:
    • droits generes sur l'exercice courant (N)
  • accrued_saturdays:
    • droits samedis generes sur N (0 pour forfait)
  • taken_days:
    • jours poses sur l'exercice
  • taken_saturdays:
    • samedis poses sur l'exercice (0 pour forfait)
  • closing_days:
    • solde de cloture jours (opening_days + accrued_days - taken_days)
  • closing_saturdays:
    • solde de cloture samedis (opening_saturdays + accrued_saturdays - taken_saturdays)
  • is_locked:
    • false sur exercice ouvert (recalcul possible)
    • true apres validation RH (exercice fige)
  • created_at, updated_at:
    • trace technique creation / mise a jour

6) Rollover automatique

Commande quotidienne (cron) idempotente.

  • commande Symfony: php bin/console app:leave:rollover
  • comportement date metier:
    • le 01/01: traite uniquement FORFAIT_218
    • le 01/06: traite uniquement CDI_CDD_NON_FORFAIT
    • les autres jours: sortie sans action
  • option manuelle: --force pour executer hors date metier (reprise/correction)

Date d'effet:

  • forfait: au 1er janvier
  • non forfait: au 1er juin

Traitement par employe:

  1. lire l'exercice precedent
  2. determiner le report:
    • si cloture paidLeaveSettled=true sur la periode precedente => report 0
    • sinon report = closing exercice precedent
  3. creer la ligne du nouvel exercice avec ce report en opening_*
  4. initialiser accrued/taken/closing pour le nouvel exercice

7) Donnees a fournir au go-live

La RH doit fournir un import d'ouverture:

Colonnes minimales:

  • employee_identifier (id interne ou matricule)
  • rule_code
  • year
  • opening_days
  • opening_saturdays (0 pour forfait)
  • source_date (date de reference du relevé RH)
  • comment (optionnel)

Format recommande:

  • CSV UTF-8
  • separateur ;
  • decimales en point (7.5)

Exemple:

employee_id;rule_code;year;opening_days;opening_saturdays;source_date;comment
42;CDI_CDD_NON_FORFAIT;2026;12.5;2;2026-05-31;Reprise fichier RH
17;FORFAIT_218;2026;8;0;2025-12-31;Reprise fichier RH

8) Checklist mise en prod

  1. Valider le mapping employe RH -> employe applicatif
  2. Importer les soldes d'ouverture N-1
  3. Verifier 5 cas metier:
    • CDI simple sans changement de contrat
    • CDD -> CDI avec paidLeaveSettled=false
    • CDD -> CDI avec paidLeaveSettled=true
    • Forfait sur annee complete
    • Forfait avec debut en cours d'annee
  4. Activer le cron de rollover
  5. Geler (is_locked) les exercices historicises valides

Exemple cron (tous les jours a 02:10): Dev

10 2 * * * cd /var/www/html && php bin/console app:leave:rollover --no-interaction 2>&1

Prod

10 2 * * * cd /var/www/sirh && php bin/console app:leave:rollover --no-interaction 2>&1

Explication de la ligne cron:

  • 10 2 * * *: planification
    • 10 = minute
    • 2 = heure
    • * = tous les jours du mois
    • * = tous les mois
    • * = tous les jours de la semaine
  • cd /var/www/html: se place dans le dossier de l application Symfony
  • php bin/console app:leave:rollover --no-interaction: execute le rollover sans demander de confirmation
    • hors 01/01 et 01/06, la commande sort en no-op (normal)
  • >> var/log/leave-rollover.log: ajoute la sortie standard dans le fichier de log (sans ecraser l historique)
  • 2>&1: redirige aussi les erreurs dans le meme fichier de log

Execution manuelle forcee:

php bin/console app:leave:rollover --force --no-interaction

Exemple de verification rapide:

tail -n 50 /var/www/html/var/log/leave-rollover.log

9) Points de vigilance

  • Ne jamais recalculer les soldes historiques apres validation RH sans procedure explicite
  • Garder une trace de toute correction manuelle (auteur, date, motif)
  • Aligner strictement les regles UI et API sur les memes compteurs (pas de formule differente front/back)

10) Regle de consommation des droits

Regle metier:

  • un employe peut poser des conges en cours d'acquisition
  • la consommation se fait par ordre:
    1. acquis (report N-1)
    2. en cours d'acquisition (droits N)

Effet attendu:

  • si acquis = 0 et en cours = 7.5, puis prise de 7, alors:
    • acquis reste 0
    • en cours devient 0.5
  • si acquis = 0 et en cours = 2.5, puis prise de 3, alors:
    • acquis reste 0
    • en cours devient -0.5 (dette)
    • le mois suivant, une acquisition de 2.5 ramené en cours a 2.0

Formule de lecture recommandée:

  • restant_acquis = max(0, acquis - pris)
  • reste_a_imputer_sur_en_cours = max(0, pris - acquis)
  • restant_en_cours = en_cours - reste_a_imputer_sur_en_cours (valeur negative autorisee)