4.8 KiB
PTA V7.15 — Les affectations sont bornées par le contrat de l’agent
Le problème traité
La fiche agent portait date_debut_contrat et date_fin_contrat depuis l’origine — saisies,
contrôlées l’une par rapport à l’autre, affichées dans les écrans et les PDF. Mais aucun contrôle
de planification ne les lisait : rien n’empêchait de planifier un agent trois mois avant son
arrivée, ou un contrat temporaire l’année suivant son départ.
Les conséquences n’étaient pas cosmétiques : ces heures entraient dans les cumuls annuels, dans le quota, dans les contrôles de couverture — un lieu pouvait passer pour couvert par un agent qui n’était pas encore embauché.
Ce qui change
1. Toute écriture de créneau est bornée
La règle est posée sur tous les chemins qui créent ou déplacent une affectation :
| Chemin | Ce qui est contrôlé |
|---|---|
| Enregistrement d’un brouillon | Chaque date saisie |
| Modification d’un créneau (fiche agent) | La nouvelle date |
| Déplacement / duplication d’un créneau | La date cible |
| Copie d’une semaine entière | Les cinq jours ouvrés de la semaine cible |
| Application d’une semaine type | Les cinq jours ouvrés de la semaine visée |
| Duplication sur une période | Les deux bornes de la période |
Le refus est un 422 portant code: HORS_CONTRAT, la liste des dates refusées, et une phrase qui
nomme la période réellement couverte :
Marc Louis n’est pas sous contrat à cette période : son contrat court à partir du 04/05/2026. Date(s) refusée(s) : 02/03/2026.
La règle vaut pour tous les motifs, congés et absences compris : hors contrat, il n’y a rien à décompter.
Une borne absente ouvre, elle ne ferme jamais : pas de date de fin signifie contrat à durée indéterminée ; pas de date de début (fiche ancienne) signifie qu’aucune borne basse n’est opposée, plutôt que d’inventer une date.
2. La validation révèle les affectations déjà hors contrat
Les gardes ci-dessus empêchent d’en créer de nouvelles ; elles ne disent rien de celles qui
existaient avant. Un contrôle bloquant HORS_CONTRAT rejoint donc les quatre contrôles de
validation existants, à la validation d’une semaine comme à celle d’une année entière :
L’affectation #824 du 2026-05-11 est en dehors des dates de contrat de l’agent.
La comparaison est faite en SQL sur la fiche agent jointe : c’est l’état du contrat au moment du contrôle qui fait foi.
3. Le contrat ne peut plus glisser sous des affectations existantes
Contrôle miroir, sans lequel le premier ne servirait à rien : modifier les dates de contrat d’un agent est refusé si cela laisserait des affectations au-dehors. Le message dit combien et sur quelle période, pour qu’on sache quoi retirer :
Ces dates de contrat laisseraient 6 affectation(s) en dehors du contrat, entre le 11/05/2026 et le 14/08/2026. Supprimez-les d’abord, ou élargissez les dates.
Vérifications effectuées
Onze cas exécutés sur la pile, tous conformes : saisie avant le début de contrat (refusée), dans le contrat (acceptée), sur la semaine à cheval contenant le premier jour (acceptée), copie de semaine hors contrat, saisie après la date de fin, déplacement et modification de créneau vers une date hors contrat, raccourcissement de contrat sous des affectations existantes, contrôle de validation sur une donnée devenue illégitime, application d’une semaine type sur une semaine puis sur une période hors contrat.
Fichiers
| Fichier | Rôle |
|---|---|
app/Models/AgentModel.php |
contractRange(), contractCoversDate(), datesOutsideContract(), contractViolationMessage(), entriesOutsideContract() |
app/Controllers/PlanningController.php |
Garde sur les quatre chemins d’écriture, contrôle de validation |
app/Controllers/WeekTemplateController.php |
Garde sur l’application à une semaine et sur une période |
app/Controllers/AnnualOverviewController.php |
Même contrôle à la validation annuelle |
app/Controllers/AgentController.php |
Refus d’un contrat qui orphelinerait des affectations |
app/Models/PlanningModel.php |
entriesOutsideContract() pour le contrôle de validation |
Aucune migration : les colonnes existent depuis le socle, seule leur exploitation change.
Point d’attention
La garde est dupliquée dans PlanningController et WeekTemplateController, faute de base
commune entre contrôleurs — comme l’est déjà parseWeek(). Ce qui n’est pas dupliqué, c’est le
message : il est construit par AgentModel::contractViolationMessage(), pour que l’utilisateur lise
la même phrase quel que soit l’écran. Toute nouvelle voie d’écriture de créneaux doit poser la même
garde — le contrôle de validation n’est qu’un filet, pas un substitut.