diff --git a/.manus/db/db-query-1764099145203.json b/.manus/db/db-query-1764099145203.json new file mode 100644 index 0000000..06a35c0 --- /dev/null +++ b/.manus/db/db-query-1764099145203.json @@ -0,0 +1,58 @@ +{ + "query": "SHOW COLUMNS FROM datesFormation;", + "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 datesFormation;", + "rows": [ + { + "Field": "id", + "Type": "int(11)", + "Null": "NO", + "Key": "PRI", + "Default": "NULL", + "Extra": "auto_increment" + }, + { + "Field": "sequenceId", + "Type": "int(11)", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "dateDebut", + "Type": "datetime", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "dateFin", + "Type": "datetime", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "ordre", + "Type": "int(11)", + "Null": "NO", + "Key": "", + "Default": "NULL", + "Extra": "" + }, + { + "Field": "createdAt", + "Type": "timestamp", + "Null": "NO", + "Key": "", + "Default": "CURRENT_TIMESTAMP", + "Extra": "" + } + ], + "messages": [], + "stdout": "Field\tType\tNull\tKey\tDefault\tExtra\nid\tint(11)\tNO\tPRI\tNULL\tauto_increment\nsequenceId\tint(11)\tNO\t\tNULL\t\ndateDebut\tdatetime\tNO\t\tNULL\t\ndateFin\tdatetime\tNO\t\tNULL\t\nordre\tint(11)\tNO\t\tNULL\t\ncreatedAt\ttimestamp\tNO\t\tCURRENT_TIMESTAMP\t\n", + "stderr": "", + "execution_time_ms": 63 +} \ No newline at end of file diff --git a/server/importExcel.ts b/server/importExcel.ts index 84300d6..270fa15 100644 --- a/server/importExcel.ts +++ b/server/importExcel.ts @@ -196,13 +196,13 @@ export async function importToDatabase( for (const formation of formations) { try { console.log(`[Import] Création formation: ${formation.nom}`); - const result = await db.insert(formationsTable).values({ + const [result] = await db.insert(formationsTable).values({ nom: formation.nom, description: formation.description, lienUnique: generateUniqueLien(), - }); + }).$returningId(); - const formationId = Number(result.insertId); + const formationId = result.id; 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++; @@ -238,7 +238,7 @@ export async function importToDatabase( continue; } - const result = await db.insert(sequencesTable).values({ + const [result] = await db.insert(sequencesTable).values({ formationId, nom: sequence.nom, lieu: sequence.lieu, @@ -246,16 +246,18 @@ export async function importToDatabase( capaciteMax: sequence.capaciteMax, dateBlocage: new Date(sequence.dateBlocage), statut: sequence.statut, - }); + }).$returningId(); - const sequenceId = Number(result.insertId); + const sequenceId = result.id; // Insérer les dates de formation - for (const date of sequence.dates.slice(0, 4)) { + for (let i = 0; i < Math.min(sequence.dates.length, 4); i++) { + const date = sequence.dates[i]; await db.insert(datesFormation).values({ sequenceId, dateDebut: new Date(date.debut), dateFin: new Date(date.fin), + ordre: i + 1, }); } diff --git a/test-import-direct.ts b/test-import-direct.ts new file mode 100644 index 0000000..c64c6f9 --- /dev/null +++ b/test-import-direct.ts @@ -0,0 +1,46 @@ +import { parseExcelFile, importToDatabase } from './server/importExcel'; +import { readFileSync } from 'fs'; + +async function testImport() { + console.log('=== TEST IMPORT DIRECT ===\n'); + + const buffer = readFileSync('/home/ubuntu/upload/template_import_formations_test.xlsx'); + const { formations, sequences } = parseExcelFile(buffer); + + console.log(`Formations parsées: ${formations.length}`); + formations.forEach((f, i) => { + console.log(` ${i}: "${f.nom}" - "${f.description}" - public: "${f.publicCible}"`); + }); + + console.log(`\nSéquences parsées: ${sequences.length}`); + sequences.forEach((s, i) => { + console.log(` ${i}: formation="${s.formationNom}", nom="${s.nom}"`); + }); + + console.log('\n=== DÉBUT IMPORT EN BASE ===\n'); + const result = await importToDatabase(formations, sequences); + + console.log('\n=== RÉSULTAT ==='); + console.log(`Success: ${result.success}`); + console.log(`Formations créées: ${result.formationsCreated}`); + console.log(`Séquences créées: ${result.sequencesCreated}`); + + if (result.errors.length > 0) { + console.log('\nErreurs:'); + result.errors.forEach(e => console.log(` - ${e}`)); + } + + if (result.warnings.length > 0) { + console.log('\nAvertissements:'); + result.warnings.forEach(w => console.log(` - ${w}`)); + } +} + +testImport().then(() => { + console.log('\n=== TEST TERMINÉ ==='); + process.exit(0); +}).catch(err => { + console.error('\n=== ERREUR FATALE ==='); + console.error(err); + process.exit(1); +}); diff --git a/todo.md b/todo.md index f2a05f2..8ac3b97 100644 --- a/todo.md +++ b/todo.md @@ -677,3 +677,10 @@ - [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 + +## Bug import Excel - Problème persistant "Formation non trouvée" + +- [x] Analyser les logs serveur pour voir si la formation est réellement créée (ID = NaN) +- [x] Vérifier si l'erreur vient de la création ou de la recherche dans la map (problème de récupération ID) +- [x] Corriger le problème identifié (utilisation de $returningId() pour formations et séquences, ajout ordre pour dates) +- [x] Tester l'import et valider que tout fonctionne