d201489bcb
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2.6 KiB
2.6 KiB
Notification de fin de contrat (veille du dernier jour)
Objectif
Prévenir les administrateurs, sur le dernier jour ouvré précédant la fin d'un contrat, qu'un salarié arrive au terme de son emploi.
Déclenchement
Commande app:contract:end-notifications, lancée chaque jour par le crontab de production
(ex. 0 6 * * *). Option --date=YYYY-MM-DD pour test/rattrapage. Logger cron.
Règle métier
- Cible : la dernière période de contrat d'un employé (aucune période ne lui succède). Un changement de contrat enchaîné (ex. CDD → CDI) ne notifie pas.
- Quand : sur le dernier jour ouvré strictement avant
endDate(endDateest inclusif = dernier jour travaillé). Les week-ends ET jours fériés (PublicHolidayService, zonemetropole) sont sautés. Concrètement, le jour J ouvré couvre les fins de contrat dans l'intervalle]J ; prochain_jour_ouvré(J)]— un vendredi notifie ainsi les fins du samedi, dimanche et lundi (mardi si lundi férié). - Jour de solidarité (Lundi de Pentecôte) : traité comme un jour ouvré (choix
délibéré). Le calcul s'appuie sur
getHolidaysDayByYears, qui appliqueEXCLUDED_PUBLIC_HOLIDAYS(défaut ="Lundi de Pentecôte") — la même liste de fériés que le reste de l'app (heures, congés, RTT). On évite ainsi une définition de « férié » divergente pour ce seul calcul ; et le jour de solidarité est, par nature, un jour travaillé (admins présents → la cloche est vue). Une fin de contrat le mardi après Pentecôte est donc notifiée le Lundi de Pentecôte, pas le vendredi précédent. - Destinataires : tous les
ROLE_ADMIN. - Message :
Fin de {CDI|CDD|Intérim} de {Prénom Nom} le {dd/mm/yyyy}, catégorieContrat, cible/employees/{id}, sans acteur.
Idempotence
Avant création, on vérifie l'absence d'une notif identique
(recipient, category='Contrat', target, message). Le message étant unique par
(employé + date + nature), relancer la commande le même jour ne crée aucun doublon.
Implémentation
App\Service\Notification\WorkingDayCalculator— jour ouvré / prochain jour ouvré.App\Service\Notification\ContractEndNotificationPlanner— sélection + message (pur, testé).App\Service\Notification\ContractEndNotificationService— persistance (1 notif/admin).App\Command\ContractEndNotificationCommand—app:contract:end-notifications.EmployeeContractPeriodRepository::findLatestPeriodsForAllEmployees,NotificationRepository::existsForRecipientCategoryTargetMessage.- Pas de migration : réutilise la table
notifications.