diff --git a/docs/ui-audit/DOCUMENT_CENTER_PROPOSAL_V2.md b/docs/ui-audit/DOCUMENT_CENTER_PROPOSAL_V2.md new file mode 100644 index 0000000..4d049a5 --- /dev/null +++ b/docs/ui-audit/DOCUMENT_CENTER_PROPOSAL_V2.md @@ -0,0 +1,211 @@ +# Centre documentaire global — proposition V2 + +**Statut : étude et spécification uniquement.** Aucun code applicatif, modèle, +route, migration, permission ou menu n'est créé par ce document. + +## A. Décisions de périmètre + +La V1 agrégera en lecture les documents déjà attachés à trois sources : + +- interventions (`InterventionDocument`) ; +- équipements (`EquipmentDocument`) ; +- produits d'entretien (`ProductDocument`). + +Il n'y aura ni table `Document` commune, ni copie physique, ni upload ou +suppression depuis `/documents/`. `Contract.contract_file`, la prévention et +les données personnelles du personnel sont explicitement hors V1. Outlook, +ENT et les autres intégrations restent hors périmètre. + +## B. Cartographie réelle actuelle + +| Source | Table / modèle | Parent obligatoire | Métadonnées actuelles | Routes observées | +|---|---|---|---|---| +| Intervention | `intervention_documents` / `InterventionDocument` (`app_new/core/models/maintenance.py`) | `intervention_id` | `filename`, `filepath`, `description`, `uploaded_at`, `uploaded_by_id` | `/documents/upload/intervention/`, téléchargement, édition de description, suppression | +| Équipement | `equipment_documents` / `EquipmentDocument` (`app_new/core/models/equipment.py`) | `equipment_id` | `filename`, `filepath`, `description`, `uploaded_at`, `uploaded_by_id` | famille `/documents/...` et famille `/equipments//documents/...` | +| Produit | `cleaning_product_documents` / `ProductDocument` (`app_new/core/models/cleaning.py`) | `commercial_product_id` | `document_type`, `title`, `filename`, `filepath`, `version`, `published_at`, `uploaded_at`, `uploaded_by_id`, `is_current` | `GET /cleaning/documents` ; upload/téléchargement produit à compléter dans une évolution séparée | +| Contrat | `contracts.contract_file` | aucun objet documentaire | chemin texte unique | non indexé par le centre V1 | + +`/documents/` répond actuellement 404 : cette absence est le bug UI-011, +mais elle ne justifie pas la création d'un stockage parallèle. + +## C. Stockage physique et risques + +`Config.UPLOAD_FOLDER` pointe vers `app_new/uploads`, monté par Docker dans le +volume `gmao_uploads` (`/app/app_new/uploads`). La limite globale est de 50 MiB. +Les conventions historiques sont `uploads/interventions/_`, +`uploads/equipments/_` et +`uploads/documents//.`. + +Les extensions autorisées sont contrôlées et `secure_filename` est utilisé, +mais le MIME réel n'est pas inspecté, le nom original n'est pas toujours +séparé du nom interne et taille/MIME/hash ne sont pas uniformément conservés. +Les téléchargements passent par `send_file` et ne sont pas exposés comme +répertoire statique ; il faut néanmoins vérifier existence, racine autorisée, +parent et permission à chaque téléchargement. Les écritures interrompues +peuvent laisser un fichier orphelin ou une ligne sans fichier. Une future +maintenance devra produire un rapport d'orphelins sans supprimer +automatiquement les données. + +## D. Dette de routes équipement + +Deux blueprints écrivent des équipements dans deux chemins et avec deux +contrats de métadonnées. La route historique tente notamment de renseigner +`file_type` et `file_size`, champs absents de `EquipmentDocument`. Avant le +centre, il faut choisir un adaptateur de service de téléchargement commun, +conserver les anciens chemins lisibles, puis déprécier une famille de routes +sans casser les URL existantes. Cette convergence est une condition de +qualité, mais ne doit pas entraîner de déplacement physique automatique en V1. + +## E. Architecture recommandée : adaptateurs de lecture + +Chaque source implémentera conceptuellement un adaptateur qui transforme une +ligne spécialisée en un résultat commun en mémoire : + +```text +DocumentResult + source_kind intervention | equipment | product + document_id identifiant de la ligne source + parent_id identifiant de l'objet métier + display_name nom lisible + document_type type métier affichable + description description éventuelle + date uploaded_at ou published_at + context_label Intervention…, Équipement…, Produit… + context_url URL de détail autorisée + location_summary chemin calculé ou « 3 emplacements » + download_target action contrôlée par l'adaptateur +``` + +La vue globale ne devient jamais propriétaire du fichier. La recherche peut +utiliser trois sélections alignées et `UNION ALL`, ou trois requêtes paginées +fusionnées dans un premier incrément. Les relations parent restent la source +de vérité. + +### Alternative étudiée : index commun + +Une table d'index serait utile pour 10 000+ documents, tags, OCR ou recherche +plein texte. Elle ajouterait toutefois un backfill, des synchronisations et le +risque d'index périmé. Elle pourrait être introduite plus tard comme index +réparable (jamais comme propriétaire physique), sans être créée pour la V1. + +## F. Types métier et migration future + +Les produits conservent `fds` et `fiche_technique` ainsi que les valeurs déjà +présentes. Les interventions et équipements recevront, lors d'une migration +future, un champ `document_type` court et indexé avec les valeurs : + +- `notice` — Notice / manuel ; +- `facture` — Facture ; +- `devis` — Devis ; +- `rapport` — Rapport / compte rendu ; +- `certificat` — Certificat / contrôle ; +- `photo` — Photo ; +- `plan` — Plan ; +- `autre` — Autre. + +La migration ajoutera une colonne nullable ou avec défaut `autre`, remplira +les documents historiques avec `autre`, puis pourra rendre le champ non nul +après vérification. Aucun fichier ne sera réécrit. Les adaptateurs afficheront +`Autre` pour une valeur absente ou inconnue. + +## G. Localisations multiples + +La localisation est calculée à partir des relations : équipement → salle → +zone → bâtiment ; produit → lots/stock → emplacements. Si un produit est dans +plusieurs emplacements, le résultat affichera par exemple **3 emplacements** +et ouvrira le détail des chemins individuels. Aucun chemin bâtiment/zone/salle +ne sera dénormalisé dans une future table documentaire. + +## H. RBAC + +La permission nouvelle proposée est `documents.view`. Aucun +`documents.manage` n'est créé. Un résultat est visible uniquement si : + +```text +documents.view ET permission de lecture de la source +``` + +Donc `intervention.view`, `patrimoine.view` ou `stock.view` s'ajoutent selon +la source. Le téléchargement réutilise la même décision en V1 : pas de +`documents.download` séparé, sauf besoin de séparation démontré. Édition et +suppression restent dans le module source et ses permissions (`manage`). Les +liens vers un parent sont masqués si l'utilisateur ne peut pas le lire. + +## I. Interface proposée + +`/documents/` afficherait : + +1. titre **Centre documentaire** et phrase d'aide ; +2. recherche (nom, titre, description, parent, référence) ; +3. filtres principaux : type, source, période ; +4. filtres avancés : bâtiment, zone, salle, équipement, produit ; +5. liste paginée : document, type, lié à, localisation, date, actions. + +Les actions sont **Consulter/Télécharger** et **Ouvrir le contexte**. Aucun +upload global ni suppression globale. Un état vide expliquera que les fichiers +s'ajoutent depuis les fiches intervention, équipement ou produit et proposera +des liens de création autorisés. + +## J. Vue FDS + +`/documents/fds` sera une vue filtrée, non un second stockage : produit, +référence commerciale, fabricant/fournisseur, version, date, statut courant, +emplacements et téléchargement. Une future fonction « Classeur FDS » pourra +exporter une liste/PDF, mais n'appartient pas au MVP. + +## K. Recherche, filtres et performance + +SQL classique suffit pour la V1 : recherche préfixe/contient sur les champs +déjà disponibles, filtrage par source/type/date et pagination obligatoire. +À 100 ou 1 000 documents, les adaptateurs sont suffisants. À 10 000, mesurer +les `UNION ALL`, ajouter index sur parent/date/type et envisager un index +commun. Les jointures de localisation seront paginées et chargées de façon +prévisible, sans N+1. + +## L. Sécurité et intégrité + +Avant implémentation, spécifier : validation extension + MIME, limite de +taille, `Content-Disposition` sûr, racine de chemin canonique, refus d'IDOR, +contrôle parent/RBAC avant téléchargement, absence d'exécution de fichiers, +et journalisation des erreurs. Prévoir des tests fichier manquant, ligne +orpheline, chemin hors racine, document supprimé et permission source absente. + +## M. Compatibilité historique + +Les trois tables et leurs fichiers restent intacts. Les noms ou types absents +sont adaptés à la lecture (`Autre`, nom de fichier sécurisé). `contract_file` +reste exclu et documenté comme dette, sans conversion silencieuse. + +## N. Tests avant développement + +- intervention, équipement et produit visibles ; +- recherche, filtres, pagination et FDS ; +- plusieurs localisations produit ; +- lien vers contexte avec permission ; +- absence d'IDOR et téléchargement contrôlé ; +- utilisateur sans `documents.view` ; +- utilisateur sans permission source ; +- fichier manquant/orphelin ; +- suppression depuis le module source retirant le résultat global ; +- non-régression des routes historiques. + +## O. MVP et évolutions + +**V1 obligatoire :** agrégation des trois sources, `/documents/`, recherche, +types/source/période, pagination, localisation calculée, téléchargement +sécurisé, lien de contexte, RBAC `documents.view`, vue `/documents/fds`. + +**Plus tard :** index SQL commun, tags, OCR, plein texte PDF, versionnage, +prévisualisation, classeur FDS, contrats, prévention et documents généraux. +L'ajout d'un document reste toujours contextuel dans la V1. + +## P. Questions à valider avant développement + +1. Confirmer les libellés et la liste des types intervention/équipement. +2. Confirmer que `documents.view` doit être accordée en plus des permissions + sources. +3. Confirmer qu'aucun `documents.download` distinct n'est requis en V1. +4. Choisir l'ordre et le style de consolidation des deux familles de routes + équipement. +5. Définir une politique de rétention pour fichiers orphelins. +6. Décider plus tard si `contract_file` mérite une migration dédiée. diff --git a/docs/ui-audit/PLANNING_ENGINE_PROPOSAL.md b/docs/ui-audit/PLANNING_ENGINE_PROPOSAL.md new file mode 100644 index 0000000..22df484 --- /dev/null +++ b/docs/ui-audit/PLANNING_ENGINE_PROPOSAL.md @@ -0,0 +1,319 @@ +# 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:00–17: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:00–12: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:00–17: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. diff --git a/docs/ui-audit/PROGRESS.md b/docs/ui-audit/PROGRESS.md index fe7e795..156590b 100644 --- a/docs/ui-audit/PROGRESS.md +++ b/docs/ui-audit/PROGRESS.md @@ -350,3 +350,22 @@ UI-023 est corrigé localement : `request_enabled` est désormais visible et modifiable dans `/cleaning/products//edit`. Le produit `TEST_UI_DETERGENT_SOL` a été activé et apparaît dans `/cleaning/requests/new`. Test automatisé associé : **1 passed** (`product_request_enabled_is_editable`). + +## Étude d'architecture — centre documentaire V2 et moteur de planning interne + +Date : 22 août 2026 + +Étude terminée sans modification du code applicatif. Deux spécifications ont +été produites : + +- `DOCUMENT_CENTER_PROPOSAL_V2.md` : agrégation en lecture par adaptateurs + des interventions, équipements et produits, sans table commune ni copie de + fichier ; RBAC `documents.view` combiné à la permission source ; +- `PLANNING_ENGINE_PROPOSAL.md` : planning interne autonome, saisie manuelle + des salles, provenance des créneaux, Pronote facultatif, tâches préventives, + administratives et entreprises, urgences, heuristique déterministe et + compatibilité multi-techniciens future. + +Aucune route, migration, permission, modèle, template, synchronisation ou +fonctionnalité n'a été créée. Développement conditionné à la validation des +questions listées dans les deux documents.