# Phase 2.1b — implémentation préventif et entreprises ## Baseline - Version avant : `0.1.0-dev.10` ; version après : `0.1.0-dev.11`. - Commit de départ : `e65e653`. - Le dépôt était propre ; les services Docker local (Flask, MariaDB, Adminer) étaient démarrés et `/health/` répondait. - Les tests de référence restaient `152 passed, 1 failed, 1 error` ; l'échec et l'erreur historiques concernent le lookback/contexte GMAO et son teardown, hors périmètre. ## Ce qui est implémenté ### Durée et périmètre `LotTask` expose maintenant : - `duration_mode` : `unit`, `fixed` ou `zone` ; - `scope_mode` : `dynamic` ou `manual` ; - `executor_type` : `internal`, `external_company`, `department`, `mixed`, `undefined`. En mode `unit`, la durée d'une cible est `duree_minutes × quantity`. Une quantité de groupe (par exemple 30 chaises) est donc respectée. En mode `fixed`, la quantité ne multiplie pas le forfait. Le périmètre dynamique suit les équipements actifs du lot ; le périmètre manuel utilise la sélection explicitement enregistrée. Les tâches sans durée ont `estimated_duration=0` et le statut technique `needs_duration`; elles ne sont pas proposées par `DayPlanner` comme tâches planifiées. Les valeurs historiques ne sont pas réintroduites comme vérité : le catalogue reste idempotent et ne remplace jamais une personnalisation existante. Les propositions de durée du document de référence restent à valider métier avant d'être injectées en masse. ### Espaces verts Les zones disposent de quatre durées facultatives propres à la zone : tonte, bordures, haies et ramassage/évacuation. Elles sont éditables dans le formulaire normal d'une zone et ne créent aucune durée générique dans un lot. Le raccord automatique d'une règle de lot à ces quatre champs reste à faire dans une passe ultérieure après validation du vocabulaire des tâches espaces verts. ### Entreprises et passages Les champs existants `company_id`, `contract_id`, `periodicite` et `jours_entre_interventions` sont exposés dans la fiche de tâche, ainsi que le type d'exécutant. En revanche, le workflow complet de passage (rendez-vous, fenêtre, non-venue, date réelle, accompagnement et tableau Passages & contrôles) n'est pas encore implémenté dans cette passe. `ContractVisit` ne porte actuellement qu'une date obligatoire et ne peut pas représenter fidèlement les trois modes demandés sans migration métier dédiée. ## Migration `h3c4d5e6f7a8_phase21b_preventive_scope.py` ajoute sans perte : - les trois colonnes de qualification à `lot_tasks` ; - la table d'association `lot_task_equipments` ; - les quatre durées d'espaces verts à `zones`. La migration est additive et possède un downgrade. Elle n'attribue aucun horaire, lot ou exécutant à `alban`. ## Tests ajoutés `tests/unit/test_preventive_scope.py` couvre le calcul par quantité, le forfait par cible et l'absence explicite de durée. La compilation Python et le chargement des modèles passent. La suite intégration locale est actuellement bloquée par l'erreur historique de teardown (`equipment_lifecycle_events` absente de la base de test), déjà présente avant cette passe. ## État de validation Cette passe est **partiellement validée** : la durée unitaire, le périmètre et les durées de zone ont une base persistante et une UI simple ; le workflow entreprise complet et le scénario intégral sans intervention technique restent à réaliser. Phase 2.2 non commencée.