docs(planning): préciser relais Pronote et créneaux protégés
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
This commit is contained in:
parent
8e19476bb3
commit
df9a402d27
1 changed files with 117 additions and 42 deletions
|
|
@ -48,42 +48,90 @@ résolue avant d'automatiser la disponibilité.
|
||||||
## C. Principe de vérité interne
|
## C. Principe de vérité interne
|
||||||
|
|
||||||
La GMAO possède des créneaux internes d'occupation. Chaque créneau conserve
|
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
|
une provenance (`manual`, `pronote`, `import`) et, conceptuellement, un
|
||||||
conceptuels sont `source`, `external_id`, `last_synced_at`,
|
booléen `protected_from_sync`, un `external_id`, les horodatages de
|
||||||
`source_updated_at`, période de validité et statut actif. Le métier parle de
|
synchronisation et une période de validité.
|
||||||
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
|
La distinction métier est la suivante :
|
||||||
`PRONOTE_ENABLED=false`, sans token et sans synchronisation.
|
|
||||||
|
- **manuel initial** : `source=manual`, protection désactivée ; il permet de
|
||||||
|
démarrer avant Pronote et peut être supplanté par une donnée Pronote fiable ;
|
||||||
|
- **manuel protégé** : `source=manual`, protection activée ; il représente une
|
||||||
|
décision locale explicite et ne peut être écrasé automatiquement ;
|
||||||
|
- **Pronote** : `source=pronote`, géré uniquement par la synchronisation qui
|
||||||
|
l'a créé ;
|
||||||
|
- **import** : donnée issue d'une autre importation connue ou historique.
|
||||||
|
|
||||||
|
L'occupation active présentée au moteur de maintenance est une vue résolue :
|
||||||
|
elle ne contient pas deux fois un créneau manuel initial et son équivalent
|
||||||
|
Pronote. Pronote est une source de synchronisation, jamais le moteur de
|
||||||
|
planning de la GMAO. 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
|
## D. Saisie manuelle en début d'année
|
||||||
|
|
||||||
Une fonction de gestion crée les `RoomSchedule` de source `manual` à partir
|
Une fonction de gestion crée des `RoomSchedule` de source `manual` à partir
|
||||||
des salles, périodes, jours, heures et types d'occupation : cours, réunion,
|
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
|
examen, réservation, travaux, intervention, fermeture ou autre. Par défaut,
|
||||||
validation refusent début ≥ fin et signalent les chevauchements. Une saisie
|
une saisie de cours destinée à l'initialisation est **non protégée**. Pour une
|
||||||
manuelle est toujours conservée, même lorsqu'une source externe est absente.
|
réunion exceptionnelle, un examen local, des travaux, une réservation,
|
||||||
|
intervention ou fermeture, l'utilisateur peut cocher une formulation métier
|
||||||
|
telle que « Ne pas modifier automatiquement ce créneau ».
|
||||||
|
|
||||||
|
La validation refuse début ≥ fin et signale les chevauchements. L'interface
|
||||||
|
affiche « Saisi manuellement » et, si nécessaire, « Protégé des mises à jour
|
||||||
|
automatiques » ; elle ne montre jamais le nom technique
|
||||||
|
`protected_from_sync`.
|
||||||
|
|
||||||
## E. Pronote facultatif
|
## E. Pronote facultatif
|
||||||
|
|
||||||
Pronote peut fournir des créneaux après configuration, mais ne possède jamais
|
Lorsque Pronote devient disponible et fiable, il peut prendre progressivement
|
||||||
la source interne de vérité. La synchronisation ne doit lire/écrire que les
|
le relais sur les créneaux manuels **non protégés** correspondant à son emploi
|
||||||
créneaux qu'elle a créés (`source=pronote`, `external_id` connu).
|
du temps. Il ne modifie ni ne supprime les créneaux manuels protégés. Il ne
|
||||||
|
possède jamais la source interne de vérité : le service de synchronisation
|
||||||
|
résout d'abord les provenances et les conflits, puis le moteur consomme la vue
|
||||||
|
interne active.
|
||||||
|
|
||||||
## F. Synchronisation et conflits
|
## F. Synchronisation et conflits
|
||||||
|
|
||||||
- Créneau manuel : jamais modifié ni supprimé automatiquement par Pronote.
|
### Rapprochement déterministe
|
||||||
- Créneau Pronote identique : mise à jour de ses champs et de
|
|
||||||
`last_synced_at`.
|
Un créneau Pronote peut être rapproché automatiquement d'un manuel initial
|
||||||
- Créneau supprimé côté Pronote : désactivation du seul créneau Pronote
|
uniquement si les critères stables concordent : même salle, même période de
|
||||||
correspondant ; aucune suppression manuelle.
|
validité, même jour/date et horaires identiques ou suffisamment proches,
|
||||||
- Collision manuel/Pronote : le manuel gagne, le conflit est signalé à
|
complétés si disponibles par classe/groupe, matière et enseignant. La V1 ne
|
||||||
l'utilisateur avec les deux provenances.
|
déduit pas une correspondance à partir d'un seul critère. Si la correspondance
|
||||||
- Pronote indisponible : conserver les dernières données importées, marquer
|
est ambiguë, elle conserve les deux lignes, signale un conflit et demande une
|
||||||
leur fraîcheur et afficher un avertissement ; ne jamais vider le planning.
|
validation humaine.
|
||||||
- Donnée Pronote obsolète : elle peut être désactivée selon une politique de
|
|
||||||
rétention explicite, jamais effacée silencieusement.
|
### Règles
|
||||||
|
|
||||||
|
- Manuel initial non protégé + Pronote correspondant : le créneau Pronote
|
||||||
|
devient actif et le manuel initial est marqué supplanté/archivé ; il n'y a
|
||||||
|
pas de doublon dans la vue d'occupation.
|
||||||
|
- Manuel initial non protégé + horaire Pronote modifié : le Pronote remplace
|
||||||
|
l'ancien intervalle, qui n'est plus considéré comme une occupation active.
|
||||||
|
- Manuel protégé + Pronote chevauchant : le manuel reste actif, Pronote reste
|
||||||
|
visible comme conflit ; rien n'est écrasé automatiquement.
|
||||||
|
- Créneau Pronote identique ou modifié : seule la ligne `source=pronote` avec
|
||||||
|
`external_id` correspondant est mise à jour et son `last_synced_at` avancé.
|
||||||
|
- Suppression côté Pronote : désactivation de la ligne Pronote propriétaire.
|
||||||
|
Un manuel initial supplanté reste archivé comme historique et ne redevient
|
||||||
|
actif automatiquement que si une règle de réactivation explicite est
|
||||||
|
validée ; par défaut, l'interface propose à l'utilisateur de le restaurer.
|
||||||
|
Aucun manuel protégé n'est supprimé.
|
||||||
|
- Pronote indisponible : conserver tous les créneaux actifs connus, afficher
|
||||||
|
la date de dernière synchronisation et un avertissement de fraîcheur ; ne
|
||||||
|
jamais vider le planning.
|
||||||
|
|
||||||
|
Chaque transition laisse une trace minimale : créé manuellement, protégé ou
|
||||||
|
déprotégé, repris par Pronote, modifié par synchronisation, conflit détecté ou
|
||||||
|
désactivé car absent de Pronote. Cette trace doit rester compréhensible sans
|
||||||
|
imposer un moteur d'audit complexe en V1.
|
||||||
|
|
||||||
|
Le moteur de maintenance demande uniquement « quels sont les créneaux
|
||||||
|
d'occupation internes actifs de cette salle ? ». Il ne connaît ni la priorité
|
||||||
|
Pronote ni les règles de rapprochement.
|
||||||
|
|
||||||
## G. Disponibilité des salles
|
## G. Disponibilité des salles
|
||||||
|
|
||||||
|
|
@ -188,9 +236,10 @@ par deux affectations liées à la même activité.
|
||||||
|
|
||||||
Réutiliser au maximum les tables présentes :
|
Réutiliser au maximum les tables présentes :
|
||||||
|
|
||||||
1. **Étendre `RoomSchedule`** : `source`, `external_id`, horodatage de
|
1. **Étendre `RoomSchedule`** : `source`, `protected_from_sync`,
|
||||||
synchronisation, validité, type/libellé et statut actif. Index futur sur
|
`external_id`, horodatage de synchronisation, validité, type/libellé,
|
||||||
`(room_id, week_start, day_of_week, start_time, end_time, source)`.
|
statut actif et, si nécessaire, référence au créneau supplanté. 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
|
2. **Conserver `ScheduledTask`** comme échéance/exécution préventive ; ajouter
|
||||||
ultérieurement contrainte de priorité et fenêtre si les champs existants ne
|
ultérieurement contrainte de priorité et fenêtre si les champs existants ne
|
||||||
suffisent pas.
|
suffisent pas.
|
||||||
|
|
@ -209,11 +258,14 @@ que `PlanningItem` ne peut pas être consolidé.
|
||||||
|
|
||||||
## Q. Migrations futures
|
## Q. Migrations futures
|
||||||
|
|
||||||
Les extensions ci-dessus nécessiteront des migrations Alembic non destructives,
|
Une migration non destructive ajoutera à `RoomSchedule` la provenance, la
|
||||||
avec valeurs par défaut (`source=manual`, statut actif) et backfill explicite
|
protection, les identifiants/horodatages de synchronisation, la validité et le
|
||||||
des `RoomSchedule` existants. Les données Pronote historiques ne doivent pas
|
statut. Les lignes existantes seront initialisées avec `source=manual` et
|
||||||
être confondues avec le manuel : si leur origine est inconnue, les marquer
|
`protected_from_sync=false`, puis un écran de validation permettra de protéger
|
||||||
`import` et demander validation.
|
les exceptions locales. Les données Pronote historiques d'origine inconnue
|
||||||
|
seront marquées `import` et soumises à validation, jamais fusionnées à
|
||||||
|
l'aveugle. Le statut supplanté/archivé doit conserver le lien historique sans
|
||||||
|
réactiver automatiquement un faux créneau.
|
||||||
|
|
||||||
## R. Algorithme V1 déterministe
|
## R. Algorithme V1 déterministe
|
||||||
|
|
||||||
|
|
@ -250,8 +302,15 @@ compatibles. L'utilisateur choisit et confirme.
|
||||||
|
|
||||||
- salle libre/occupée et chevauchement ;
|
- salle libre/occupée et chevauchement ;
|
||||||
- planning manuel sans Pronote ;
|
- planning manuel sans Pronote ;
|
||||||
- Pronote désactivé, indisponible, puis synchronisé ;
|
- Pronote prend le relais sur un manuel initial non protégé ;
|
||||||
- conflit manuel/Pronote et suppression distante ;
|
- Pronote modifie l'heure d'un manuel initial ;
|
||||||
|
- manuel protégé jamais écrasé ;
|
||||||
|
- conflit Pronote/réservation protégée ;
|
||||||
|
- Pronote désactivé ou indisponible ;
|
||||||
|
- retour de Pronote après plusieurs jours et fraîcheur affichée ;
|
||||||
|
- suppression côté Pronote et manuel initial supplanté ;
|
||||||
|
- absence de doublon manuel + Pronote ;
|
||||||
|
- rapprochement ambigu nécessitant validation humaine ;
|
||||||
- préventif de 45 minutes entre deux cours ;
|
- préventif de 45 minutes entre deux cours ;
|
||||||
- durée/échéance d'une tâche liée à un lot ;
|
- durée/échéance d'une tâche liée à un lot ;
|
||||||
- pause, horaires hors travail, fermeture et permanence ;
|
- pause, horaires hors travail, fermeture et permanence ;
|
||||||
|
|
@ -265,12 +324,18 @@ compatibles. L'utilisateur choisit et confirme.
|
||||||
|
|
||||||
## U. Scénarios métier de validation
|
## U. Scénarios métier de validation
|
||||||
|
|
||||||
1. **Début d'année manuel** : saisir les créneaux de plusieurs salles,
|
1. **Rentrée progressive** : le gestionnaire saisit le planning manuellement,
|
||||||
planifier une maintenance et vérifier l'absence de Pronote.
|
planifie immédiatement la maintenance, puis Pronote fonctionne quelques
|
||||||
2. **Mise à jour Pronote** : importer un nouveau cours, modifier un cours
|
jours plus tard. Les cours compatibles reprennent les manuels initiaux,
|
||||||
importé et vérifier qu'un créneau manuel reste intact.
|
sans doublon ; une réservation protégée reste intacte.
|
||||||
|
2. **Mise à jour Pronote** : importer un cours correspondant, modifier son
|
||||||
|
heure puis vérifier que seul le manuel initial non protégé est supplanté et
|
||||||
|
que l'historique reste lisible.
|
||||||
3. **Panne Pronote** : simuler une semaine sans connexion, conserver le
|
3. **Panne Pronote** : simuler une semaine sans connexion, conserver le
|
||||||
dernier planning et afficher sa date de fraîcheur.
|
dernier planning Pronote connu et tous les manuels, avec date de fraîcheur.
|
||||||
|
4. **Retour de Pronote** : après plusieurs jours, synchroniser une nouvelle
|
||||||
|
version, traiter une suppression distante et demander validation pour un
|
||||||
|
rapprochement ambigu.
|
||||||
4. **Préventif interstitiel** : proposer 45 minutes entre deux cours en
|
4. **Préventif interstitiel** : proposer 45 minutes entre deux cours en
|
||||||
respectant la pause et le temps de travail.
|
respectant la pause et le temps de travail.
|
||||||
5. **Tournée locale** : cinq préventifs de la même zone sont regroupés avant
|
5. **Tournée locale** : cinq préventifs de la même zone sont regroupés avant
|
||||||
|
|
@ -308,8 +373,9 @@ d'autres sources et statistiques de charge.
|
||||||
Avant développement, valider :
|
Avant développement, valider :
|
||||||
|
|
||||||
1. `RoomSchedule` comme base des occupations internes et ses champs de
|
1. `RoomSchedule` comme base des occupations internes et ses champs de
|
||||||
provenance ;
|
provenance/protection ;
|
||||||
2. la règle « Pronote ne modifie jamais le manuel » ;
|
2. la règle « Pronote peut supplanter le manuel initial non protégé, mais ne
|
||||||
|
modifie jamais le manuel protégé » ;
|
||||||
3. l'usage de `PlanningItem` comme projection anti-doublon ;
|
3. l'usage de `PlanningItem` comme projection anti-doublon ;
|
||||||
4. le périmètre des tâches administratives et des étapes entreprise ;
|
4. le périmètre des tâches administratives et des étapes entreprise ;
|
||||||
5. le niveau de priorité/contrainte exposé aux utilisateurs ;
|
5. le niveau de priorité/contrainte exposé aux utilisateurs ;
|
||||||
|
|
@ -317,3 +383,12 @@ Avant développement, valider :
|
||||||
7. la politique lorsque les horaires d'un agent sont absents ;
|
7. la politique lorsque les horaires d'un agent sont absents ;
|
||||||
8. la future association multi-techniciens ;
|
8. la future association multi-techniciens ;
|
||||||
9. les index et volumes acceptables pour la vue semaine/année.
|
9. les index et volumes acceptables pour la vue semaine/année.
|
||||||
|
|
||||||
|
### Décision recommandée
|
||||||
|
|
||||||
|
Retenir l'**option A** : `source = manual | pronote | import` complétée par
|
||||||
|
`protected_from_sync` et un statut historique (actif, supplanté, désactivé).
|
||||||
|
Elle évite de multiplier les valeurs de provenance tout en distinguant
|
||||||
|
clairement le manuel initial du manuel protégé. La vue interne résolue est la
|
||||||
|
seule entrée du moteur de maintenance ; Pronote ne devient jamais une
|
||||||
|
dépendance fonctionnelle.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue