eptm_dashboard/data/docs/10-faq.md
2026-05-12 15:30:28 +02:00

163 lines
7.1 KiB
Markdown

# FAQ / Dépannage
## Synchronisation Escada
### « Import timeout — vérifiez les logs (> 15 min) »
Le subprocess Playwright n'a pas répondu dans le temps imparti. Causes possibles :
- Escadaweb répond très lentement (en pic de charge)
- Captcha / re-login imposé par Escada
- Container Docker en surcharge
**Que faire** :
1. Aller dans `/logs` et chercher le dernier `[sync]` actif
2. Si Playwright est bloqué sur un écran de login : lancer un Actualiser des classes (re-login)
3. Si gros volume de classes : lancer la sync en plusieurs lots de 5-6 classes
### « Aucune classe récupérée »
Le scraping Playwright a échoué — souvent token de session expiré.
**Que faire** : recliquer sur « Actualiser » (force un re-login propre).
### « Le push échoue toujours sur le même apprenti »
Possibles causes :
- L'apprenti existe en local mais pas (ou plus) sur Escada → le pending est obsolète, à supprimer
- Le nom diffère entre local et Escada (ex : prénom composé partiel)
- La page Escada de cet apprenti est verrouillée par un autre éditeur (lock pessimiste Escada)
**Que faire** :
1. Vérifier les logs pour le message d'erreur exact
2. Si l'apprenti n'existe plus : supprimer le pending manuellement en DB
3. Sinon : retenter plus tard
### « L'option 'Forcer la réimportation complète' est en rouge — c'est dangereux ? »
Pas dangereux mais **destructif** :
- Tous les pendings concernés sont écrasés (les modifs locales pas encore poussées sont perdues)
- Tous les statuts d'absences sont remis à ce qu'Escada dit
À utiliser **uniquement** quand on veut sciemment reprendre l'état complet d'Escada.
## Tâches planifiées (cron)
### « J'ai créé une tâche, elle ne se déclenche pas »
Vérifier dans l'ordre :
1. La tâche est-elle **activée** ? (toggle vert)
2. Les heures choisies sont-elles dans le bon fuseau horaire ? (l'app fonctionne en `Europe/Zurich`)
3. La crontab du host appelle-t-elle bien `cron_tick.py` ?
```bash
crontab -l | grep cron_tick
# Doit avoir : * * * * * docker exec eptm-dashboard-app-1 python scripts/cron_tick.py
```
4. Regarder le log d'exécution : `ls /logs/cron/` et `tail` sur le dernier fichier.
### « J'avais un job 'toutes les X minutes', il a disparu »
L'ancien mode `interval` a été remplacé par `daily_multi`. Au boot du container, les jobs `interval` sont **automatiquement migrés** en `daily_multi` (l'intervalle est déroulé sur 24 h depuis minuit). Idem pour les anciens jobs `daily` (`HH:MM`) → convertis en `daily_multi` avec une seule heure.
Si tu veux modifier un de ces jobs : ouvre-le, tu verras la grille 24 cases avec les heures qui étaient configurées.
### « La tâche ne notifie pas sur Telegram »
- `notify_on` doit être `always`, `success` ou `failure` (pas `never`)
- Le `bot_token` et `chat_id` doivent être valides → tester via le bouton « Tester Telegram »
## Édition d'absences
### « Le bouton 'Absent toute la journée' est grisé »
Affichage « Absent toute la journée (Données chronoplan manquantes) » → aucun horaire n'est configuré pour cette classe et ce jour de la semaine.
**Que faire** : admin → `/params → Horaires de classe`, sélectionner la classe, cocher les périodes du jour concerné, enregistrer.
### « Quel est le type de jour affiché en badge ? »
Théorie / Pratique / Matu — défini par classe et par jour dans `/params → Horaires de classe`. Sert d'indication contextuelle dans le panneau d'édition.
## Authentification
### « Mon utilisateur n'a accès à aucune classe »
À sa première connexion, un dialog s'ouvre pour configurer l'accès. Il doit fournir :
- son email Escada (identifiant Keycloak)
- son mot de passe Escada
- un code TOTP courant
Un script Playwright tourne en arrière-plan (visible dans `/logs` avec préfixe `[fetch_classes:<username>]`) et remplit automatiquement `allowed_classes` dans `auth.yaml`.
Si le dialog est fermé (« Plus tard »), il réapparaîtra au prochain login.
### « J'ai perdu mon téléphone avec mon code 2FA »
Un admin peut réinitialiser le 2FA via `/users` : bouton « Réinitialiser 2FA ». Au prochain login, l'utilisateur reverra le QR code.
### « Comment révoquer l'accès d'un user »
Admin → `/users` → bouton « Réinitialiser les droits » : efface `allowed_classes` + identifiants Escada. À sa prochaine connexion, le popup d'enrôlement réapparaîtra (s'il ne le reconfigure pas, il n'aura accès à rien).
## Données
### « Les BN affichent des trous (cellules vides) »
C'est normal : un apprenti peut avoir commencé sa formation au S2 ou S3 → les premiers semestres restent vides. L'extraction depuis le PDF Escada respecte ces trous. Toutes les notes (pas juste les moyennes) sont stockées et affichées.
### « Les notes Matu n'apparaissent pas »
Pré-requis : l'apprenti est dans une classe MP / MI correspondante. Le matching se fait via la classe MP1, MP2, etc. La sync Matu cherche le PDF correspondant **si la case 'BN' est cochée**.
### « L'adresse sur les avis sanction/retenue est fausse »
Depuis mai 2026, l'app n'utilise **plus l'adresse de l'entreprise**. Elle prend :
- l'adresse du **représentant légal** si l'apprenti est mineur (`majeur=False`)
- l'adresse perso de **l'apprenti** sinon
Vérifier que les champs `ApprentiFiche.resp_legal_*` et `ApprentiFiche.adresse/code_postal/localite` sont bien remplis (sync option « Données apprentis »).
## Performance
### « L'app rame quand je change de classe avec beaucoup d'apprentis »
Le `_reload` reconstruit les tableaux HTML BN / Notes pour chaque apprenti — peut prendre quelques secondes pour 25+ apprentis. Un skeleton s'affiche pendant le chargement pour donner du feedback visuel.
### « L'app est bloquée pour les autres users quand je lance la synchro de mes classes »
C'était un bug : le subprocess Playwright bloquait l'event loop. Corrigé en passant à `@rx.event(background=True)` + `asyncio.create_subprocess_exec`. Si ça revient, vérifier que `fetch_my_classes` est bien décoré `background=True` dans `profile.py`.
## Conteneur Docker
### « Le conteneur consomme 100 % CPU à l'idle »
Bug historique lié au hot-reload qui détectait les fichiers WAL/SHM de SQLite comme des modifications source. Corrigé via `REFLEX_HOT_RELOAD_EXCLUDE_PATHS=/app/data` dans le docker-compose.
### « La version dans le sidebar ne change pas après un nouveau tag git »
`data/VERSION` doit être mis à jour manuellement (le `.git` du container dev n'est pas synchronisé avec celui du hôte). Édite le fichier, puis :
```bash
docker restart eptm-dashboard-app-1
```
### « Comment redémarrer proprement »
```bash
cd /opt/eptm-dashboard
docker compose -f docker-compose.dev.yml restart app
```
### « Comment voir les logs du serveur Reflex »
```bash
docker logs -f eptm-dashboard-app-1
```
## SSL / Accès depuis le web
### « Mon navigateur affiche un avertissement sécurité sur dev.dashboard.eptm-automation.ch »
Vérifier le certificat affiché : si l'émetteur est « Fortinet CA » (et non Let's Encrypt), c'est ton firewall qui fait du SSL inspection / IPS — pas un problème du serveur. À demander à l'IT pour whitelister le domaine.