Checkpoint: Ajout de la fonctionnalité d'import Excel pour créer des formations et séquences en masse. Inclut le template Excel, la logique backend de parsing et validation, l'interface frontend avec prévisualisation, et la documentation utilisateur complète.

This commit is contained in:
Manus Sandbox
2025-11-25 05:49:13 -05:00
parent 9fffa8c773
commit f5dfb20e9a
10 changed files with 1514 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ import { generateAnalyticsExcel, generateAnalyticsPDF } from "./analyticsExportS
import { TRPCError } from "@trpc/server";
import { sendInscriptionConfirmation, sendGroupEmail } from "./emailService";
import { generateExcelExport, generatePDFExport, generateFeuillePresence } from "./exportService";
import { parseExcelFile, validateImportData, importToDatabase } from "./importExcel";
// Procédure admin uniquement
const adminProcedure = protectedProcedure.use(({ ctx, next }) => {
@@ -72,6 +73,68 @@ export const appRouter = router({
await db.deleteFormation(input.id);
return { success: true };
}),
importExcel: adminProcedure.input(z.object({
fileBase64: z.string(),
})).mutation(async ({ input }) => {
try {
// Décoder le fichier base64
const buffer = Buffer.from(input.fileBase64, 'base64');
// Parser le fichier Excel
const { formations, sequences } = parseExcelFile(buffer);
// Valider les données
const validation = validateImportData(formations, sequences);
if (!validation.valid) {
return {
success: false,
formationsCreated: 0,
sequencesCreated: 0,
errors: validation.errors,
warnings: validation.warnings,
};
}
// Importer dans la base de données
const result = await importToDatabase(formations, sequences);
return {
...result,
warnings: [...validation.warnings, ...result.warnings],
};
} catch (error: any) {
return {
success: false,
formationsCreated: 0,
sequencesCreated: 0,
errors: [`Erreur lors du traitement du fichier: ${error.message}`],
warnings: [],
};
}
}),
previewExcel: adminProcedure.input(z.object({
fileBase64: z.string(),
})).mutation(async ({ input }) => {
try {
const buffer = Buffer.from(input.fileBase64, 'base64');
const { formations, sequences } = parseExcelFile(buffer);
const validation = validateImportData(formations, sequences);
return {
formations,
sequences,
validation,
};
} catch (error: any) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: `Erreur lors de la lecture du fichier: ${error.message}`,
});
}
}),
}),
// ===== APPRENANTS =====