## Problèmes résolus
### Bug 1 : Seulement 2 invitations sur 3 envoyées
**Cause :** Tentative de conversion base64 incorrecte qui corrompait la première invitation
**Solution :** Conversion explicite Buffer → base64 avec encodage UTF-8 pour toutes les invitations
### Bug 2 : Fichiers ICS corrompus (erreur Outlook "Nous n'avons pas pu importer le calendrier")
**Cause :** Encodage incorrect lors de la transmission SMTP
**Solution :** Conversion UTF-8 → base64 explicite avec contentType correct
## Modifications techniques
- `server/emailService.ts` : Conversion explicite en base64 UTF-8 pour chaque invitation ICS
- `server/_core/smtpSender.ts` : Ajout de logs détaillés pour tracer les pièces jointes
- ContentType : `text/calendar; charset=utf-8` (sans method=REQUEST qui posait problème)
## Déploiement
✅ Serveur TEST (108.143.67.56) - Validé
✅ Serveur PROD (98.71.216.234) - Déployé
Les apprenants reçoivent maintenant les 3 invitations ICS et peuvent les importer correctement dans Outlook.
## Problème identifié
Les présences formateur validées n'apparaissaient pas dans la fenêtre des émargements. La fonction `getSignaturesFormateursBySequence()` lisait la table `presences` avec un filtre `typeUtilisateur = "formateur"`, alors que les présences formateur sont enregistrées dans une table séparée `presences_formateur`.
## Solution implémentée
- Modification de `getSignaturesFormateursBySequence()` dans `presenceDb.ts` pour lire directement la table `presences_formateur`
- Suppression du filtre `typeUtilisateur` devenu inutile
- Correction définitive et robuste pour éviter toute récurrence
## Déploiement
✅ Serveur de production (98.71.216.234) - Compilé et redémarré
✅ Toutes les présences formateur sont maintenant visibles dans l'interface
## Problème identifié
La recherche du formateur par email était sensible à la casse et aux espaces, ce qui empêchait de trouver le formateur même s'il existait dans la base de données.
## Solution implémentée
Modification de la logique de recherche dans `server/routers.ts` (lignes 2617-2623) :
- Normalisation de l'email saisi : `trim().toLowerCase()`
- Utilisation de SQL `LOWER(TRIM())` pour la comparaison en base de données
- La recherche est maintenant insensible à la casse et aux espaces
## Déploiement
✅ Serveur de production (98.71.216.234) - Bundle: index-C6kRdcg-.js
✅ Application redémarrée avec PM2
Le formateur peut maintenant être trouvé quelle que soit la casse utilisée lors de la saisie de l'email.
## Bug 1 : Erreur "inscription requise pour un apprenant"
**Problème :** Le paramètre typeUtilisateur: "formateur" n'était pas passé dans l'appel à la mutation validerPresence
**Solution :** Ajout du paramètre manquant dans EmargementFormateurScan.tsx (ligne 101)
## Bug 2 : Erreur "Aucune date de formation ne correspond à aujourd'hui"
**Problème :** Le backend cherchait automatiquement la date du jour avec CURDATE() au lieu d'utiliser le dateFormationId sélectionné par le formateur
**Solution :** Remplacement de la logique de recherche automatique par l'utilisation directe du dateFormationId fourni (routers.ts lignes 2631-2635)
## Déploiements effectués
✅ Serveur de production (98.71.216.234) - Bundle: index-C6kRdcg-.js
✅ Serveur de recette (108.143.67.56) - Bundle: index-CHmE9ro_.js
Les formateurs peuvent maintenant :
- Signer leur présence sans erreur d'inscription
- Sélectionner n'importe quelle date de la séquence (pas seulement aujourd'hui)
Problème identifié :
- Le paramètre typeUtilisateur: "formateur" n'était pas passé dans l'appel à la mutation validerPresence depuis EmargementFormateurScan.tsx
- Sans ce paramètre, le backend traitait la requête comme un apprenant et déclenchait l'erreur "Inscription requise pour un apprenant"
Correction appliquée :
- Ajout du paramètre typeUtilisateur: "formateur" dans l'appel à validerPresence (ligne 101 de EmargementFormateurScan.tsx)
- Le backend peut maintenant distinguer correctement les formateurs des apprenants
Prochaines étapes :
- Déployer sur les serveurs VPS (recette et production)
- Tester avec l'email marianne.tarrieu@gmail.com sur la séquence 1 du 03/02/26
Modifications apportées :
- Format d'affichage identique à celui des apprenants
- Une zone par date avec deux lignes (matin et après-midi)
- Case verte (CheckCircle2) pour indiquer qu'une signature est présente
- Affichage du nom "Formateur", de la date/heure de signature
- Icône de signature cliquable pour voir la signature tactile en grand
- Suppression de l'affichage avec les grandes images de signature
- Ergonomie cohérente avec la section apprenants
- Déployé sur recette (108.143.67.56) et production (98.71.216.234)
Modifications apportées :
- Regroupement des signatures formateurs par date (au lieu d'une signature par ligne)
- Affichage d'une zone par date avec les signatures matin et après-midi à l'intérieur
- Ergonomie identique à celle des apprenants pour une meilleure cohérence visuelle
- Affichage de "Aucune signature" pour les périodes sans signature
- Heure de signature affichée dans un badge pour chaque période
- Design distinct avec bordure bleue pour différencier des signatures apprenants
- Déployé sur recette (108.143.67.56) et production (98.71.216.234)
Modifications apportées :
- Backend : Ajout de la fonction getSignaturesFormateursBySequence dans presenceDb.ts
- Backend : Ajout de la procédure tRPC presences.listSignaturesFormateurs dans routers.ts
- Frontend : Ajout de l'encart visuel des signatures formateurs dans FormateurEmargement.tsx
- L'encart affiche les signatures avec date, période (matin/après-midi), heure et image de signature
- Rafraîchissement automatique toutes les 30 secondes
- Design distinct avec bordure bleue pour différencier des signatures apprenants
- Déployé sur recette (108.143.67.56) et production (98.71.216.234)
- Procédure generateQRCodeFormateur dans routers.ts
- Fonction validerPresenceFormateur dans presenceDb.ts
- Bouton "QR Code Formateur" dans FormateurEmargement.tsx
- Page EmargementFormateurScan.tsx pour le scan du QR code
- Route /emargement-formateur/{token}
- Gestion automatique de la date du jour
- Stockage de la signature sur S3
- Champ qrCodeFormateurToken dans le schéma sequences
Prêt pour déploiement et tests sur le VPS.
- Création de la page /emargement-formateur/:token avec formulaire simplifié
- Procédure backend presences.validerFormateur dédiée
- Deux boutons QR code dans l'interface formateur (apprenants + formateur)
- Génération automatique des URL distinctes pour chaque type d'utilisateur
- Déploiement réussi sur le VPS de production
- Ajout de la détection automatique formateur/apprenant dans EmargementScan.tsx
- Nouvelle procédure tRPC getSequenceByToken pour récupérer les infos de séquence
- Interface adaptée selon le type d'utilisateur (apprenant ou formateur)
- Déploiement réussi sur le VPS de production
Le système détecte maintenant automatiquement si l'email correspond à un apprenant ou un formateur, et affiche l'interface appropriée pour chaque cas.
Modifications principales :
- Ajout des champs typeUtilisateur et formateurId dans la table presences pour distinguer formateurs et apprenants
- Détection automatique du rôle (formateur/apprenant) via l'email lors du scan du QR code
- Interface de signature tactile réutilisée pour les formateurs
- Intégration des signatures tactiles formateur dans la génération PDF de la feuille de présence
- QR code dans l'espace formateur accessible pour l'émargement
- Tests unitaires validés avec succès
Le système permet maintenant aux formateurs d'émarger (matin et après-midi) via le même QR code que les apprenants, avec détection automatique du rôle et intégration des signatures dans le PDF.
- Amélioration du feedback visuel lors du chargement des attestations (affichage immédiat du nom de fichier)
- Ergonomie unifiée pour tous les uploads de fichiers (composant FileUpload)
- Réorganisation de la modal des rappels (largeur optimisée, disposition horizontale)
- Modification de la feuille de présence (signatures formateur matin/après-midi sans date)
- Permissions de gestion des attestations pour formateurs et super-formateurs
- Rafraîchissement automatique de la page d'émargement numérique (30 secondes)
- Indicateur visuel de rafraîchissement "Mis à jour il y a X secondes"
- Vérification empêchant l'émargement avant la date de formation
Toutes les modifications sont déployées sur le VPS de production.