# Requalification Phase 2.1 — prérequis métier et interface

Date : 2026-08-23  
Version auditée initialement : 0.1.0-dev.8 ; correction catalogue : 0.1.0-dev.10

## Conclusion

La validation précédente est requalifiée **PARTIELLEMENT VALIDÉE**. Les
services de planification sont testés, mais le scénario préventif annoncé
n'était pas reproductible par un administrateur depuis l'interface : les
données `TEST_UI_PHASE21_*` persistées dans la copie VM ont été préparées par
SQLAlchemy/script (et les tests utilisent des fixtures). Aucun lot ni
équipement marqué Phase 2.1 n'était présent dans la base contrôlée. Une
fixture passante ne constitue donc pas une validation du parcours utilisateur.

## Audit des données Phase 2.1

| Donnée | Mode constaté | Parcours UI identifié | Validation métier |
|---|---|---|---|
| `TEST_UI_PHASE21_TECH` et horaires | SQLAlchemy/script puis fixtures | `/planning/time` existait pour l'utilisateur courant | Partielle |
| salles et occupations | script/fixtures | planning des salles | Partielle |
| tâches planifiées, urgence, entreprise | script/fixtures | routes normales disponibles | Partielle |
| lot, tâche de lot, équipements | aucune donnée marqueur dans la copie VM | assistant équipement + détail du lot + `/lots/<id>/tasks/new` | Non validée |

Le précédent rapport doit être lu comme une validation technique du moteur, et
non comme une preuve de configuration UI. La cause est méthodologique : le
scénario a été construit directement en base pour tester l'algorithme avant de
vérifier chaque écran de configuration.

## Horaires par technicien

`WorkSchedule.user_id` et `WorkScheduleTemplate.user_id` rattachent déjà les
plages à un utilisateur. Avant cette passe, `/planning/time` ne permettait
cependant de gérer que l'utilisateur connecté et `PlanningService` choisissait
une plage globale lorsqu'aucun utilisateur n'était filtré. Cette contamination
était incompatible avec deux techniciens.

La correction minimale appliquée :

- sélection du technicien dans `/planning/time` pour un administrateur ou un
  détenteur de `planning.manage` ;
- requêtes horaires, absences et formations filtrées par `user_id` ;
- `DayPlanner` reçoit explicitement l'utilisateur ;
- sans horaire explicite pour cet utilisateur, aucune journée 08:00–17:00
  implicite n'est créée ; l'écran affiche une aide et un lien de configuration ;
- les tâches administratives peuvent être rattachées à un utilisateur (`NULL`
  conserve les anciennes tâches globales).

Le modèle permet plusieurs plages dans une journée via `lunch_start/lunch_end`
et des jours différents via `day_of_week`. Les pauses sont donc représentées
comme une coupure de la plage. La page affiche les horaires appliqués et la
personne concernée. Les fermetures du collège restent globales ; les congés,
formations (`TrainingParticipant`) et indisponibilités
(`TechnicianAvailability`) sont filtrés par technicien.

Test automatisé ajouté : deux utilisateurs avec 08:00–17:00 et 07:00–15:30
obtiennent chacun exclusivement leurs horaires.

## Lots et préventif

La relation réelle est directe : `Equipment.lot_id -> Lot.id`, avec héritage
possible par équipement parent (`effective_lot_id`). Un lot possède des
`LotTask`; la tâche contient `duree_minutes`, `periodicite` et les paramètres de
génération. Les formulaires équipement permettent de choisir un lot et
l'assistant équipement expose une création rapide de lot. Le détail du lot
permet d'ajouter une tâche. Il n'existe pas de route autonome `/lots/new` : la
création initiale passe par l'assistant, désormais indiqué depuis la liste des
lots.

La durée et la périodicité sont donc des champs UI de `LotTask`. Attention :
`LotTask.effective_duration()` ne fabrique plus une durée de 60 minutes si
aucune durée n'est saisie : la tâche est signalée comme à renseigner. La génération
préventive complète depuis un lot et deux équipements n'a pas été rejouée via
UI dans cette passe : elle reste **NON VALIDÉE**.

## Matrice des prérequis de Ma journée

| Donnée | Rattachement | Création/modification UI | Utilisé par DayPlanner | Statut |
|---|---|---|---|---|
| Technicien | `User` | utilisateurs | oui | disponible |
| Horaires / pauses | `WorkSchedule.user_id` | `/planning/time` | oui | corrigé et testé |
| Congés | `PersonalLeave.user_id` | planning | oui | filtré |
| Formation | `TrainingParticipant.user_id` | planning | oui | filtré |
| Indisponibilité | `TechnicianAvailability.user_id` | planning | oui | filtré |
| Fermeture | `CollegeClosure` | administration | oui, globale | disponible |
| Salle/occupation | Room/RoomSchedule | planning salles | oui | disponible |
| Lot/tâche | `Lot`, `LotTask` | assistant + détail lot | via génération | UI à rejouer |
| Équipement | `Equipment.lot_id`, localisation | équipements | via préventif | UI à rejouer |
| Durée/périodicité | `LotTask` | tâche de lot | oui | disponible, fallback 60 à clarifier |
| Intervention | `Intervention` | interventions | oui | disponible |
| Tâche administrative | `AdminTask.user_id` | `/planning/admin-tasks` | oui | corrigé |
| Entreprise extérieure | rendez-vous planning | planning | oui | disponible |
| Urgence | intervention/candidat | interventions | oui | disponible |

## Fallbacks détectés

- fallback historique 08:00–17:00 : supprimé pour un `user_id` explicite ;
- durée administrative 30 minutes : supprimée, une durée absente devient « À
  replanifier » ;
- durée de lot 60 minutes : conservée provisoirement, à décider avant la
  prochaine validation ;
- technicien implicite : conservé uniquement pour les anciennes tâches
  administratives globales, jamais pour les horaires d'un technicien.

## Navigation et aide

Le nouveau menu `Mon travail` expose maintenant `Horaires de travail` et `Lots
préventifs`. `Ma journée` propose un lien de configuration lorsque les horaires
manquent et signale quand le planning des salles est incomplet. L'Ancien menu
reste inchangé, administrateur uniquement, 76/76.

## Scénario UI et limites

Le scénario complet demandé (TECH_A → horaires, lot, tâche, équipements,
génération, Ma journée) n'a pas encore été exécuté intégralement avec un
navigateur et un compte administrateur de test. Il ne doit pas être présenté
comme validé. Les données historiques `TEST_UI_PHASE21_*` sont conservées ;
aucune donnée n'a été nettoyée.

## Décision

La phase est **PARTIELLEMENT VALIDÉE** : l'isolation des horaires et l'absence
de fallback silencieux sont corrigées et testées ; le parcours UI préventif
réel, la création de deux techniciens depuis l'UI et la génération sans
fixture restent à démontrer. Le catalogue embarqué contient désormais les 330
tâches historiques de `lot_tasks` et son import est idempotent.
