100 lines
6 KiB
Markdown
100 lines
6 KiB
Markdown
# Synchronisation Escada (pull)
|
|
|
|
La synchronisation depuis Escada télécharge les PDFs / vues (absences, BN, Matu, notes, fiches, notices) et les importe en base. C'est l'opération la plus complexe de l'application.
|
|
|
|
## Page : `/escada`
|
|
|
|
### Sélection des classes
|
|
|
|
La liste des classes vient d'un cache disque (`data/esacada_classes.json`) rempli via le bouton **Actualiser**. Le rafraîchissement lance une session Playwright qui se connecte à Escadaweb et récupère la liste complète des classes.
|
|
|
|
> Note : MP, MI et « Formation » sont **filtrées de l'affichage UI** mais conservées dans le cache (elles servent au matching Matu pro).
|
|
|
|
### Options de synchronisation
|
|
|
|
| Option | Effet |
|
|
|---------------------|----------------------------------------------------------------------|
|
|
| Absences | Télécharge les PDFs d'absences + parse + import |
|
|
| BN | Bulletins de notes + moyennes Matu (semestres complets) |
|
|
| Notes | Notes d'examens finales |
|
|
| Données apprentis | Fiches personnelles : adresse, entreprise, formateur, représentant légal, statut compensation des désavantages, majeur/mineur |
|
|
| Notices | Importe l'historique des notices Escada (table `apprenti_notices`) |
|
|
|
|
### Force réimportation complète
|
|
|
|
La case « Forcer la réimportation complète » (signalée en jaune) **écrase tous les statuts d'absences** côté local par les valeurs du PDF, et **vide les pendings** des absences concernées.
|
|
|
|
À utiliser uniquement quand on veut **reprendre l'état complet d'Escada** (par exemple après un test ou une corruption locale).
|
|
|
|
Sans ce flag :
|
|
- Les absences modifiées localement et **pas encore poussées** (= en pending) sont **préservées**.
|
|
- Les nouvelles absences du PDF sont importées normalement.
|
|
- Les absences orphelines (présentes en DB mais absentes du PDF) sont supprimées.
|
|
|
|
## Phases d'exécution
|
|
|
|
### Phase 1 : Scraping (Playwright)
|
|
|
|
`scripts/sync_esacada.py --sync-all CLASSE1 CLASSE2 ...`
|
|
|
|
1. Playwright ouvre Escadaweb avec un profil persistant (`data/browser_profile/`).
|
|
2. Pour chaque classe sélectionnée :
|
|
- Télécharge le PDF d'absences
|
|
- Télécharge le PDF de bulletin
|
|
- Télécharge le PDF de notes
|
|
- Pour les apprentis Matu : télécharge le PDF Matu de la classe MP correspondante
|
|
- Scrape les fiches personnelles (vue ViewLernende — y compris représentant légal + flag compensation)
|
|
- Si l'option « Notices » est cochée : pull l'historique via `pull_notices.py`
|
|
3. À la fin, écrit `ALL_DONE` dans la sortie standard et `data/sync_last_result.json` (timestamp).
|
|
|
|
### Phase 2 : Import en DB
|
|
|
|
`scripts/run_imports.py` est lancé par le wrapper après réception du signal `ALL_DONE` :
|
|
|
|
1. Parse chaque PDF d'absences → upsert des `Absence` (déduplication sur (apprenti, date, période))
|
|
2. Parse les BN → insère `NotesBulletin` (toutes les notes du BN sont stockées, pas seulement les moyennes)
|
|
3. Parse les notes → insère `NotesExamen`
|
|
4. Parse les fiches → upsert `ApprentiFiche` (adresse perso, entreprise, **représentant légal**, **compensation_desavantages**, **majeur**)
|
|
5. Détecte les **orphelines** (absences en DB mais absentes du PDF dans la fenêtre temporelle) et les supprime (sauf si elles ont un pending, sans force).
|
|
6. Écrit `data/sync_last_result.json` avec les compteurs détaillés.
|
|
|
|
### Re-parsing sans re-téléchargement
|
|
|
|
`scripts/run_imports.py --reparse-bn-only` permet de re-traiter tous les PDFs déjà téléchargés (utile après un changement dans le parser BN, sans relancer Playwright).
|
|
|
|
## Pendings : modifications locales en attente
|
|
|
|
Quand un utilisateur modifie une absence dans l'application (page Apprentis), une entrée est créée dans la table `EscadaPending` avec une action :
|
|
|
|
- **`E`** : marquer comme excusée sur Escada
|
|
- **`N`** : marquer comme non excusée sur Escada
|
|
- **`clear`** : retirer l'absence sur Escada (= remettre l'apprenti présent)
|
|
|
|
Ces pendings sont visibles sur la page `/escada` dans la section « Modifications en attente ». Le bouton **Pousser vers Escada** les vide en envoyant chaque modification.
|
|
|
|
## Notices Escada (import et création)
|
|
|
|
Les notices sont les remarques rattachées à un apprenti dans Escada (avis de sanction, retenue, remarque libre, etc.).
|
|
|
|
### Import (pull)
|
|
|
|
`scripts/pull_notices.py` lit la vue Escada de chaque classe, scrape les notices, et upsert dans la table `apprenti_notices` (clé `(apprenti, date_event, titre)`). Affichage en lecture seule dans l'onglet « Notices » de la fiche apprenti et de la vue classe.
|
|
|
|
### Création (push)
|
|
|
|
Voir le chapitre dédié [Push vers Escada](#) — la création locale d'un avis de sanction ou de retenue crée une `Notice` (table locale), qui est ensuite poussée vers Escada par `scripts/push_notices.py`.
|
|
|
|
## Cas particuliers gérés
|
|
|
|
| Situation | Sans force | Avec force |
|
|
|----------------------------------------------------|---------------------------|---------------------------|
|
|
| Absence dans PDF + pending sur la même | Pending préservé | Pending écrasé |
|
|
| Absence dans PDF + DB sans pending | Mise à jour si différent | Mise à jour systématique |
|
|
| Absence dans DB, absente du PDF, sans pending | Supprimée (orpheline) | Supprimée |
|
|
| Absence dans DB, absente du PDF, avec pending=clear | Conservée (le clear gagne)| Supprimée |
|
|
|
|
## Diagnostic
|
|
|
|
- **Timeout > 15 min** : vérifier les logs `data/logs/operations.log`. Souvent un problème Playwright (captcha, session expirée).
|
|
- **Aucune classe récupérée** : token de session Escada expiré → relancer le rafraîchissement (re-login automatique avec les identifiants stockés en /params, code 2FA généré via `totp_secret`).
|
|
- **Logs détaillés** : page `/logs` affiche `operations.log` en temps réel.
|