Checkpoint: Checkpoint saved: Ajout de la colonne "Type d'envoi" dans l'historique des rappels et nettoyage des anciens logs erronés
**Améliorations apportées :**
1. **Colonne "Type d'envoi" avec badge coloré** :
- Ajout d'une nouvelle colonne dans l'interface d'historique des rappels
- Badge bleu pour les tests ("Test")
- Badge vert pour les envois automatiques ("Automatique")
- Permet de distinguer visuellement les envois de test des envois réels
2. **Correction des filtres** :
- Correction de l'enum du statut : "succes"/"echec" au lieu de "success"/"failed"
- Correction des noms de colonnes : "email" au lieu de "emailDestinataire", "type" au lieu de "typeRappel"
3. **Nettoyage des anciens logs** :
- Ajout d'une procédure tRPC `nettoyerLogsErrones` pour supprimer les logs sans email
- Exécution de la requête SQL sur le VPS pour nettoyer les données erronées
- Tous les logs créés avant la correction du schéma ont été supprimés
**Fichiers modifiés :**
- client/src/pages/admin/AdminRappelsHistorique.tsx : Ajout de la colonne Type d'envoi avec badges colorés
- server/routers.ts : Ajout de la procédure nettoyerLogsErrones + correction des enums
**Résultat :**
- L'historique des rappels affiche maintenant clairement si un envoi est un test ou automatique
- Les anciens logs erronés ont été supprimés de la base de données
- Les statistiques sont maintenant plus fiables et précises
Déployé sur le VPS de production (https://formations.itinova.org)
This commit is contained in:
@@ -23,7 +23,7 @@ export default function AdminRappelsHistorique() {
|
||||
dateDebut: "",
|
||||
dateFin: "",
|
||||
sequenceId: undefined as number | undefined,
|
||||
statut: undefined as "success" | "failed" | undefined,
|
||||
statut: undefined as "succes" | "echec" | undefined,
|
||||
email: "",
|
||||
limit: 50,
|
||||
offset: 0,
|
||||
@@ -134,8 +134,8 @@ export default function AdminRappelsHistorique() {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">Tous les statuts</SelectItem>
|
||||
<SelectItem value="success">Succès</SelectItem>
|
||||
<SelectItem value="failed">Échec</SelectItem>
|
||||
<SelectItem value="succes">Succès</SelectItem>
|
||||
<SelectItem value="echec">Échec</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@@ -190,6 +190,7 @@ export default function AdminRappelsHistorique() {
|
||||
<TableHead>Date envoi</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead>Type</TableHead>
|
||||
<TableHead>Type d'envoi</TableHead>
|
||||
<TableHead>Statut</TableHead>
|
||||
<TableHead>Tentatives</TableHead>
|
||||
<TableHead>Erreur</TableHead>
|
||||
@@ -201,15 +202,26 @@ export default function AdminRappelsHistorique() {
|
||||
<TableCell className="whitespace-nowrap">
|
||||
{format(new Date(log.dateEnvoi), "dd/MM/yyyy HH:mm", { locale: fr })}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">{log.emailDestinataire}</TableCell>
|
||||
<TableCell className="font-medium">{log.email}</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">
|
||||
{log.typeRappel === "rappel" ? "J-7" : "J-1"}
|
||||
{log.type}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={log.statut === "success" ? "default" : "destructive"}>
|
||||
{log.statut === "success" ? "Succès" : "Échec"}
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={log.typeEnvoi === "test"
|
||||
? "bg-blue-50 text-blue-700 border-blue-200"
|
||||
: "bg-green-50 text-green-700 border-green-200"
|
||||
}
|
||||
>
|
||||
{log.typeEnvoi === "test" ? "Test" : "Automatique"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={log.statut === "succes" ? "default" : "destructive"}>
|
||||
{log.statut === "succes" ? "Succès" : "Échec"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { generateExcelExport, generatePDFExport, generateFeuillePresence } from
|
||||
import { parseExcelFile, validateImportData, importToDatabase } from "./importExcel";
|
||||
import crypto from "crypto";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { sql } from "drizzle-orm";
|
||||
|
||||
// Procédure admin uniquement
|
||||
const adminProcedure = protectedProcedure.use(({ ctx, next }) => {
|
||||
@@ -1546,6 +1547,27 @@ export const appRouter = router({
|
||||
const { getEvolutionEnvois } = await import('./rappelDb');
|
||||
return getEvolutionEnvois();
|
||||
}),
|
||||
|
||||
// Nettoyer les anciens logs erronés (avant la correction du schéma)
|
||||
nettoyerLogsErrones: adminProcedure
|
||||
.mutation(async () => {
|
||||
const database = await db.getDb();
|
||||
if (!database) throw new Error("Database not available");
|
||||
|
||||
// Supprimer tous les logs qui n'ont pas d'email (champ obligatoire manquant)
|
||||
const result = await database.execute(sql`
|
||||
DELETE FROM logsRappels
|
||||
WHERE email IS NULL OR email = ''
|
||||
`);
|
||||
|
||||
const nbSupprimes = Array.isArray(result) ? 0 : (result as any).affectedRows || 0;
|
||||
|
||||
return {
|
||||
success: true,
|
||||
nbSupprimes,
|
||||
message: `${nbSupprimes} log(s) erroné(s) supprimé(s)`,
|
||||
};
|
||||
}),
|
||||
}),
|
||||
|
||||
emailConfig: router({
|
||||
|
||||
2
todo.md
2
todo.md
@@ -833,3 +833,5 @@
|
||||
- [x] Supprimer les boutons "Aperçu rappel J-7", "Envoyer rappel J-7", "Aperçu rappel J-1", "Envoyer rappel J-1" de la fenêtre de détails des séquences
|
||||
- [x] Corriger le bouton "Tester le rappel" pour enregistrer les envois dans l'historique des rappels (table logsRappels)
|
||||
- [x] Corriger l'enregistrement des logs de rappels : type erroné (J-1 au lieu de J+2), statut erroné (success/failed au lieu de succes/echec), email erroné (emailDestinataire au lieu de email)
|
||||
- [x] Ajouter une colonne "Type d'envoi" avec badge coloré dans l'interface d'historique des rappels
|
||||
- [x] Nettoyer les anciens logs erronés de la base de données
|
||||
|
||||
Reference in New Issue
Block a user