Checkpoint: Correction complète du bug d'import Excel - Utilisation de $returningId() pour récupérer les IDs après insertion (formations et séquences), ajout de la colonne ordre obligatoire pour les dates de formation. L'import fonctionne maintenant correctement.

This commit is contained in:
Manus Sandbox
2025-11-25 14:33:57 -05:00
parent c4f9cb9ebc
commit 46f8a6bcfd
4 changed files with 120 additions and 7 deletions

View File

@@ -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
}

View File

@@ -196,13 +196,13 @@ export async function importToDatabase(
for (const formation of formations) { for (const formation of formations) {
try { try {
console.log(`[Import] Création formation: ${formation.nom}`); 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, nom: formation.nom,
description: formation.description, description: formation.description,
lienUnique: generateUniqueLien(), lienUnique: generateUniqueLien(),
}); }).$returningId();
const formationId = Number(result.insertId); const formationId = result.id;
formationIdMap.set(formation.nom.toLowerCase(), formationId); formationIdMap.set(formation.nom.toLowerCase(), formationId);
console.log(`[Import] Formation créée avec ID ${formationId}, ajoutée à la map avec clé: "${formation.nom.toLowerCase()}"`); console.log(`[Import] Formation créée avec ID ${formationId}, ajoutée à la map avec clé: "${formation.nom.toLowerCase()}"`);
formationsCreated++; formationsCreated++;
@@ -238,7 +238,7 @@ export async function importToDatabase(
continue; continue;
} }
const result = await db.insert(sequencesTable).values({ const [result] = await db.insert(sequencesTable).values({
formationId, formationId,
nom: sequence.nom, nom: sequence.nom,
lieu: sequence.lieu, lieu: sequence.lieu,
@@ -246,16 +246,18 @@ export async function importToDatabase(
capaciteMax: sequence.capaciteMax, capaciteMax: sequence.capaciteMax,
dateBlocage: new Date(sequence.dateBlocage), dateBlocage: new Date(sequence.dateBlocage),
statut: sequence.statut, statut: sequence.statut,
}); }).$returningId();
const sequenceId = Number(result.insertId); const sequenceId = result.id;
// Insérer les dates de formation // 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({ await db.insert(datesFormation).values({
sequenceId, sequenceId,
dateDebut: new Date(date.debut), dateDebut: new Date(date.debut),
dateFin: new Date(date.fin), dateFin: new Date(date.fin),
ordre: i + 1,
}); });
} }

46
test-import-direct.ts Normal file
View File

@@ -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);
});

View File

@@ -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] 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] Corriger le code d'import (retiré publicCible de l'insertion formations)
- [x] Tester l'import après correction - [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