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:
58
.manus/db/db-query-1764099145203.json
Normal file
58
.manus/db/db-query-1764099145203.json
Normal 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
|
||||||
|
}
|
||||||
@@ -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
46
test-import-direct.ts
Normal 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);
|
||||||
|
});
|
||||||
7
todo.md
7
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] 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
|
||||||
|
|||||||
Reference in New Issue
Block a user