From c4f9cb9ebc1e556d6a7f2858caeb7167bdb37084 Mon Sep 17 00:00:00 2001 From: Manus Sandbox Date: Tue, 25 Nov 2025 14:22:36 -0500 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20Correction=20du=20bug=20d'import?= =?UTF-8?q?=20Excel=20-=20Retrait=20de=20la=20colonne=20publicCible=20inex?= =?UTF-8?q?istante=20dans=20la=20table=20formations.=20Ajout=20de=20logs?= =?UTF-8?q?=20de=20d=C3=A9bogage=20et=20am=C3=A9lioration=20de=20la=20gest?= =?UTF-8?q?ion=20des=20erreurs=20d'import.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .manus/db/db-query-1764098411417.json | 66 +++++++++++++++++++++ .manus/db/db-query-1764098425699.json | 66 +++++++++++++++++++++ .manus/db/db-query-error-1764098316699.json | 8 +++ server/importExcel.ts | 24 +++++++- test-import.ts | 29 +++++++++ todo.md | 13 ++++ 6 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 .manus/db/db-query-1764098411417.json create mode 100644 .manus/db/db-query-1764098425699.json create mode 100644 .manus/db/db-query-error-1764098316699.json create mode 100644 test-import.ts diff --git a/.manus/db/db-query-1764098411417.json b/.manus/db/db-query-1764098411417.json new file mode 100644 index 0000000..d90811d --- /dev/null +++ b/.manus/db/db-query-1764098411417.json @@ -0,0 +1,66 @@ +{ + "query": "DESCRIBE formations;", + "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 DESCRIBE formations;", + "rows": [ + { + "Field": "id", + "Type": "int(11)", + "Null": "NO", + "Key": "PRI", + "Default": "NULL", + "Extra": "auto_increment" + }, + { + "Field": "nom", + "Type": "varchar(255)", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "description", + "Type": "text", + "Null": "YES", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "lienUnique", + "Type": "varchar(100)", + "Null": "NO", + "Key": "UNI", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "actif", + "Type": "tinyint(1)", + "Null": "NO", + "Key": "", + "Default": "1", + "Extra": "" + }, + { + "Field": "createdAt", + "Type": "timestamp", + "Null": "NO", + "Key": "", + "Default": "CURRENT_TIMESTAMP", + "Extra": "" + }, + { + "Field": "updatedAt", + "Type": "timestamp", + "Null": "NO", + "Key": "", + "Default": "CURRENT_TIMESTAMP", + "Extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + } + ], + "messages": [], + "stdout": "Field\tType\tNull\tKey\tDefault\tExtra\nid\tint(11)\tNO\tPRI\tNULL\tauto_increment\nnom\tvarchar(255)\tNO\t\tNULL\t\ndescription\ttext\tYES\t\tNULL\t\nlienUnique\tvarchar(100)\tNO\tUNI\tNULL\t\nactif\ttinyint(1)\tNO\t\t1\t\ncreatedAt\ttimestamp\tNO\t\tCURRENT_TIMESTAMP\t\nupdatedAt\ttimestamp\tNO\t\tCURRENT_TIMESTAMP\tDEFAULT_GENERATED on update CURRENT_TIMESTAMP\n", + "stderr": "", + "execution_time_ms": 54 +} \ No newline at end of file diff --git a/.manus/db/db-query-1764098425699.json b/.manus/db/db-query-1764098425699.json new file mode 100644 index 0000000..3ef1f63 --- /dev/null +++ b/.manus/db/db-query-1764098425699.json @@ -0,0 +1,66 @@ +{ + "query": "SHOW COLUMNS FROM formations;", + "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 SHOW COLUMNS FROM formations;", + "rows": [ + { + "Field": "id", + "Type": "int(11)", + "Null": "NO", + "Key": "PRI", + "Default": "NULL", + "Extra": "auto_increment" + }, + { + "Field": "nom", + "Type": "varchar(255)", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "description", + "Type": "text", + "Null": "YES", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "lienUnique", + "Type": "varchar(100)", + "Null": "NO", + "Key": "UNI", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "actif", + "Type": "tinyint(1)", + "Null": "NO", + "Key": "", + "Default": "1", + "Extra": "" + }, + { + "Field": "createdAt", + "Type": "timestamp", + "Null": "NO", + "Key": "", + "Default": "CURRENT_TIMESTAMP", + "Extra": "" + }, + { + "Field": "updatedAt", + "Type": "timestamp", + "Null": "NO", + "Key": "", + "Default": "CURRENT_TIMESTAMP", + "Extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + } + ], + "messages": [], + "stdout": "Field\tType\tNull\tKey\tDefault\tExtra\nid\tint(11)\tNO\tPRI\tNULL\tauto_increment\nnom\tvarchar(255)\tNO\t\tNULL\t\ndescription\ttext\tYES\t\tNULL\t\nlienUnique\tvarchar(100)\tNO\tUNI\tNULL\t\nactif\ttinyint(1)\tNO\t\t1\t\ncreatedAt\ttimestamp\tNO\t\tCURRENT_TIMESTAMP\t\nupdatedAt\ttimestamp\tNO\t\tCURRENT_TIMESTAMP\tDEFAULT_GENERATED on update CURRENT_TIMESTAMP\n", + "stderr": "", + "execution_time_ms": 51 +} \ No newline at end of file diff --git a/.manus/db/db-query-error-1764098316699.json b/.manus/db/db-query-error-1764098316699.json new file mode 100644 index 0000000..be1c920 --- /dev/null +++ b/.manus/db/db-query-error-1764098316699.json @@ -0,0 +1,8 @@ +{ + "query": "SELECT id, nom, description, publicCible, lienUnique, createdAt FROM formations ORDER BY createdAt DESC LIMIT 10;", + "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 id, nom, description, publicCible, lienUnique, createdAt FROM formations ORDER BY createdAt DESC LIMIT 10;", + "returncode": 1, + "logs": [ + "ERROR 1054 (42S22) at line 1: Unknown column 'publiccible' in 'field list'" + ] +} \ No newline at end of file diff --git a/server/importExcel.ts b/server/importExcel.ts index d0e1d38..84300d6 100644 --- a/server/importExcel.ts +++ b/server/importExcel.ts @@ -192,27 +192,47 @@ export async function importToDatabase( const formationIdMap = new Map(); // Importer les formations + console.log(`[Import] Début import de ${formations.length} formations`); for (const formation of formations) { try { + console.log(`[Import] Création formation: ${formation.nom}`); const result = await db.insert(formationsTable).values({ nom: formation.nom, description: formation.description, - publicCible: formation.publicCible, lienUnique: generateUniqueLien(), }); const formationId = Number(result.insertId); formationIdMap.set(formation.nom.toLowerCase(), formationId); + console.log(`[Import] Formation créée avec ID ${formationId}, ajoutée à la map avec clé: "${formation.nom.toLowerCase()}"`); formationsCreated++; } catch (error: any) { + console.error(`[Import] Erreur formation "${formation.nom}":`, error); errors.push(`Erreur lors de la création de la formation "${formation.nom}": ${error.message}`); } } + console.log(`[Import] Formations créées: ${formationsCreated}, Map size: ${formationIdMap.size}`); + console.log(`[Import] Clés dans la map:`, Array.from(formationIdMap.keys())); + + // Si des erreurs sont survenues lors de la création des formations, arrêter l'import + if (errors.length > 0) { + console.error(`[Import] Arrêt de l'import car ${errors.length} erreur(s) lors de la création des formations`); + return { + success: false, + formationsCreated, + sequencesCreated: 0, + errors, + warnings, + }; + } // Importer les séquences + console.log(`[Import] Début import de ${sequences.length} séquences`); for (const sequence of sequences) { try { - const formationId = formationIdMap.get(sequence.formationNom.toLowerCase()); + const searchKey = sequence.formationNom.toLowerCase(); + console.log(`[Import] Recherche formation pour séquence "${sequence.nom}" avec clé: "${searchKey}"`); + const formationId = formationIdMap.get(searchKey); if (!formationId) { errors.push(`Formation "${sequence.formationNom}" non trouvée pour la séquence "${sequence.nom}"`); continue; diff --git a/test-import.ts b/test-import.ts new file mode 100644 index 0000000..b37aa20 --- /dev/null +++ b/test-import.ts @@ -0,0 +1,29 @@ +import { parseExcelFile, validateImportData } from './server/importExcel'; +import { readFileSync } from 'fs'; + +const buffer = readFileSync('/home/ubuntu/upload/template_import_formations_test.xlsx'); +const { formations, sequences } = parseExcelFile(buffer); + +console.log('=== FORMATIONS PARSÉES ==='); +console.log(`Total: ${formations.length}`); +formations.forEach((f, i) => { + console.log(`${i}: nom="${f.nom}", desc="${f.description}", public="${f.publicCible}"`); +}); + +console.log('\n=== SÉQUENCES PARSÉES ==='); +console.log(`Total: ${sequences.length}`); +sequences.forEach((s, i) => { + console.log(`${i}: formation="${s.formationNom}", nom="${s.nom}", lieu="${s.lieu}"`); +}); + +console.log('\n=== VALIDATION ==='); +const validation = validateImportData(formations, sequences); +console.log(`Valid: ${validation.valid}`); +if (validation.errors.length > 0) { + console.log('Erreurs:'); + validation.errors.forEach(e => console.log(` - ${e}`)); +} +if (validation.warnings.length > 0) { + console.log('Avertissements:'); + validation.warnings.forEach(w => console.log(` - ${w}`)); +} diff --git a/todo.md b/todo.md index 07a92f0..f2a05f2 100644 --- a/todo.md +++ b/todo.md @@ -664,3 +664,16 @@ - [x] Vérifier le schéma de la table formations - [x] Corriger le nom de colonne dans importExcel.ts (lienInscription → lienUnique) - [x] Tester l'import après correction + +## Bug import Excel - Formation non trouvée après création + +- [ ] Analyser le fichier Excel de test fourni +- [ ] Identifier pourquoi la formation n'est pas trouvée dans la map +- [ ] Corriger la logique d'import +- [ ] Tester avec le fichier Excel fourni + +## Bug import Excel - Erreur nom de colonne publicCible + +- [x] Vérifier le schéma de la table formations en base de données (publicCible n'existe pas dans formations) +- [x] Corriger le code d'import (retiré publicCible de l'insertion formations) +- [x] Tester l'import après correction