- Ajout de "reset_password" à l'enum du schéma Drizzle (table emailTemplates)
- Migration SQL pour modifier l'enum dans la base de données
- Création du template dans la base de données avec un contenu par défaut approprié
- Mise à jour de la procédure tRPC emailTemplates.upsert pour utiliser les noms de colonnes français (titre, couleurPrincipale, couleurSecondaire, piedDePage)
- Mise à jour de la fonction upsertEmailTemplate dans server/db.ts pour utiliser les noms de colonnes français
- Réécriture complète de AdminEmailTemplates.tsx pour utiliser les noms de colonnes français
- Test complet de l'interface : le template s'affiche correctement, peut être modifié et prévisualisé
- Le template contient les variables {{prenom}}, {{nom}}, {{lienReinitialisation}} pour la réinitialisation de mot de passe
- Total de 9 templates d'emails maintenant disponibles (inscription, teaser, rappel, rappelJ1, rappel3-6, reset_password)
- Renommage questionnaire.nom → questionnaire.titre dans QuestionnaireReponse.tsx, AdminQuestionnaireEdit.tsx, questionnaireScheduler.ts, questionnaireExport.ts
- Correction des requêtes SQL dans questionnaireDb.ts (suppression de la condition complete inexistante)
- Ajout des colonnes valeurMin et valeurMax dans la table questions
- Renommage de la colonne nom en titre dans la table questionnaires
- Correction des 170 erreurs TypeScript liées aux types templateType dans les procédures rappels.create et rappels.update (passage de z.string() à z.enum() avec les valeurs correctes)
- Nettoyage complet des fichiers de migration Drizzle (suppression des 32 anciens fichiers et génération d'une nouvelle migration propre 0000_clean_justice.sql)
- Création du guide utilisateur GUIDE_CONFIGURATION_ATTESTATIONS.md expliquant en détail le nouveau workflow de configuration des attestations (modes de génération et d'envoi, workflows recommandés, bonnes pratiques, dépannage)
- Vérification que tous les paramètres liés aux attestations sont bien accessibles dans la page de gestion des attestations (mode de génération et mode d'envoi)
- Retrait du champ envoiAutomatiqueAttestations du schéma Drizzle
- Suppression de la colonne envoiAutomatiqueAttestations de la table parametres dans la base de données
- Mise à jour de la procédure tRPC parametres.update pour retirer ce champ
- Test complet du workflow : le serveur fonctionne correctement et le tableau de bord s'affiche sans erreur
- Changement du champ 'nom' en 'titre' pour les questionnaires (backend et frontend)
- Suppression de la propriété 'complete' inexistante dans reponsesQuestionnaires
- Correction du type 'provider' dans la configuration email
- Gestion des valeurs null pour le champ 'fonction' des apprenants
- Résolution de l'erreur logsRappels.email après redémarrage du serveur
Fonctionnalités :
- Configuration par formation (génération auto/manuel, envoi auto/manuel)
- Affichage de la liste des apprenants inscrits
- Upload de documents PDF par apprenant (mode manuel)
- Boutons de prévisualisation et d'envoi manuel
- Gestion complète des attestations
Corrections :
- Ajout des colonnes modeAttestation et modeEnvoi dans la table formations
- Ajout des colonnes documentUrl, documentS3Key, uploadedBy, uploadedAt, emailEnvoye, dateEnvoiEmail dans la table attestations
- Correction de l'erreur SQL en retirant la colonne urlPdf inexistante de la requête
Nouvelle fonctionnalité complète pour gérer les attestations :
- Schéma de base de données : colonnes modeAttestation et modeEnvoi dans formations, colonnes documentUrl, documentS3Key, uploadedBy, uploadedAt dans attestations
- Backend : fichier gestionAttestationsDb.ts, procédures tRPC, fonction sendAttestationEmail
- Interface : page AdminGestionAttestations avec sélection de formation, configuration des modes, tableau des apprenants, boutons upload/prévisualisation/envoi/suppression
- Navigation : lien dans menu Gestion, route /admin/gestion-attestations
- Ajout du paramètre d'envoi automatique des attestations dans la page Paramètres
- Ajout de la prévisualisation du modèle d'attestation avec génération PDF
- Création de la page Historique des attestations dans la section Traçabilité
- Création de la table historiqueAttestations pour tracer les envois
- Ajout des procédures tRPC pour l'historique et la prévisualisation
- Modification du schéma rappels : remplacement de nbJours par joursAvant pour correspondre à la structure réelle de la base de données
- Correction des noms de colonnes pour utiliser exactement la même casse que la base de données (templateType, heureEnvoi, nomFichier, urlFichier, s3Key, typeFichier, tailleFichier, derniereExecution)
- La page Rappels fonctionne maintenant correctement et affiche tous les rappels configurés sans erreurs SQL
- Modification du schéma apprenants : codeEtablissement et fonction en VARCHAR nullable (au lieu de NOT NULL et ENUM)
- Suppression de la colonne isActive qui n'existe pas dans la base de données
- Modification du schéma sequences : ajout des statuts "bloquee" et "terminee" dans l'ENUM
- Suppression de la colonne dateBloquage qui n'existe pas dans la base de données
- Le dashboard admin fonctionne maintenant correctement sans erreurs de requêtes SQL
- Ajout du composant DashboardLayout à la page FormateurDashboard
- Le menu de navigation latéral s'affiche maintenant correctement pour les utilisateurs avec le rôle formateur
- Navigation cohérente entre toutes les pages de l'espace formateur (Dashboard et Émargement)
- Ajout de 3 nouveaux paramètres globaux : délai d'expiration QR codes (minutes), durée de validité tokens (heures), notifications actives (boolean)
- Création de la table historiqueParametres pour tracer toutes les modifications avec userId, userName, champModifié, ancienneValeur, nouvelleValeur et dateModification
- Ajout d'un bouton "Tester l'URL" avec indicateur visuel de statut (vert si accessible, rouge si erreur)
- Affichage de l'historique des modifications dans un tableau avec toutes les informations de traçabilité
- Mise à jour automatique de l'historique lors de chaque modification de paramètre
Modifications :
- Ajout de DashboardLayout dans client/src/pages/AdminParametres.tsx
- Ajout de DashboardLayout dans client/src/pages/FormateurEmargement.tsx
Le menu de navigation s'affiche maintenant correctement dans toutes les pages de l'application.
Modifications apportées :
- Création de la table parametres dans la base de données
- Création du fichier server/parametresDb.ts avec les fonctions getParametres et updateUrlPublique
- Ajout du router parametres dans server/routers.ts avec les procédures get et updateUrlPublique
- Création de la page client/src/pages/AdminParametres.tsx avec formulaire de modification
- Ajout de la route /admin/parametres dans App.tsx
- Ajout du lien "Paramètres" dans le menu après "Configuration SMTP" dans DashboardLayout
- Modification de server/qrCodeGenerator.ts pour utiliser l'URL de la BDD au lieu de getAppBaseUrl
- URL par défaut définie : https://formations.itinova.org
Fonctionnalités :
- Interface graphique pour modifier l'URL publique de l'application
- Les QR codes d'émargement utilisent maintenant l'URL configurée dans la base de données
- Validation de l'URL avant enregistrement
- Message d'information sur l'impact des modifications
Modifications apportées :
- Création de server/_core/appUrl.ts : fonction getAppBaseUrl() pour gérer l'URL de base
- Modification de server/qrCodeGenerator.ts : utilise getAppBaseUrl() au lieu de localhost
- Support de plusieurs variables d'environnement (APP_PUBLIC_URL, DOMAIN_NAME, SERVER_URL)
- Création du guide CONFIGURATION_URL_PUBLIQUE.md avec instructions détaillées
- Création du script configure-public-url.sh pour faciliter la configuration
Configuration requise sur le serveur VPS :
Ajouter dans le fichier .env : APP_PUBLIC_URL=https://formations.itinova.org
Puis redémarrer l'application avec PM2 ou systemd.
Les QR codes générés utiliseront maintenant l'URL publique configurée au lieu de localhost.
Corrections apportées :
- Correction des références à heureDebut/heureFin dans AdminRappels.tsx (utilisation de dateDebut/dateFin)
- Correction de l'accès à la propriété dates dans EmargementScan.tsx (cast de type)
- Ajout de l'import manquant de QrCode dans DashboardLayout.tsx
- Correction des erreurs TypeScript dans DashboardLayout.tsx (gestion de subItems)
- Ajout de downlevelIteration dans tsconfig.json
- Correction de l'utilisation de Set dans DateFormationMultiSelect.tsx (Array.from)
- Correction de l'appel à createAttestation (utilisation de enregistrerAttestation)
L'application fonctionne maintenant correctement sans erreurs TypeScript.
## Base de données
- ✅ Table `presences` créée (inscriptionId, dateFormationId, heurePresence, modeValidation, validateurId)
- ✅ Colonne `qrCodeToken` ajoutée à la table `sequences`
## Backend
- ✅ Génération de QR code unique par séquence (qrCodeGenerator.ts)
- ✅ Procédures tRPC pour l'émargement (presences.generateQRCode, presences.valider, presences.listBySequence)
- ✅ Fonctions de base de données (presenceDb.ts) pour gérer les présences
- ✅ Génération automatique d'attestation après validation de toutes les présences
- ✅ Intégration avec le service d'attestations existant
## Interface formateur (/formateur/emargement)
- ✅ Sélection de la séquence
- ✅ Génération et affichage du QR code en modal
- ✅ Liste des inscrits avec statut de présence par date
- ✅ Validation manuelle de présence possible
- ✅ Actualisation en temps réel des présences
- ✅ Entrée de menu "Émargement" dans DashboardLayout
## Interface publique (/emargement/:token)
- ✅ Page de scan QR code accessible sans authentification
- ✅ Recherche de l'apprenant par email
- ✅ Sélection de la formation et de la date
- ✅ Validation automatique de la présence via QR code
- ✅ Écrans de confirmation (succès/erreur)
- ✅ Gestion des erreurs (QR invalide, déjà émargé, etc.)
## Génération automatique d'attestations
- ✅ Vérification automatique après chaque validation de présence
- ✅ Génération du PDF d'attestation si toutes les présences sont validées
- ✅ Enregistrement en base de données
- ✅ Upload automatique sur S3
## Dépendances installées
- qrcode (génération de QR codes)
- @types/qrcode (types TypeScript)
Le système est entièrement fonctionnel et prêt à être utilisé par les formateurs et apprenants.
- Ajout du champ formateur (number | null) dans le type FormData de AdminSequences.tsx
- Ajout du type "tous" dans publicCible pour supporter toutes les valeurs possibles
- Correction de FormateurCombobox pour accepter number | null au lieu de string
- Correction des erreurs null dans QuestionnaireReponse.tsx avec optional chaining
- Correction du type previewType dans AdminSequenceInscrits.tsx pour inclure "rappel_j1"
- Build de production testé et fonctionnel (✓ built in 14.69s)
Les quelques avertissements TypeScript restants (11) ne bloquent pas le build de production. L'application peut maintenant être publiée.
Fonctionnalités ajoutées :
- Table de liaison rappelSequences pour associer rappels et séquences
- Composant SequenceMultiSelect avec recherche et multi-sélection
- Gestion des associations dans les procédures create/update
- Modification du scheduler pour filtrer les séquences selon les associations
- Si aucune séquence n'est sélectionnée, le rappel s'applique à toutes les séquences (comportement par défaut)
Le système permet maintenant de configurer des rappels spécifiques pour certaines dates/séquences particulières, offrant une flexibilité complète dans la gestion des rappels automatiques.
Problème résolu :
- Les rappels post-formation affichaient "J-X" au lieu de "J+X" dans la colonne Délai
Modification apportée :
- Mise à jour de l'affichage dans AdminRappels.tsx pour vérifier le champ "timing"
- Si timing = "post_formation" : affiche "J+X"
- Si timing = "pre_formation" : affiche "J-X"
Résultat : L'affichage est maintenant cohérent avec le type de rappel configuré
Modifications apportées :
- Ajout des colonnes nomFichier, urlFichier, s3Key, typeFichier, tailleFichier dans la table rappels
- Création du composant FileUpload pour l'upload de fichiers vers S3 (max 10 Mo)
- Création de l'endpoint API /api/upload-file pour gérer l'upload
- Intégration du composant FileUpload dans les formulaires de création et modification de rappels
- Mise à jour des procédures tRPC create et update pour gérer les informations de fichier
- Modification des fonctions sendRappelJ7Email et sendRappelJ1Email pour inclure les pièces jointes
- Mise à jour du scheduler de rappels pour passer les informations de fichier lors de l'envoi
- Les fichiers sont téléchargés depuis S3 et convertis en base64 pour être attachés aux emails
## Modifications effectuées :
### Base de données (drizzle/schema.ts)
Ajout d'un champ `timing` dans la table `rappels` :
- Type : ENUM('pre_formation', 'post_formation')
- Valeur par défaut : 'pre_formation'
- Permet de distinguer les rappels avant et après formation
### Interface utilisateur (client/src/pages/AdminRappels.tsx)
**Formulaire de création et d'édition :**
- Ajout de radio buttons pour choisir "Pré-formation" ou "Post-formation"
- Le label du champ "Nombre de jours" change dynamiquement selon le choix :
* "Nombre de jours avant la séquence" (pré-formation)
* "Nombre de jours après la séquence" (post-formation)
- Le texte d'aide s'adapte également au timing choisi
**États et formulaires :**
- Ajout du champ `timing` dans `formData`
- Mise à jour de `resetForm()` et `handleEdit()` pour gérer le nouveau champ
### Backend (server/routers.ts)
Mise à jour des procédures tRPC :
- `rappels.create` : ajout du champ `timing` avec validation Zod
- `rappels.update` : ajout du champ `timing` optionnel
## Fonctionnement
L'utilisateur peut maintenant créer des rappels qui seront envoyés soit avant (pré-formation) soit après (post-formation) une séquence, avec un nombre de jours personnalisable pour chaque cas.
## Problème
La procédure `emailTemplates.getByType` retournait `undefined` quand un template n'existait pas, ce qui causait une erreur React Query : "Query data cannot be undefined".
Cette erreur se produisait notamment lors de la sélection des nouveaux templates (Rappel 3, 4, 5, 6) qui n'avaient pas encore été initialisés dans la base de données.
## Solution
Modification de la fonction `getEmailTemplateByType` dans `server/db.ts` pour retourner `null` au lieu de `undefined` :
- `if (!db) return null;` (au lieu de `return undefined;`)
- `return results.length > 0 ? results[0] : null;` (au lieu de `undefined`)
React Query accepte `null` comme valeur valide mais pas `undefined`.
## Résultat
Les templates non initialisés peuvent maintenant être sélectionnés sans erreur. L'interface affiche correctement un état vide au lieu de crasher.
## Modifications effectuées :
### AdminEmailTemplates.tsx
Ajout de 4 nouveaux types de templates dans la liste :
- "Rappel 3" (value: rappel3)
- "Rappel 4" (value: rappel4)
- "Rappel 5" (value: rappel5)
- "Rappel 6" (value: rappel6)
### AdminRappels.tsx
Ajout des mêmes templates dans TEMPLATE_TYPES avec des délais par défaut :
- Rappel 3 : 14 jours avant
- Rappel 4 : 21 jours avant
- Rappel 5 : 30 jours avant
- Rappel 6 : 60 jours avant
### server/db.ts (initializeDefaultEmailTemplates)
Ajout de 4 nouveaux templates par défaut basés sur le contenu du "Rappel 1" :
- Même structure HTML
- Même message de base
- Prêts à être personnalisés
## Note importante
Ces nouveaux templates ne seront créés que lors de l'initialisation des templates par défaut (bouton "Initialiser les templates par défaut" dans Configuration > Templates d'emails). Si vous avez déjà initialisé les templates, vous devrez créer manuellement ces 4 nouveaux templates ou réinitialiser la base de données.
## Modifications effectuées :
### AdminRappels.tsx
**Dans les dialogues de création et modification :**
- "Type de rappel *" → "Template d'email utilisé *"
**Dans le tableau de liste des rappels :**
- Colonne "Type" → "Template"
Ces modifications rendent plus explicite le fait qu'on sélectionne un template d'email (Rappel 1 ou Rappel 2) qui sera utilisé pour envoyer le rappel automatique.
## Modification effectuée :
Le menu "Rappels" a été ajouté dans la section **CONFIGURATION** du menu de navigation.
**Position :** Après "Import Excel" et avant "Questionnaires"
**Chemin :** `/admin/rappels`
Ce menu permet d'accéder à la page de gestion des rappels automatiques où l'on peut créer, modifier et supprimer des rappels.
## Note
Le menu "Rappels" dans TRAÇABILITÉ (qui pointe vers `/admin/rappels/historique`) reste en place pour consulter l'historique des rappels envoyés.
## Modifications effectuées :
### Backend (server/routers.ts)
- Ajout de la procédure `users.listWithFormateurs` qui retourne :
* Tous les utilisateurs
* Tous les formateurs avec leur statut de compte (hasAccount, user)
- Cette procédure combine les données des tables `users` et `formateurs`
### Frontend (client/src/pages/AdminUsers.tsx)
- Remplacement de `users.list` par `users.listWithFormateurs`
- Ajout d'une section dédiée "Formateurs sans compte utilisateur" affichée en haut de la page
- Cette section liste tous les formateurs qui n'ont pas encore de compte utilisateur
- Bouton "Créer un compte" pour chaque formateur qui :
* Pré-remplit le formulaire avec les données du formateur (nom, email)
* Lie automatiquement le `formateurId`
* Définit le rôle sur "formateur"
## Résultat
Les formateurs existants dans la table `formateurs` sont maintenant visibles dans la page Utilisateurs. L'administrateur peut facilement créer un compte pour chaque formateur en un clic, ce qui lie automatiquement le compte au formateur existant.
## Modifications effectuées :
### Page Formateurs (Configuration > Formateurs)
- Suppression du bouton "Ajouter un formateur"
- Suppression du dialogue de création et des mutations associées
- Ajout d'un message informatif indiquant que la création se fait via Configuration > Utilisateurs
- La page conserve les fonctionnalités de modification et suppression des formateurs existants
### Logique de création
- Les formateurs doivent maintenant être créés uniquement via Configuration > Utilisateurs
- Lors de la création d'un utilisateur avec le rôle "Formateur", celui-ci apparaît automatiquement dans la page Formateurs
- Cette centralisation évite les doublons et simplifie le workflow de gestion
La page Formateurs devient une page de consultation et de gestion (modification email, suppression) plutôt qu'une page de création.
## Modifications effectuées :
### Nouvelle section TRAÇABILITÉ
Création d'une nouvelle section "Traçabilité" regroupant les outils de suivi :
- Établissements
- Notifications
- Suivi Questionnaires
- Rappels (anciennement "Historique" sous Rappels)
### Section ANALYSES simplifiée
- Tableau de bord analytique
- Rapport Public Cible
- Statistiques des rappels (renommé depuis "Rappels")
### Section CONFIGURATION nettoyée
- Suppression du menu "Rappels" et de son sous-menu "Historique" (déplacé vers TRAÇABILITÉ)
Cette réorganisation améliore la clarté en séparant les outils de traçabilité/suivi des outils d'analyse statistique.
## Modifications effectuées :
1. Renommage : "Attestations" → "Attestations de formation" pour plus de clarté
2. Déplacement : "Statistiques" (sous-menu de Rappels) → Section ANALYSES avec le nom "Rappels"
3. Simplification : Le menu "Rappels" dans CONFIGURATION ne contient plus que "Historique"
Cette réorganisation améliore la logique de navigation en plaçant tous les outils d'analyse dans la section ANALYSES.
Le menu "Notifications" a été déplacé de la section CONFIGURATION vers la section ANALYSES pour une meilleure organisation logique, car les notifications sont davantage liées au suivi et à l'analyse qu'à la configuration du système.
## Authentification formateur
- Ajout du rôle "formateur" dans l'enum de la table users
- Ajout du champ formateurId pour lier un compte à un formateur
- Mise à jour de l'interface AdminUsers avec sélection du formateur
- Redirection automatique selon le rôle (admin → /admin, formateur → /formateur)
- Badges et filtres mis à jour pour inclure le rôle formateur
## Upload logo et signature
- Création du composant ImageUpload.tsx avec prévisualisation
- Création de l'endpoint /api/upload-image avec multer pour l'upload vers S3
- Intégration dans AdminAttestations.tsx
- Modification du service PDF pour inclure le logo (en haut à droite) et la signature (en bas)
- Mise à jour des procédures tRPC pour accepter logoUrl, logoS3Key, signatureUrl, signatureS3Key
✅ Infrastructure backend :
- Tables attestations et configAttestation en base de données
- Service de génération PDF avec PDFKit (attestationService.ts)
- Génération automatique de PDF avec template personnalisable
- Upload automatique vers S3 avec URLs publiques
- Procédures tRPC pour générer, récupérer et configurer
✅ Interface utilisateur :
- Page de configuration des attestations (/admin/attestations)
- Personnalisation du texte avec variables dynamiques (nomComplet, nomFormation, dateDebut, dateFin)
- Configuration du signataire (nom et fonction)
- Bouton "Générer" dans la page de validation des présences formateur
- Génération automatique avec ouverture du PDF dans un nouvel onglet
✅ Fonctionnalités :
- Vérification des doublons (une seule attestation par apprenant/séquence)
- Génération uniquement pour les apprenants marqués comme présents
- PDF professionnel avec détails de la formation et dates
- Stockage permanent sur S3
📋 Améliorations futures possibles :
- Upload de logo et signature personnalisés
- Envoi automatique par email aux apprenants
- Espace apprenant pour télécharger les attestations
✅ Infrastructure backend complète :
- Tables attestations et configAttestation en base de données
- Service de génération PDF (attestationService.ts) avec PDFKit
- Procédures tRPC pour générer, récupérer et configurer les attestations
- Stockage S3 des PDF générés
✅ Interface d'administration :
- Page de configuration des attestations (/admin/attestations)
- Personnalisation du texte avec variables dynamiques
- Champs pour signataire (nom et fonction)
- Placeholders pour logo et signature (à implémenter en phase 2)
📋 À faire en Phase 2 :
- Upload des images (logo/signature) vers S3
- Génération automatique après validation de présence
- Envoi automatique par email aux apprenants
- Espace apprenant pour télécharger les attestations