Checkpoint: Modification de la procédure testerRappel pour envoyer le rappel à tous les inscrits confirmés :

- Remplacement de l'envoi au premier inscrit uniquement par un envoi à tous les inscrits confirmés
- Ajout d'un compteur de succès et d'échecs
- Gestion des erreurs individuelles pour chaque envoi
- Message de retour détaillé avec le nombre d'envois réussis et échoués
- Déploiement sur le VPS de production
- Mise à jour du fichier todo.md
This commit is contained in:
Manus
2026-01-15 13:01:17 -05:00
parent e642f23170
commit 820c12d6c1
2 changed files with 52 additions and 35 deletions

View File

@@ -1424,16 +1424,23 @@ export const appRouter = router({
throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun apprenant inscrit confirmé pour cette séquence' }); throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun apprenant inscrit confirmé pour cette séquence' });
} }
// Envoyer le rappel de test au premier inscrit uniquement // Envoyer le rappel de test à l'administrateur connecté
const premierInscrit = inscritsConfirmes[0]; // Envoyer le rappel de test à tous les inscrits confirmés
const apprenant = premierInscrit.apprenant; const { sendRappelEmail } = await import('./emailService');
let nbEnvoyes = 0;
let nbEchecs = 0;
const erreurs: string[] = [];
for (const inscrit of inscritsConfirmes) {
const apprenant = inscrit.apprenant;
if (!apprenant || !apprenant.email) { if (!apprenant || !apprenant.email) {
throw new TRPCError({ code: 'BAD_REQUEST', message: 'Apprenant introuvable ou sans email' }); nbEchecs++;
erreurs.push(`Apprenant ${apprenant?.nom || 'inconnu'}: email manquant`);
continue;
} }
const { sendRappelEmail } = await import('./emailService');
try { try {
await sendRappelEmail({ await sendRappelEmail({
apprenantEmail: apprenant.email, apprenantEmail: apprenant.email,
@@ -1454,18 +1461,27 @@ export const appRouter = router({
attachmentFilename: rappelAUtiliser.nomFichier || undefined, attachmentFilename: rappelAUtiliser.nomFichier || undefined,
attachmentMimeType: rappelAUtiliser.typeFichier || undefined, attachmentMimeType: rappelAUtiliser.typeFichier || undefined,
}); });
nbEnvoyes++;
} catch (error: any) {
nbEchecs++;
erreurs.push(`${apprenant.email}: ${error.message}`);
}
}
if (nbEnvoyes === 0) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: `Aucun email envoyé. Erreurs: ${erreurs.join(', ')}`,
});
}
return { return {
success: true, success: true,
message: `Rappel de test envoyé à ${apprenant.email}`, message: `Rappel de test envoyé à ${nbEnvoyes} apprenant(s)${nbEchecs > 0 ? ` (${nbEchecs} échec(s))` : ''}`,
destinataire: apprenant.email, nbEnvoyes,
nbEchecs,
erreurs: nbEchecs > 0 ? erreurs : undefined,
}; };
} catch (error: any) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: `Erreur lors de l'envoi: ${error.message}`,
});
}
}), }),
historique: adminProcedure historique: adminProcedure

View File

@@ -820,3 +820,4 @@
- [x] Corriger l'erreur de validation du type de rappel dans la procédure testerRappel (typeRappel invalide) - [x] Corriger l'erreur de validation du type de rappel dans la procédure testerRappel (typeRappel invalide)
- [x] Corriger l'erreur "Cannot read properties of undefined (reading 'replace')" lors de l'envoi de test de rappel - [x] Corriger l'erreur "Cannot read properties of undefined (reading 'replace')" lors de l'envoi de test de rappel
- [x] Améliorer le bouton "Tester le rappel" pour utiliser automatiquement le bon template configuré pour la séquence (au lieu de toujours envoyer rappel J-7) - [x] Améliorer le bouton "Tester le rappel" pour utiliser automatiquement le bon template configuré pour la séquence (au lieu de toujours envoyer rappel J-7)
- [x] Modifier la procédure testerRappel pour envoyer le rappel à tous les inscrits confirmés (au lieu du premier uniquement)