gmao/docs/ui-audit/PLANNING_ENGINE_PROPOSAL.md
root 8e19476bb3
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
docs(architecture): concevoir centre documentaire v2 et planning interne
2026-08-22 22:02:37 +00:00

15 KiB
Raw Blame History

Moteur de planification interne — proposition d'architecture

Statut : étude et spécification uniquement. Aucun modèle, route, migration, synchronisation ou changement applicatif n'est créé par ce document.

A. Architecture actuelle

Le dépôt possède déjà plusieurs briques réutilisables :

  • Room et RoomSchedule (app_new/core/models/college.py) pour les salles et un emploi du temps hebdomadaire (week_start, jour, début/fin, matière, enseignant, classe) ;
  • WorkSchedule, WorkScheduleTemplate, TechnicianAvailability, PersonalLeave, Training, CollegeClosure, ClosureSchedule et ClosureWorkDay (app_new/core/models/planning.py) pour horaires, pauses, absences, formations, fermetures et permanences ;
  • PreventiveTask (durée, lot, équipement/catégorie, fenêtre autorisée), LotTask (durée, périodicité, sécurité) et ScheduledTask (date, début, fin, durée, salle, équipement, entreprise, contrat, technicien, statut) ;
  • Intervention avec date planifiée, priorité, salle/équipement, technicien et entreprise ;
  • AdminTask, actuellement récurrente avec heure et durée ;
  • PlanningDay/PlanningItem, qui représentent déjà prévention, curatif, administratif et formation avec durée, salle, priorité et statut.

planning_service.py sait produire une journée et calculer des heures de travail, mais schedule_task ne place pas réellement de créneau et la disponibilité de salle n'est pas croisée avec toutes les tâches internes. L'implémentation interroge en outre un symbole PronoteSchedule alors que le modèle local de salle observé est RoomSchedule : cette dette doit être résolue avant d'automatiser la disponibilité.

B. Limites actuelles

  1. RoomSchedule ne conserve pas de provenance, identifiant externe, validité ou récurrence explicite.
  2. Le service de planification peut retomber sur 08:0017:00 et certaines requêtes d'horaires/indisponibilités ne filtrent pas toujours par agent.
  3. Les conflits salle, tâches, pauses, fermetures et interventions ne sont pas évalués dans un même calendrier.
  4. AdminTask ne porte ni statut d'exécution, priorité, agent ou fenêtre.
  5. PlanningItem et ScheduledTask se recouvrent partiellement, ce qui peut produire des doublons d'affichage.
  6. L'import Pronote est optionnel dans les routes mais ne doit jamais être une dépendance du calcul interne.

C. Principe de vérité interne

La GMAO possède des créneaux internes d'occupation. Chaque créneau conserve sa source : manual, pronote, import ou une future source. Les champs conceptuels sont source, external_id, last_synced_at, source_updated_at, période de validité et statut actif. Le métier parle de créneau d'occupation interne ; il ne dépend jamais d'une réponse en direct de Pronote.

L'application doit démarrer et rester pleinement utilisable avec PRONOTE_ENABLED=false, sans token et sans synchronisation.

D. Saisie manuelle en début d'année

Une fonction de gestion crée les RoomSchedule de source manual à partir des salles, périodes, jours, heures et types d'occupation : cours, réunion, examen, réservation, travaux, intervention, fermeture ou autre. Les règles de validation refusent début ≥ fin et signalent les chevauchements. Une saisie manuelle est toujours conservée, même lorsqu'une source externe est absente.

E. Pronote facultatif

Pronote peut fournir des créneaux après configuration, mais ne possède jamais la source interne de vérité. La synchronisation ne doit lire/écrire que les créneaux qu'elle a créés (source=pronote, external_id connu).

F. Synchronisation et conflits

  • Créneau manuel : jamais modifié ni supprimé automatiquement par Pronote.
  • Créneau Pronote identique : mise à jour de ses champs et de last_synced_at.
  • Créneau supprimé côté Pronote : désactivation du seul créneau Pronote correspondant ; aucune suppression manuelle.
  • Collision manuel/Pronote : le manuel gagne, le conflit est signalé à l'utilisateur avec les deux provenances.
  • Pronote indisponible : conserver les dernières données importées, marquer leur fraîcheur et afficher un avertissement ; ne jamais vider le planning.
  • Donnée Pronote obsolète : elle peut être désactivée selon une politique de rétention explicite, jamais effacée silencieusement.

G. Disponibilité des salles

Le calcul croise les occupations internes, fermetures de salle/collège, interventions, tâches planifiées, rendez-vous d'entreprises et permanence. Les catégories d'occupation sont celles de la saisie manuelle. Une tâche de 45 minutes peut occuper 12:0012:45 entre deux cours si le technicien est également disponible ; les créneaux hors horaires, pause ou fermeture sont exclus.

Le futur service doit utiliser RoomSchedule pour les cours importés ou manuels et ScheduledTask/PlanningItem/Intervention pour les activités internes, sans appeler Pronote en direct.

H. Préventif et lots

PreventiveTask et LotTask fournissent la périodicité, la durée, la portée, les restrictions d'accès et le caractère critique. ScheduledTask est la source d'exécution d'un travail généré : lot, tâche, équipement/local, date cible, durée, début/fin, priorité, statut, entreprise/contrat et technicien.

Les créneaux proposés doivent afficher quoi, où, quand, durée et refuser une date dépassant une échéance de conformité. Une intervention convertie ne doit pas être affichée deux fois.

I. Horaires de travail

Le moteur utilise le WorkSchedule de l'agent, les templates, pauses, TechnicianAvailability, congés, formations, fermetures et ClosureWorkDay. Il ne planifie jamais sur la pause ou hors intervalle. La V1 doit exiger un agent explicite pour une proposition automatique et ne pas inventer 08:0017:00 lorsque la configuration manque ; l'absence de données doit être expliquée.

J. Tâches administratives

Les tâches administratives sont des activités planifiables qui consomment du temps : commande, devis, compte rendu, registre, dossier ou appels. La V1 doit compléter le modèle actuel par une durée, priorité, statut, fenêtre/date, heure planifiée et responsable, ou projeter ces données dans PlanningItem. Une récurrence ne doit pas masquer l'instance réellement faite ou reportée.

K. Entreprises extérieures

Un rendez-vous doit représenter au minimum entreprise, date/heure fixe, intervention/contrat lié, durée d'accueil, accompagnement, éventuels passages et temps administratif final. Pour la V1, réutiliser ScheduledTask/PlanningItem avec company_id et un type d'étape simple (accueil, contrôle, signature) plutôt que créer un système de calendrier externe. Une entité ExternalCompanyAppointment séparée ne sera justifiée que si plusieurs étapes doivent être suivies indépendamment.

L. Urgences et contraintes

Les niveaux compréhensibles sont :

  • Fixe : rendez-vous entreprise ou examen à heure imposée ;
  • Urgent : fuite, sécurité ou panne critique ;
  • Échéance : conformité ou tâche à terminer avant une date ;
  • Déplaçable : prévention réalisable dans la fenêtre ;
  • Administratif : travail planifiable avant une échéance.

Une urgence peut interrompre ou repousser, mais le système conserve chaque tâche, son ancien créneau, sa raison et sa nouvelle proposition.

M. Optimisation géographique

La première version calcule un coût ordinal simple : même salle (0), même zone (1), même bâtiment (2), autre bâtiment (3). Ce coût ne passe jamais avant sécurité, rendez-vous fixe, échéance, disponibilité, horaires et compétences. Il sert uniquement à départager des créneaux équivalents, sans GPS ni tournée complexe.

Ordre d'arbitrage : urgence/sécurité, rendez-vous fixe, échéance, disponibilité salle, horaires, compétence/affectation, regroupement géographique, réduction des trous.

N. Replanification et contrôle humain

Lorsqu'une urgence arrive à 10:00, l'interface propose les tâches décalables, les conserve avec leur historique et expose les créneaux alternatifs. Elle classe chaque élément en conservé, décalé, non planifiable ou nouvelle proposition. Une validation humaine est obligatoire ; aucun déplacement silencieux.

Un déplacement manuel revalide conflit salle, horaires, pauses, autre tâche, rendez-vous fixe et fermeture. Le message doit être métier : « Salle 101 occupée jusqu'à 11:00 », avec créneaux disponibles.

O. Multi-techniciens futur

La colonne actuelle assigned_to_id convient à la V1 mono-agent, mais ne doit pas devenir une contrainte conceptuelle. Une évolution pourra ajouter une association PlannedTaskAssignee (tâche, utilisateur, rôle), avec preferred_technician, required_skill et required_people_count. Une personne préférée n'est pas une personne assignée ; une compétence requise est une contrainte, pas une préférence. Deux personnes seront représentées par deux affectations liées à la même activité.

P. Modèle de données recommandé

Réutiliser au maximum les tables présentes :

  1. Étendre RoomSchedule : source, external_id, horodatage de synchronisation, validité, type/libellé et statut actif. Index futur sur (room_id, week_start, day_of_week, start_time, end_time, source).
  2. Conserver ScheduledTask comme échéance/exécution préventive ; ajouter ultérieurement contrainte de priorité et fenêtre si les champs existants ne suffisent pas.
  3. Utiliser PlanningItem comme projection de placement (date, début, fin, durée, salle, statut, priorité) et imposer une règle anti-doublon avec les références scheduled_task_id/intervention_id/admin_task_id.
  4. Étendre AdminTask ou sa projection pour responsable, statut, priorité et fenêtre, sans perdre la récurrence.
  5. Rendez-vous entreprise : d'abord ScheduledTask/PlanningItem avec company_id; créer ExternalCompanyAppointment seulement si les étapes deviennent des objets suivis.

Chaque futur index doit couvrir les requêtes par date/statut, salle/intervalle et agent. Aucune table de planning parallèle ne doit être créée sans preuve que PlanningItem ne peut pas être consolidé.

Q. Migrations futures

Les extensions ci-dessus nécessiteront des migrations Alembic non destructives, avec valeurs par défaut (source=manual, statut actif) et backfill explicite des RoomSchedule existants. Les données Pronote historiques ne doivent pas être confondues avec le manuel : si leur origine est inconnue, les marquer import et demander validation.

R. Algorithme V1 déterministe

  1. Construire les intervalles de travail de l'agent, en retirant pauses, congés, formations, fermetures et permanences incompatibles.
  2. Construire les intervalles occupés de la salle et du planning interne.
  3. Générer les créneaux possibles par durée et fenêtre.
  4. Éliminer conflits, hors horaires, échéances et rendez-vous fixes.
  5. Classer par contrainte puis coût géographique, puis heure la plus proche.
  6. Retourner une proposition explicable, sans commit automatique.

Une heuristique simple est préférable à un solveur d'optimisation complet : elle est déterministe, testable, lisible et réversible.

S. Interface proposée

Vue journalière

Afficher pour chaque bloc : heure, bâtiment/zone/salle, titre, catégorie (préventif, curatif, urgent, administratif, entreprise), durée, statut et contrainte. Un panneau « Propositions » explique les créneaux refusés.

Gestion des salles

Calendrier par salle/semaine, saisie manuelle claire, provenance visible et indication « données Pronote anciennes » sans bloquer le planning interne.

Conflits

Afficher la cause, la ressource concernée et deux ou trois créneaux compatibles. L'utilisateur choisit et confirme.

T. Tests à prévoir

  • salle libre/occupée et chevauchement ;
  • planning manuel sans Pronote ;
  • Pronote désactivé, indisponible, puis synchronisé ;
  • conflit manuel/Pronote et suppression distante ;
  • préventif de 45 minutes entre deux cours ;
  • durée/échéance d'une tâche liée à un lot ;
  • pause, horaires hors travail, fermeture et permanence ;
  • tâche administrative récurrente, réalisée et reportée ;
  • entreprise avec accueil, accompagnement et signature ;
  • urgence décalant deux tâches sans perte d'historique ;
  • regroupement même salle/zone/bâtiment ;
  • déplacement manuel vers rendez-vous fixe ;
  • données sans agent/horaires explicites ;
  • futur multi-techniciens compatible (test de structure, pas d'optimiseur).

U. Scénarios métier de validation

  1. Début d'année manuel : saisir les créneaux de plusieurs salles, planifier une maintenance et vérifier l'absence de Pronote.
  2. Mise à jour Pronote : importer un nouveau cours, modifier un cours importé et vérifier qu'un créneau manuel reste intact.
  3. Panne Pronote : simuler une semaine sans connexion, conserver le dernier planning et afficher sa date de fraîcheur.
  4. Préventif interstitiel : proposer 45 minutes entre deux cours en respectant la pause et le temps de travail.
  5. Tournée locale : cinq préventifs de la même zone sont regroupés avant un autre bâtiment.
  6. Entreprise fixe : rendez-vous chaudière à 09:00, accueil, contrôle, signature et temps administratif visibles.
  7. Urgence : fuite à 10:00, conserver le rendez-vous fixe, décaler deux tâches déplaçables et faire valider la proposition.
  8. Journée mixte : maintenance, commande, entreprise et intervention curative avec horaires et statuts cohérents.
  9. Fermeture/permanence : proposer une tâche pendant une journée rouverte de vacances, refuser les dates fermées.
  10. Salle indisponible : fermeture d'une salle, replanification vers une autre salle compatible sans modifier silencieusement l'objet métier.

V. MVP obligatoire

  • planning interne des salles, saisie manuelle et provenance ;
  • Pronote optionnel, import limité à ses propres créneaux ;
  • durée, début/fin, statut et priorité des tâches ;
  • respect horaires, pauses, fermetures et absences ;
  • prévention/lot, interventions, tâches administratives ;
  • rendez-vous entreprise simple ;
  • urgences et propositions de replanification ;
  • regroupement salle/zone/bâtiment ;
  • déplacement manuel avec avertissements ;
  • vue journalière lisible et déterministe.

W. Évolutions futures et décisions à valider

Plus tard : multi-techniciens avancé, compétences, absences détaillées, deux personnes par tâche, optimisation complexe, calcul de trajets, import d'autres sources et statistiques de charge.

Avant développement, valider :

  1. RoomSchedule comme base des occupations internes et ses champs de provenance ;
  2. la règle « Pronote ne modifie jamais le manuel » ;
  3. l'usage de PlanningItem comme projection anti-doublon ;
  4. le périmètre des tâches administratives et des étapes entreprise ;
  5. le niveau de priorité/contrainte exposé aux utilisateurs ;
  6. le comportement d'une donnée Pronote obsolète ;
  7. la politique lorsque les horaires d'un agent sont absents ;
  8. la future association multi-techniciens ;
  9. les index et volumes acceptables pour la vue semaine/année.