- Ajout du support SMTP pour l'envoi d'emails (sans dépendre de Resend)
- Correction de l'affichage du statut pour montrer "SMTP Direct" au lieu de "Resend"
- Ajout d'alertes spécifiques pour la configuration SMTP
- Correction de la fonction upsertEmailConfig pour mettre à jour au lieu de créer une nouvelle configuration
- Correction du bug d'enregistrement des champs SMTP dans la base de données
- Mise à jour forcée du provider à "smtp" dans la base de données
**Problème identifié** :
La mutation tRPC `emailConfig.upsert` n'acceptait pas les champs SMTP (smtpHost, smtpPort, smtpSecure, smtpUser, smtpPassword) dans son schéma de validation Zod, ce qui empêchait l'enregistrement de la configuration SMTP.
**Solution appliquée** :
- Ajout des 5 champs SMTP dans le schéma d'input de la mutation `upsert` dans `server/routers.ts`
- Tous les champs SMTP sont définis comme nullable et optional pour permettre la flexibilité
- Types corrects : smtpPort (number), smtpSecure (enum), autres (string)
**Résultat** :
La configuration SMTP peut maintenant être enregistrée correctement dans la base de données. Les champs sont transmis du frontend au backend et stockés via la fonction `upsertEmailConfig`.
**Modifications de la base de données** :
- Ajout des champs SMTP dans la table `emailConfig` : smtpHost, smtpPort, smtpSecure, smtpUser, smtpPassword
**Backend** :
- Installation de `nodemailer` pour l'envoi SMTP
- Création de `server/_core/smtpSender.ts` avec les fonctions d'envoi SMTP et de test de connexion
- Modification de `server/_core/emailSender.ts` pour supporter les deux méthodes (Resend et SMTP)
- Priorité donnée à SMTP si configuré, sinon fallback sur Resend
**Frontend** :
- Mise à jour de `AdminEmailConfig.tsx` pour permettre le choix entre Resend et SMTP
- Ajout d'un sélecteur de méthode d'envoi (Resend API / SMTP Direct)
- Formulaire de configuration SMTP avec :
* Hôte SMTP (ex: smtp.gmail.com)
* Port (587, 465, 25)
* Sécurité (TLS, SSL, None)
* Identifiants (utilisateur/mot de passe)
* Email expéditeur
**Compatibilité** :
- Support des principaux fournisseurs SMTP (Gmail, Outlook, serveurs SMTP personnalisés)
- Instructions pour les mots de passe d'application Gmail
- Mode simulation toujours disponible pour les tests
**Problème identifié** :
Le script `update-app.sh` utilisait `pnpm install --prod` qui n'installe que les dépendances de production, excluant les devDependencies comme `drizzle-kit` nécessaire pour les migrations.
**Solution appliquée** :
1. **update-app.sh** : Changé `pnpm install --prod` en `pnpm install` pour installer toutes les dépendances (production + développement)
2. **GUIDE_MISE_A_JOUR.md** : Mise à jour de la documentation pour refléter ce changement
**Justification** :
`drizzle-kit` est nécessaire pour exécuter `pnpm db:push` qui applique les migrations de base de données. Sans les devDependencies, la commande échoue.
**Nouveau package créé** :
- formation-manager-update-20251127_114306.tar.gz (2.6M)
- Prêt pour déploiement avec la correction
**Modifications apportées** :
1. **backup-before-update.sh** :
- APP_DIR: /var/www/formation-manager-itinova
- BACKUP_DIR: /var/backups/formation-manager-itinova
2. **update-app.sh** :
- APP_DIR: /var/www/formation-manager-itinova
- SERVICE_NAME: formation-manager-itinova
3. **GUIDE_MISE_A_JOUR.md** :
- Tous les chemins mis à jour vers formation-manager-itinova
- Tous les noms de service corrigés
4. **README.md** :
- Documentation mise à jour avec les bons chemins
- Exemples corrigés
5. **Nouveau package créé** :
- formation-manager-update-20251127_095935.tar.gz (2.6M)
- Prêt pour déploiement sur le serveur VPS
1. **backup-before-update.sh** : Script de sauvegarde automatique
- Sauvegarde complète des fichiers de l'application
- Export de la base de données MySQL
- Sauvegarde du fichier .env
- Conservation des 10 dernières sauvegardes
2. **update-app.sh** : Script de mise à jour automatique
- Création d'une sauvegarde de sécurité
- Arrêt/redémarrage du service
- Copie des nouveaux fichiers
- Installation des dépendances
- Application des migrations de base de données
- Vérification du bon fonctionnement
3. **create-deployment-package.sh** : Script de création de package
- Crée une archive .tar.gz prête à transférer
- Inclut tous les fichiers nécessaires
- Exclut node_modules, .git, .env
4. **Documentation complète** :
- GUIDE_MISE_A_JOUR.md : Guide détaillé avec procédures de mise à jour et rollback
- README.md : Documentation des scripts avec exemples d'utilisation
5. **Package de déploiement créé** :
- formation-manager-update-20251127_074417.tar.gz (2.6M)
- Prêt à être transféré sur le serveur VPS
1. Bug décalage horaire dans le formulaire d'édition des séquences
- Correction de la fonction safeFormatDate pour utiliser les méthodes locales (getHours, getMinutes) au lieu des méthodes UTC
- Les heures saisies (ex: 9h00) s'affichent maintenant correctement dans le formulaire d'édition
2. Ajout du menu de navigation sur la page Import Excel
- Intégration du DashboardLayout wrapper dans AdminImportExcel.tsx
- Le menu latéral s'affiche maintenant correctement sur cette page
3. Déplacement du menu "Import Excel"
- Déplacé du bloc GESTION vers le bloc CONFIGURATION dans le menu de navigation
- Positionné après "Utilisateurs" et avant "Rappels" pour une meilleure organisation
- Ajout de la valeur "tous" dans l'enum publicCible du schéma drizzle/schema.ts
- Mise à jour des validations Zod dans server/routers.ts
- Modification directe de la colonne publicCible en base de données via SQL
- Test réussi : création d'une séquence avec public cible "Tous" fonctionne parfaitement
Corrections apportées:
- Utilisation de clés stables (format yyyy-MM-dd) au lieu de day.toISOString() pour éviter l'erreur React #31
- Gestion correcte des objets Date vs strings pour dateBloquage dans le modal
- Gestion correcte du champ formateur qui peut être un objet ou une string
- Ajout de clés uniques pour les dates de formation dans le modal
Le calendrier fonctionne maintenant sans erreur lors du survol et de l'ouverture des modals de détails.
Modification apportée :
- Le champ email est maintenant modifiable pour l'utilisateur adminServFormation
- Mise à jour du message dans le formulaire d'édition : "Seuls l'email et le mot de passe peuvent être modifiés pour cet utilisateur"
- Les champs nom et identifiant restent en lecture seule (grisés et désactivés)
- Les champs email, mot de passe et rôle sont modifiables pour cet utilisateur spécial
Modifications apportées :
- Création de l'utilisateur "Administrateur" avec identifiant "adminServFormation" et mot de passe "Itinova69!" (hashé avec bcrypt)
- Modification de l'interface pour désactiver le bouton de suppression pour cet utilisateur (grisé avec tooltip explicatif)
- Modification du formulaire d'édition pour rendre les champs nom, email et identifiant en lecture seule (grisés et désactivés)
- Ajout d'un message explicatif dans le formulaire : "Seul le mot de passe peut être modifié pour cet utilisateur"
- Seuls les champs "Nouveau mot de passe" et "Rôle" restent modifiables pour cet utilisateur
- L'utilisateur est identifié par son username "adminServFormation" pour appliquer les restrictions
- Cet utilisateur ne peut pas être supprimé et ses informations de base ne peuvent pas être modifiées, garantissant un accès administrateur permanent au système
Modifications apportées :
- Ajout du champ username (identifiant de connexion) dans le schéma de la base de données avec contrainte UNIQUE
- Mise à jour des procédures tRPC create et update pour gérer username et password
- Implémentation du hashage du mot de passe avec bcryptjs dans createUser et updateUser
- Ajout de la colonne "Identifiant" dans le tableau de la page de gestion des utilisateurs
- Ajout des champs "Identifiant de connexion" et "Mot de passe" dans le formulaire de création
- Ajout des champs "Identifiant de connexion" et "Nouveau mot de passe" dans le formulaire d'édition avec notes explicatives
- Les mots de passe sont hashés avant d'être stockés en base de données pour la sécurité
- Dans le formulaire d'édition, les champs username et password sont optionnels (laissez vide pour ne pas modifier)
Problème identifié :
- La contrainte UNIQUE sur la colonne openId n'existait pas dans la base de données
- Tous les utilisateurs partageaient le même openId
- Chaque connexion créait un nouvel utilisateur au lieu de mettre à jour l'existant
- 344 utilisateurs en double ont été créés
Solution appliquée :
- Nettoyé 343 utilisateurs en double (gardé le plus récent pour chaque openId)
- Ajouté la contrainte UNIQUE sur la colonne openId via ALTER TABLE
- Maintenant onDuplicateKeyUpdate fonctionne correctement
Résultat :
- Plus aucun utilisateur en double ne sera créé
- À chaque connexion, l'utilisateur existant est mis à jour
- Table users propre avec seulement les utilisateurs uniques
✅ Nouvelle procédure tRPC `apprenants.getInscriptions` pour récupérer toutes les inscriptions d'un apprenant avec les détails de formation et séquence
✅ Nouvelle page AdminApprenantDetail (/admin/apprenants/:id) affichant :
- Informations personnelles de l'apprenant (nom, prénom, email, code établissement, fonction)
- Tableau complet de toutes ses inscriptions avec :
* Nom de la formation
* Nom de la séquence
* Toutes les dates de la séquence
* Lieu
* Public cible
* Date d'inscription
* Statut (avec badge coloré : vert pour confirmée, gris pour en attente, rouge pour annulée)
✅ Bouton "Détail" (icône œil) ajouté dans la colonne Actions de la page AdminApprenants
✅ Route /admin/apprenants/:id configurée dans App.tsx
✅ Bouton "Retour aux apprenants" pour navigation facile
Correction appliquée : La procédure getInscriptions extrait maintenant correctement l'objet inscription du résultat retourné par getInscriptionsByApprenant.
Tests réussis : Affichage correct des inscriptions pour l'apprenant "Nouveau Apprenant" (1 inscription à la séquence "Groupe A" avec statut confirmée).
✅ Champ de signature du formateur ajouté en bas de chaque page de feuille de présence
✅ Comprend :
- Label "Signature du formateur :" en gras
- Ligne pour la signature manuscrite (60mm de largeur)
- Champ "Date : _______________" pour dater la validation
Le formateur peut maintenant valider officiellement chaque journée de formation en signant et en datant la feuille de présence.
Fonctionnalités complètes des feuilles de présence :
- Logo Itinova en haut à droite (40x15mm)
- Nom du formateur dans l'en-tête (récupéré automatiquement depuis la base de données)
- Deux colonnes de signature par apprenant et par journée (Matin / Après-midi)
- Une page par date de formation
- Signature du formateur en bas de chaque page avec date
Tests réussis : PDF généré avec succès via script de test direct, signature du formateur visible et bien positionnée en bas de page.