diff --git a/server/rappelScheduler.ts b/server/rappelScheduler.ts index 7d3e393..3575dfb 100644 --- a/server/rappelScheduler.ts +++ b/server/rappelScheduler.ts @@ -52,25 +52,45 @@ async function processRappel(rappel: any) { console.log(`[Rappels] Recherche des séquences débutant le ${dateCible.toLocaleDateString()}`); - // Trouver toutes les séquences dont la première date correspond à la date cible - const sequencesConcernees = await db + // CORRECTION DU BUG: Récupérer d'abord toutes les séquences + const toutesSequences = await db .select({ sequence: sequences, formation: formations, - dateFormation: datesFormation, formateur: formateurs, }) - .from(datesFormation) - .leftJoin(sequences, eq(datesFormation.sequenceId, sequences.id)) + .from(sequences) .leftJoin(formations, eq(sequences.formationId, formations.id)) - .leftJoin(formateurs, eq(sequences.formateurId, formateurs.id)) - .where( - and( - eq(datesFormation.ordre, 1), // Première date seulement - gte(datesFormation.dateDebut, dateCible), - lte(datesFormation.dateDebut, dateCibleFin) + .leftJoin(formateurs, eq(sequences.formateurId, formateurs.id)); + + // Filtrer les séquences dont la première date correspond à la date cible + const sequencesConcernees = []; + for (const { sequence, formation, formateur } of toutesSequences) { + if (!sequence || !formation) continue; + + // Récupérer la première date de cette séquence + const premiereDates = await db + .select() + .from(datesFormation) + .where( + and( + eq(datesFormation.sequenceId, sequence.id), + eq(datesFormation.ordre, 1) + ) ) - ); + .limit(1); + + if (premiereDates.length === 0) continue; + + const premiereDate = premiereDates[0]; + const dateDebut = new Date(premiereDate.dateDebut); + dateDebut.setHours(0, 0, 0, 0); + + // Vérifier si cette première date correspond à la date cible + if (dateDebut >= dateCible && dateDebut <= dateCibleFin) { + sequencesConcernees.push({ sequence, formation, formateur }); + } + } console.log(`[Rappels] ${sequencesConcernees.length} séquence(s) trouvée(s)`); @@ -125,7 +145,7 @@ async function processRappel(rappel: any) { })), lieu: sequence.lieu || "", }); - console.log(`[Rappels] Email J-7 envoyé à ${apprenant.email}`); + console.log(`[Rappels] Email J-7 envoyé à ${apprenant.email} pour la séquence ${sequence.nom}`); } else if (rappel.templateType === "rappelJ1") { // Rappel J-1 await sendRappelJ1Email({ @@ -142,7 +162,7 @@ async function processRappel(rappel: any) { })), lieu: sequence.lieu || "", }); - console.log(`[Rappels] Email J-1 envoyé à ${apprenant.email}`); + console.log(`[Rappels] Email J-1 envoyé à ${apprenant.email} pour la séquence ${sequence.nom}`); } } catch (emailError) { console.error(`[Rappels] Erreur lors de l'envoi à ${apprenant.email}:`, emailError); diff --git a/todo.md b/todo.md index 2b4018f..14a5cca 100644 --- a/todo.md +++ b/todo.md @@ -70,3 +70,10 @@ ### Tests - [x] Tester toutes les fonctionnalités de l'espace formateur + +## Correction bug rappels multiples + +- [x] Analyser le code du scheduler de rappels +- [x] Identifier pourquoi plusieurs emails sont envoyés +- [x] Corriger la logique pour envoyer un seul email par séquence +- [x] Tester avec la formation JetSki du 15/12/2025