/** * Service d'export des données en Excel et PDF */ import * as XLSX from 'xlsx'; import { jsPDF } from 'jspdf'; import autoTable from 'jspdf-autotable'; interface InscriptionExport { nom: string; prenom: string; email: string; codeEtablissement: string; fonction: string; statut: string; dateInscription: Date; } interface SequenceInfo { formationNom: string; sequenceNom: string; dates: Array<{ dateDebut: Date; dateFin: Date; ordre: number }>; lieu: string; inscriptions: InscriptionExport[]; } interface ApprenantPresence { nom: string; prenom: string; codeEtablissement: string; fonction: string; } interface FeuillePresenceInfo { formationNom: string; sequenceNom: string; dates: Array<{ dateDebut: Date; dateFin: Date; ordre: number }>; lieu: string; apprenants: ApprenantPresence[]; } /** * Génère un fichier Excel avec la liste des inscrits */ export function generateExcelExport(sequenceInfo: SequenceInfo): Buffer { // Préparer les données const data = sequenceInfo.inscriptions.map(i => ({ 'Nom': i.nom, 'Prénom': i.prenom, 'Email': i.email, 'Code établissement': i.codeEtablissement, 'Fonction': i.fonction === 'directeur' ? 'Directeur' : i.fonction === 'chef_service' ? 'Chef de service' : 'Autre', 'Statut': i.statut === 'confirmee' ? 'Confirmée' : i.statut === 'liste_attente' ? 'Liste d\'attente' : 'Annulée', 'Date d\'inscription': i.dateInscription.toLocaleDateString('fr-FR'), })); // Créer le workbook const wb = XLSX.utils.book_new(); // Créer la feuille avec les informations de séquence const infoData = [ ['Formation', sequenceInfo.formationNom], ['Séquence', sequenceInfo.sequenceNom], ['Lieu', sequenceInfo.lieu], ['Nombre de dates', sequenceInfo.dates.length.toString()], [], ['DATES DE FORMATION'], ]; // Ajouter les dates sequenceInfo.dates.forEach(date => { infoData.push([ `Date ${date.ordre}`, `Du ${date.dateDebut.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })} au ${date.dateFin.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}` ]); }); infoData.push([]); infoData.push(['Nombre d\'inscrits', sequenceInfo.inscriptions.length.toString()]); infoData.push([]); // Créer la feuille principale const ws = XLSX.utils.aoa_to_sheet(infoData); // Ajouter les données des inscrits XLSX.utils.sheet_add_json(ws, data, { origin: -1 }); // Ajouter la feuille au workbook XLSX.utils.book_append_sheet(wb, ws, 'Inscrits'); // Générer le buffer const excelBuffer = XLSX.write(wb, { type: 'buffer', bookType: 'xlsx' }); return excelBuffer; } /** * Génère un fichier PDF avec la liste des inscrits */ export function generatePDFExport(sequenceInfo: SequenceInfo): Buffer { const doc = new jsPDF(); // Titre doc.setFontSize(18); doc.text('Liste des inscrits', 14, 20); // Informations de séquence doc.setFontSize(10); let yPos = 35; doc.text(`Formation : ${sequenceInfo.formationNom}`, 14, yPos); yPos += 6; doc.text(`Séquence : ${sequenceInfo.sequenceNom}`, 14, yPos); yPos += 6; doc.text(`Lieu : ${sequenceInfo.lieu}`, 14, yPos); yPos += 6; doc.text(`Nombre de dates : ${sequenceInfo.dates.length}`, 14, yPos); yPos += 8; // Dates de formation doc.setFontSize(9); sequenceInfo.dates.forEach(date => { doc.text(`Date ${date.ordre} : ${date.dateDebut.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}`, 14, yPos); yPos += 5; }); yPos += 3; doc.setFontSize(10); doc.text(`Nombre d'inscrits : ${sequenceInfo.inscriptions.length}`, 14, yPos); // Tableau des inscrits const tableData = sequenceInfo.inscriptions.map(i => [ i.nom, i.prenom, i.email, i.codeEtablissement, i.fonction === 'directeur' ? 'Directeur' : i.fonction === 'chef_service' ? 'Chef de service' : 'Autre', i.statut === 'confirmee' ? 'Confirmée' : i.statut === 'liste_attente' ? 'Liste d\'attente' : 'Annulée', ]); autoTable(doc, { startY: yPos + 10, head: [['Nom', 'Prénom', 'Email', 'Code étab.', 'Fonction', 'Statut']], body: tableData, styles: { fontSize: 9 }, headStyles: { fillColor: [37, 99, 235] }, }); return Buffer.from(doc.output('arraybuffer')); } /** * Génère une feuille de présence PDF */ export function generateFeuillePresence(feuilleInfo: FeuillePresenceInfo): Buffer { const doc = new jsPDF(); // Titre doc.setFontSize(18); doc.text('Feuille de présence', 14, 20); // Informations de séquence doc.setFontSize(10); let yPos = 35; doc.text(`Formation : ${feuilleInfo.formationNom}`, 14, yPos); yPos += 6; doc.text(`Séquence : ${feuilleInfo.sequenceNom}`, 14, yPos); yPos += 6; doc.text(`Lieu : ${feuilleInfo.lieu}`, 14, yPos); yPos += 8; // Dates de formation doc.setFontSize(9); feuilleInfo.dates.forEach(date => { doc.text(`Date ${date.ordre} : ${date.dateDebut.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}`, 14, yPos); yPos += 5; }); // Tableau de présence const tableData = feuilleInfo.apprenants.map(i => [ i.nom, i.prenom, i.codeEtablissement, i.fonction === 'directeur' ? 'Directeur' : i.fonction === 'chef_service' ? 'Chef de service' : 'Autre', '', // Colonne signature ]); autoTable(doc, { startY: yPos + 10, head: [['Nom', 'Prénom', 'Code établissement', 'Fonction', 'Signature']], body: tableData, styles: { fontSize: 10, cellPadding: 5 }, headStyles: { fillColor: [37, 99, 235] }, columnStyles: { 4: { cellWidth: 40 }, // Largeur pour la colonne signature }, }); return Buffer.from(doc.output('arraybuffer')); }