Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
| 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>
227 lines
7.3 KiB
Markdown
227 lines
7.3 KiB
Markdown
# 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:
|
|
```csv
|
|
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
|
|
```cron
|
|
10 2 * * * cd /var/www/html && php bin/console app:leave:rollover --no-interaction 2>&1
|
|
```
|
|
Prod
|
|
```cron
|
|
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:
|
|
```bash
|
|
php bin/console app:leave:rollover --force --no-interaction
|
|
```
|
|
|
|
Exemple de verification rapide:
|
|
```bash
|
|
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)
|