166 lines
5.5 KiB
JavaScript
166 lines
5.5 KiB
JavaScript
const { dialog } = require('electron');
|
|
const PDFDocument = require('pdfkit');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
async function generatePDF(data, tipo = 'orden') {
|
|
console.log(`📄 [PDF] Generando PDF tipo "${tipo}" para ${data.length} registros`);
|
|
|
|
if (!Array.isArray(data)) throw new Error('Datos inválidos');
|
|
|
|
const { filePath } = await dialog.showSaveDialog({
|
|
title: tipo === 'orden' ? "Guardar Orden de Mérito" : "Guardar Lista de No Recomendados",
|
|
filters: [{ name: "PDF Files", extensions: ["pdf"] }]
|
|
});
|
|
|
|
if (!filePath) throw new Error('Operación cancelada');
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const doc = new PDFDocument({ margin: 30, size: 'letter', bufferPages: true });
|
|
const stream = fs.createWriteStream(filePath);
|
|
|
|
stream.on('error', err => {
|
|
console.error("❌ Error en el stream:", err.message);
|
|
reject(new Error("Fallo en la escritura del archivo PDF"));
|
|
});
|
|
|
|
stream.on('finish', () => {
|
|
console.log("✅ PDF finalizado:", filePath);
|
|
resolve({ success: true, path: filePath });
|
|
});
|
|
|
|
doc.pipe(stream);
|
|
|
|
const generateContent = async () => {
|
|
try {
|
|
const logoLeft = path.join(__dirname, 'assets', 'imagen1.png');
|
|
const logoRight = path.join(__dirname, 'assets', 'imagen2.png');
|
|
|
|
const logoWidth = 60; // Tamaño unificado para ambos logos
|
|
|
|
if (fs.existsSync(logoLeft)) {
|
|
doc.image(logoLeft, 30, 30, { width: logoWidth });
|
|
}
|
|
|
|
if (fs.existsSync(logoRight)) {
|
|
doc.image(logoRight, doc.page.width - 30 - logoWidth, 30, { width: logoWidth });
|
|
}
|
|
|
|
// Espacio para los logos (que están a altura Y = 30), dejamos un poco más abajo el texto
|
|
const headerStartY = 100;
|
|
|
|
doc.font('Helvetica-Bold')
|
|
.fontSize(10)
|
|
.text('REPÚBLICA BOLIVARIANA DE VENEZUELA', { align: 'center', baseline: 'top', continued: false })
|
|
.moveDown(0.5)
|
|
.text('MINISTERIO DEL PODER POPULAR PARA LA DEFENSA', { align: 'center' })
|
|
.moveDown(0.5)
|
|
.text('EJÉRCITO BOLIVARIANO', { align: 'center' })
|
|
.moveDown(0.5)
|
|
.text('DIRECCIÓN DE TECNOLOGIA DE LA INFORMACIÓN Y LAS COMUNICACIONES', { align: 'center' });
|
|
|
|
doc.moveDown(2); // espacio después del encabezado
|
|
|
|
|
|
// Título según tipo
|
|
const title = tipo === 'orden' ? 'ORDEN DE MÉRITO OFICIAL' : 'LISTADO DE NO RECOMENDADOS';
|
|
doc.fontSize(12).text(title, { align: 'center' }).moveDown(2);
|
|
|
|
// Filtrado de data
|
|
const isOrden = tipo === 'orden';
|
|
const filteredData = isOrden
|
|
? [...data].sort((a, b) => (b.resultado ?? b.niea ?? 0) - (a.resultado ?? a.niea ?? 0))
|
|
: data.filter(item => !item.condicion?.toLowerCase().includes('recomendado'));
|
|
|
|
// Columnas
|
|
const headers = isOrden
|
|
? ['ID', 'GRADO', 'NOMBRE Y APELLIDO', 'CÉDULA', 'NIEA', 'RESULTADO']
|
|
: ['ID', 'GRADO', 'NOMBRE Y APELLIDO', 'CÉDULA', 'MOTIVO'];
|
|
const widths = isOrden
|
|
? [30, 70, 200, 90, 60, 60]
|
|
: [30, 70, 220, 90, 100];
|
|
|
|
let y = doc.y + 10;
|
|
|
|
doc.font('Helvetica-Bold').fontSize(9);
|
|
drawRow(y, headers, widths);
|
|
y += 22;
|
|
|
|
filteredData.forEach((item, index) => {
|
|
if (y > doc.page.height - 100) {
|
|
doc.addPage();
|
|
y = 40;
|
|
}
|
|
|
|
const row = isOrden
|
|
? [
|
|
index + 1,
|
|
item.grado || 'N/D',
|
|
item.nombreApellido || 'N/D',
|
|
item.cedula?.toString() || 'N/D',
|
|
(item.niea ?? item.resultado ?? 0).toFixed(3),
|
|
(item.resultado ?? item.niea ?? 0).toFixed(3)
|
|
]
|
|
: [
|
|
index + 1,
|
|
item.grado || 'N/D',
|
|
item.nombreApellido || 'N/D',
|
|
item.cedula?.toString() || 'N/D',
|
|
item.condicion || 'Sin especificar'
|
|
];
|
|
|
|
doc.font('Helvetica').fontSize(8);
|
|
drawRow(y, row, widths);
|
|
y += 22;
|
|
});
|
|
|
|
// Firmas
|
|
const signatureY = y + 30;
|
|
doc.fontSize(9)
|
|
.text('_________________________', 50, signatureY, { width: 200, align: 'center' })
|
|
.text('CNEL MIGUEL J. RODRÍGUEZ', 50, signatureY + 15, { width: 200, align: 'center' })
|
|
.text('_________________________', doc.page.width - 250, signatureY, { width: 200, align: 'center' })
|
|
.text('MAYO JOSÉ M. SÁNCHEZ', doc.page.width - 250, signatureY + 15, { width: 200, align: 'center' });
|
|
|
|
} catch (err) {
|
|
throw new Error("Contenido falló: " + err.message);
|
|
}
|
|
};
|
|
|
|
function drawRow(y, rowData, widths) {
|
|
let x = 30;
|
|
rowData.forEach((text, i) => {
|
|
doc.text(text.toString(), x + 5, y + 5, {
|
|
width: widths[i] - 10,
|
|
height: 20,
|
|
align: 'left',
|
|
ellipsis: true
|
|
});
|
|
x += widths[i];
|
|
});
|
|
drawBorders(y, widths);
|
|
}
|
|
|
|
function drawBorders(y, widths) {
|
|
let x = 30;
|
|
widths.forEach((w, i) => {
|
|
if (i < widths.length - 1) {
|
|
doc.moveTo(x + w, y).lineTo(x + w, y + 22).stroke();
|
|
}
|
|
x += w;
|
|
});
|
|
doc.moveTo(30, y).lineTo(doc.page.width - 30, y).stroke();
|
|
}
|
|
|
|
generateContent()
|
|
.then(() => doc.end())
|
|
.catch(err => {
|
|
console.error("❌ Error al generar contenido:", err.message);
|
|
doc.end();
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
|
|
module.exports = { generatePDF };
|