Aller au contenu

Rapprochement des formateurs de classe virtuelle OGDPC

Version métier : voir Rapprochement des formateurs de classe virtuelle OGDPC.

⚠️ Orpheline à date (2026-04-23) — la commande existe dans le code mais n’a aucun schedule GitLab actif ni job CI. À planifier prochainement (cf. section Déclenchement).

Commande qui rapproche les noms d’intervenants déclarés côté OGDPC (colonne intervenant du CSV ogdpc_sessions_latest.csv) avec les utilisateurs ROLE_TRAINER affectés aux VirtualClass futures. En cas de divergence, elle réaffecte les trainers de la VirtualClass. Le matching exact s’appuie sur une normalisation (uppercase + NFD sans accents) ; le fallback utilise Gemini pour gérer typos, inversions prénom/nom et abréviations.

Planification GitLab : aucune à ce jour. La commande scheduled:ogdpc-reconcile-virtual-class-trainers n’est pas référencée dans ci-jobs/.scheduled-ci.yml et aucun schedule GitLab (2026-04-23) ne l’invoque.

TODO(review) : brancher cette commande sur un schedule GitLab (ex. description Reconcile virtual class trainers against ANDPC, cron 0 3 * * * Europe/Paris après le rapprochement des dates). Il faudra :

  1. Ajouter un job ogdpc_reconcile_trainers dans ci-jobs/.scheduled-ci.yml (stage ogdpc_extract réutilisable), avec if: '$CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "ogdpc_reconcile_trainers"'.
  2. Créer le schedule côté GitLab > Build > Pipeline schedules avec la variable SCHEDULE_TYPE=ogdpc_reconcile_trainers.
  3. Mettre à jour cette page et la home internal-api pour refléter la planification effective.

Commande (exécution manuelle en attendant) :

Fenêtre de terminal
docker exec $APP_NAME php bin/console scheduled:ogdpc-reconcile-virtual-class-trainers

Options :

  • --bucket=<name> (défaut erevo-lms)
  • --csv-key=<key> (défaut dpc-extract/ogdpc_sessions_latest.csv)
  • --local-csv=/path.csv
  • --no-report-upload
  1. Charger le CSV depuis MinIO (ou --local-csv). Parsing BOM-aware, séparateur ;. Échec I/O ⇒ Command::FAILURE (via $io->error, pas d’exception).
  2. Indexer les lignes CSV par clé "<reference>|<sessionNumber>" en ne gardant que format === 'Classe virtuelle'.
  3. Pré-charger les trainers : SELECT u FROM User u WHERE u.roles LIKE '%"ROLE_TRAINER"%'. Construit trainerIndex[normalizeName("LASTNAME FIRSTNAME")] = User.
  4. Charger les VC futures : VirtualClassRepository::getFutureVirtualClasses().
  5. Pour chaque VirtualClass :
    • Remonter à SessionDate → Version pour obtenir reference et internalId (numéro de session).
    • Lookup CSV par clé ; absent ⇒ not_in_csv dans le rapport, skip.
    • Colonne intervenant vide ⇒ skip silencieux.
    • Pour chaque nom CSV (split sur ,) :
      • trainerIndex[normalizeName(csvName)] → match exact ; sinon
      • findUserWithGemini() envoie à Gemini le nom CSV + la liste des noms DB et retourne le nom choisi ou NONE.
      • Utilisateur introuvable ⇒ ligne unresolved_user dans le rapport.
    • Compare le set d’IDs résolus avec le set actuel ($vc->getTrainers()). Différent ⇒ removeTrainer / addTrainer pour aligner.
  6. flush() si au moins un fix.
  7. Rapport : CSV reference;session_number;type;description avec type ∈ {fixed, error, not_in_csv, unresolved_user}, uploadé sur dpc-extract/reports/virtual-class-trainer-reconcile_*.csv + alias _latest.
  8. Exit : FAILURE si au moins un unresolved_user, sinon SUCCESS.
  • User — lecture seule (liste des trainers via roles LIKE '%ROLE_TRAINER%').
  • VirtualClass — écriture de la collection trainers (ajout/retrait).
  • SessionDate — lecture (pour remonter à Version).
  • Version — lecture (reference).

TODO(review) : pages modele-de-donnees/user, virtual-class, session-date, version absentes — à créer par entity-documenter.

  • Contrairement à ReconcileSessionDateCommand, aucune ScheduledCommandException n’est levée : les erreurs I/O MinIO produisent un Command::FAILURE (via $io->error + return) plutôt qu’une exception remontée dans Sentry.

TODO(review) : harmoniser avec ReconcileSessionDateCommand en levant ScheduledCommandException (ou en ajoutant manuellement un Sentry\captureException()) pour que les échecs MinIO soient capturés dans Sentry au lieu de rester dans le log GitLab.

  • unresolved_user fait basculer l’exit en FAILURE (job CI échoue) — comportement voulu pour attirer l’attention sur les écarts de nommage à corriger côté DB ou côté OGDPC.
  • Gemini indisponible : seul le matching exact est tenté ; les noms non triviaux tombent en unresolved_user.
  • MinIO / S3 : input erevo-lms/dpc-extract/ogdpc_sessions_latest.csv, output erevo-lms/dpc-extract/reports/virtual-class-trainer-reconcile_*.csv.
  • Gemini API (App\Service\GeminiClient) — clef $GEMINI_API_KEY. Fallback de matching fuzzy.
  • MariaDB : Users, VirtualClasses, SessionDates, Versions.
  • Logs : sortie console lors d’une exécution manuelle (docker exec). Une fois planifiée, logs dans GitLab > Build > Pipelines.
  • Rapport CSV : dpc-extract/reports/virtual-class-trainer-reconcile_latest.csv sur MinIO.
  • Alerting : Sentry capture les exceptions PHP (voir TODO ci-dessus concernant les erreurs MinIO non-exception).
  • Commande : src/Command/Scheduled/ReconcileVirtualClassTrainerCommand.php
  • Job CI : aucun (à créer)
  • Services : App\Service\GeminiClient, Aws\S3\S3Client
  • Repository : App\Repository\VirtualClassRepository::getFutureVirtualClasses()