Files
formation-manager-itinova/.manus/db/db-query-1768928761210.json
Manus 99c0ee6bae Checkpoint: Correction de l'erreur "Cannot convert undefined or null to object" sur la page /admin/notifications :
**Problème identifié :**
- Incohérence entre le schéma Drizzle (`drizzle/schema.ts`) et le code (`notificationLogsDb.ts`)
- Le schéma utilisait des noms de colonnes et des types d'enum différents de ceux utilisés dans le code
- Cela causait l'erreur "Cannot convert undefined or null to object" lors de la récupération des données

**Corrections appliquées :**

1. **Mise à jour du schéma Drizzle (drizzle/schema.ts) :**
   - Renommé `destinataire` en `emailDestinataire` pour correspondre au code
   - Ajouté la colonne `sujet` (VARCHAR 500)
   - Ajouté la colonne `formateurId` (INT NULL)
   - Ajouté la colonne `metadata` (TEXT NULL)
   - Mis à jour l'enum `type` avec les bonnes valeurs : `remerciement`, `notification_formateur_inscription`, `notification_formateur_annulation`, `alerte_capacite`, `notification_liste_attente`
   - Mis à jour l'enum `statut` avec les bonnes valeurs : `success`, `failed`

2. **Amélioration de la gestion des valeurs null (notificationLogsDb.ts) :**
   - Ajout de vérifications null-safe dans `getNotificationStats()` pour éviter les erreurs lors du calcul du taux de succès
   - Ajout de valeurs par défaut pour `parType` et `evolutionParJour` (tableaux vides si undefined)
   - Ajout d'un mapping des logs pour s'assurer que tous les champs sont bien définis (null au lieu d'undefined)

**Tests réussis :**
-  Onglet "Statistiques" : affiche correctement 24 envois, 100% de succès, répartition par type et évolution par jour
-  Onglet "Historique" : affiche correctement les 24 notifications avec toutes les colonnes (Date, Type, Destinataire, Sujet, Formation/Séquence, Statut)
-  Pagination fonctionnelle (Page 1 sur 2)
-  Filtres disponibles (Type, Statut, Email, Date début, Date fin)

**Résultat :**
 L'erreur "Cannot convert undefined or null to object" est complètement résolue
 La page notifications fonctionne correctement avec toutes ses fonctionnalités
2026-01-20 12:07:33 -05:00

130 lines
4.5 KiB
JSON

{
"query": "SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_TYPE \nFROM INFORMATION_SCHEMA.COLUMNS \nWHERE TABLE_NAME = 'logsNotifications' \nORDER BY ORDINAL_POSITION;",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_TYPE \nFROM INFORMATION_SCHEMA.COLUMNS \nWHERE TABLE_NAME = 'logsNotifications' \nORDER BY ORDINAL_POSITION;",
"rows": [
{
"COLUMN_NAME": "id",
"DATA_TYPE": "int",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "int(11)"
},
{
"COLUMN_NAME": "id",
"DATA_TYPE": "int",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "int(11)"
},
{
"COLUMN_NAME": "type",
"DATA_TYPE": "enum",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "enum('remerciement','notification_formateur_inscription','notification_formateur_annulation','alerte_capacite','notification_liste_attente')"
},
{
"COLUMN_NAME": "type",
"DATA_TYPE": "enum",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "enum('inscription','annulation','capacite_atteinte','place_disponible','remerciement','formateur_inscription','formateur_annulation')"
},
{
"COLUMN_NAME": "sequenceId",
"DATA_TYPE": "int",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "int(11)"
},
{
"COLUMN_NAME": "destinataire",
"DATA_TYPE": "varchar",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "varchar(320)"
},
{
"COLUMN_NAME": "apprenantId",
"DATA_TYPE": "int",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "int(11)"
},
{
"COLUMN_NAME": "sequenceId",
"DATA_TYPE": "int",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "int(11)"
},
{
"COLUMN_NAME": "formateurId",
"DATA_TYPE": "int",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "int(11)"
},
{
"COLUMN_NAME": "apprenantId",
"DATA_TYPE": "int",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "int(11)"
},
{
"COLUMN_NAME": "emailDestinataire",
"DATA_TYPE": "varchar",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "varchar(320)"
},
{
"COLUMN_NAME": "statut",
"DATA_TYPE": "enum",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "enum('succes','echec')"
},
{
"COLUMN_NAME": "sujet",
"DATA_TYPE": "varchar",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "varchar(500)"
},
{
"COLUMN_NAME": "messageErreur",
"DATA_TYPE": "text",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "text"
},
{
"COLUMN_NAME": "dateEnvoi",
"DATA_TYPE": "timestamp",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "timestamp"
},
{
"COLUMN_NAME": "dateEnvoi",
"DATA_TYPE": "timestamp",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "timestamp"
},
{
"COLUMN_NAME": "statut",
"DATA_TYPE": "enum",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "enum('success','failed')"
},
{
"COLUMN_NAME": "messageErreur",
"DATA_TYPE": "text",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "text"
},
{
"COLUMN_NAME": "metadata",
"DATA_TYPE": "text",
"IS_NULLABLE": "YES",
"COLUMN_TYPE": "text"
},
{
"COLUMN_NAME": "createdAt",
"DATA_TYPE": "timestamp",
"IS_NULLABLE": "NO",
"COLUMN_TYPE": "timestamp"
}
],
"messages": [],
"stdout": "COLUMN_NAME\tDATA_TYPE\tIS_NULLABLE\tCOLUMN_TYPE\nid\tint\tNO\tint(11)\nid\tint\tNO\tint(11)\ntype\tenum\tNO\tenum('remerciement','notification_formateur_inscription','notification_formateur_annulation','alerte_capacite','notification_liste_attente')\ntype\tenum\tNO\tenum('inscription','annulation','capacite_atteinte','place_disponible','remerciement','formateur_inscription','formateur_annulation')\nsequenceId\tint\tYES\tint(11)\ndestinataire\tvarchar\tNO\tvarchar(320)\napprenantId\tint\tYES\tint(11)\nsequenceId\tint\tYES\tint(11)\nformateurId\tint\tYES\tint(11)\napprenantId\tint\tYES\tint(11)\nemailDestinataire\tvarchar\tNO\tvarchar(320)\nstatut\tenum\tNO\tenum('succes','echec')\nsujet\tvarchar\tNO\tvarchar(500)\nmessageErreur\ttext\tYES\ttext\ndateEnvoi\ttimestamp\tNO\ttimestamp\ndateEnvoi\ttimestamp\tNO\ttimestamp\nstatut\tenum\tNO\tenum('success','failed')\nmessageErreur\ttext\tYES\ttext\nmetadata\ttext\tYES\ttext\ncreatedAt\ttimestamp\tNO\ttimestamp\n",
"stderr": "",
"execution_time_ms": 66
}