utn-cli 2.0.87 → 2.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/frontend.js +38 -11
- package/package.json +1 -1
- package/templates/backend/servicios/Nucleo/LogoUTN.png +0 -0
- package/templates/backend/servicios/Nucleo/Miscelaneas.js +31 -388
- package/templates/backend/servicios/Nucleo/ReporteHTML.js +235 -0
- package/templates/backend/servicios/Nucleo/ReportePDF.js +797 -0
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.html +2 -2
- package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.css +12 -0
- package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.css +50 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
const { ejecutarConsultaSIGU } = require('./db.js');
|
|
2
|
+
|
|
3
|
+
class ReporteHTML {
|
|
4
|
+
constructor() {}
|
|
5
|
+
|
|
6
|
+
async generarFirmaHTML(Identificador, FechaDeLaFirma) {
|
|
7
|
+
const [persona] = await ejecutarConsultaSIGU("SELECT Identificacion, CONCAT(Nombre, ' ', PrimerApellido, ' ', SegundoApellido) AS NombreCompleto FROM SIGU.SIGU_Personas WHERE Identificador = ?", [Identificador]);
|
|
8
|
+
|
|
9
|
+
if (!persona) return '';
|
|
10
|
+
|
|
11
|
+
const nombre = persona.NombreCompleto;
|
|
12
|
+
const identificacion = persona.Identificacion;
|
|
13
|
+
const instancia = await (async () => {
|
|
14
|
+
try {
|
|
15
|
+
const result = await ejecutarConsultaSIGU(`
|
|
16
|
+
SELECT
|
|
17
|
+
CASE
|
|
18
|
+
WHEN i.TipoDeResponsabilidad = 'Ninguna' THEN sup.Nombre
|
|
19
|
+
ELSE i.Nombre
|
|
20
|
+
END AS Nombre
|
|
21
|
+
FROM SIGU.EstructuraOrganizacional_Instancias i
|
|
22
|
+
LEFT JOIN SIGU.EstructuraOrganizacional_Instancias sup
|
|
23
|
+
ON i.IdentificadorDeInstanciaSuperior = sup.IdentificadorDeInstancia
|
|
24
|
+
WHERE i.Identificador = ?
|
|
25
|
+
`, [Identificador]);
|
|
26
|
+
return result?.[0]?.Nombre || 'N/A';
|
|
27
|
+
} catch {
|
|
28
|
+
return 'N/A';
|
|
29
|
+
}
|
|
30
|
+
})();
|
|
31
|
+
|
|
32
|
+
return ` <div style="
|
|
33
|
+
font-size: 9px;
|
|
34
|
+
border: 1px solid #eee;
|
|
35
|
+
padding: 6px;
|
|
36
|
+
display: inline-flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
background-color: #fcfcfc;
|
|
39
|
+
gap: 8px;
|
|
40
|
+
">
|
|
41
|
+
<div class="logo" style="display:flex; align-items:center;">
|
|
42
|
+
<img src="https://storage.sigu.utn.ac.cr/images/cards/LogoUTN.svg"
|
|
43
|
+
alt="Logo UTN"
|
|
44
|
+
style="height:25px;">
|
|
45
|
+
</div>
|
|
46
|
+
<div style="
|
|
47
|
+
width: 1px;
|
|
48
|
+
height: 50px;
|
|
49
|
+
background-color: #ccc;
|
|
50
|
+
"></div>
|
|
51
|
+
<div style="text-align: left;">
|
|
52
|
+
<strong>Firma electrónica por:</strong><br>
|
|
53
|
+
${nombre}<br>
|
|
54
|
+
Cédula: ${identificacion}<br>
|
|
55
|
+
Instancia: ${instancia}<br>
|
|
56
|
+
Fecha: ${FechaDeLaFirma}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
</div>`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
GenerarReporteHTMLRegistrosVerticales(ElementosParaLaTabla, ParametrosExcluidos = [], ParametrosExtra = [], MostrarEncabezado = true) {
|
|
63
|
+
if (!ElementosParaLaTabla?.length) return '<p>No hay datos para mostrar.</p>';
|
|
64
|
+
|
|
65
|
+
const baseColumnas = Object.keys(ElementosParaLaTabla[0]).filter(col => !ParametrosExcluidos.includes(col));
|
|
66
|
+
const columnas = [...baseColumnas, ...ParametrosExtra.filter(p => !baseColumnas.includes(p))];
|
|
67
|
+
|
|
68
|
+
let htmlFinal = '';
|
|
69
|
+
|
|
70
|
+
ElementosParaLaTabla.forEach((fila, index) => {
|
|
71
|
+
|
|
72
|
+
const filasHTML = columnas.map(col => {
|
|
73
|
+
const valor = fila[col] ?? '-';
|
|
74
|
+
return `
|
|
75
|
+
<tr>
|
|
76
|
+
<th style="width: 20%;">${col}</th>
|
|
77
|
+
<td style="width: 80%;">${valor}</td>
|
|
78
|
+
</tr>
|
|
79
|
+
`;
|
|
80
|
+
}).join('');
|
|
81
|
+
|
|
82
|
+
const encabezadoHTML = MostrarEncabezado ? `
|
|
83
|
+
<div style="background-color: #002f6b; color: white; padding: 6px 10px; font-weight: bold; font-size: 14px;">
|
|
84
|
+
Registro N° ${index + 1}
|
|
85
|
+
</div>
|
|
86
|
+
` : '';
|
|
87
|
+
|
|
88
|
+
htmlFinal += `
|
|
89
|
+
<div style="margin-top: 20px; page-break-inside: avoid; border: 1px solid #ccc; border-radius: 8px; overflow: hidden;">
|
|
90
|
+
|
|
91
|
+
${encabezadoHTML}
|
|
92
|
+
|
|
93
|
+
<table style="border: none; border-radius: 0; margin-top: 0;">
|
|
94
|
+
<tbody>
|
|
95
|
+
${filasHTML}
|
|
96
|
+
</tbody>
|
|
97
|
+
</table>
|
|
98
|
+
|
|
99
|
+
</div>`;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return htmlFinal;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
GenerarReporteHTMLEncabezado(InformacionDeLaDerecha, titulares, marcaDeAgua = '') {
|
|
106
|
+
const date = new Date();
|
|
107
|
+
const year = date.getFullYear();
|
|
108
|
+
|
|
109
|
+
return ` <!DOCTYPE html>
|
|
110
|
+
<html lang="es">
|
|
111
|
+
<head>
|
|
112
|
+
<meta charset="UTF-8">
|
|
113
|
+
<title>${titulares.titulo}</title>
|
|
114
|
+
|
|
115
|
+
<style>
|
|
116
|
+
@media print {
|
|
117
|
+
* { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
|
118
|
+
}
|
|
119
|
+
body { font-family: Roboto, "Helvetica Neue", sans-serif; margin: 8px; }
|
|
120
|
+
.header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px; min-height: 70px; }
|
|
121
|
+
.header > div { flex: 1; }
|
|
122
|
+
.logo { flex-shrink: 0; }
|
|
123
|
+
.title-container { text-align: center; flex-grow: 1; }
|
|
124
|
+
.title { font-size: 16px; font-weight: bold; white-space: nowrap; flex-shrink: 0; }
|
|
125
|
+
.subtitle { font-size: 13px; font-weight: bold; margin-top: 4px; }
|
|
126
|
+
.info { text-align: right; font-size: 11px; margin-left: 10px; flex-shrink: 0; }
|
|
127
|
+
table { width: 100%; border-collapse: separate; border-spacing: 0; border-radius: 10px; overflow: hidden; }
|
|
128
|
+
th, td { border: 1px solid #ccc; padding: 4px; text-align: left; font-size: 12px; }
|
|
129
|
+
th { background-color: #002f6b; color: white; }
|
|
130
|
+
tr:nth-child(even) { background-color: #f9f9f9; }
|
|
131
|
+
td:last-child { width: 100px; }
|
|
132
|
+
hr { border: none; border-top: 2px solid #838383; margin: 8px 0; }
|
|
133
|
+
.watermark { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(-45deg); font-size: 80px; color: rgba(100, 100, 100, 0.09); font-weight: bold; z-index: 999; white-space: nowrap; pointer-events: none; }
|
|
134
|
+
</style>
|
|
135
|
+
|
|
136
|
+
</head>
|
|
137
|
+
<body>
|
|
138
|
+
<div class="watermark">${marcaDeAgua}</div>
|
|
139
|
+
<div class="header">
|
|
140
|
+
<div class="logo">
|
|
141
|
+
<img src="https://storage.sigu.utn.ac.cr/images/cards/LogoUTN.svg" alt="Logo UTN" style="height:50px;">
|
|
142
|
+
</div>
|
|
143
|
+
<div class="title-container">
|
|
144
|
+
<div class="title">Universidad Técnica Nacional</div>
|
|
145
|
+
<div class="subtitle">${titulares.primerSubtitulo}</div>
|
|
146
|
+
<div class="subtitle">${titulares.segundoSubtitulo}</div>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="info">
|
|
149
|
+
${InformacionDeLaDerecha}
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
</div> `;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
GenerarReporteHTMLFecha() {
|
|
156
|
+
const now = new Date();
|
|
157
|
+
|
|
158
|
+
const day = now.getDate().toString().padStart(2, '0');
|
|
159
|
+
const month = (now.getMonth() + 1).toString().padStart(2, '0');
|
|
160
|
+
const year = now.getFullYear();
|
|
161
|
+
|
|
162
|
+
let hours = now.getHours();
|
|
163
|
+
const minutes = now.getMinutes().toString().padStart(2, '0');
|
|
164
|
+
const ampm = hours >= 12 ? 'PM' : 'AM';
|
|
165
|
+
|
|
166
|
+
hours = hours % 12;
|
|
167
|
+
hours = hours ? hours : 12;
|
|
168
|
+
hours = hours.toString().padStart(2, '0');
|
|
169
|
+
|
|
170
|
+
const fechaFormateada = `\${day}-\${month}-\${year} \${hours}:\${minutes} \${ampm}\`;
|
|
171
|
+
|
|
172
|
+
return \` <div style="margin-left: 0; font-size: 11px; margin-top:4px;">
|
|
173
|
+
<strong>Fecha:</strong>
|
|
174
|
+
<span style="
|
|
175
|
+
border-bottom: 1px solid #000;
|
|
176
|
+
margin-left: 10px;
|
|
177
|
+
display: inline-block;
|
|
178
|
+
padding: 0 4px 2px 4px;
|
|
179
|
+
vertical-align: middle;
|
|
180
|
+
text-align: center;
|
|
181
|
+
min-width: 120px;
|
|
182
|
+
">\${fechaFormateada}
|
|
183
|
+
</span>
|
|
184
|
+
</div>
|
|
185
|
+
`
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
GenerarReporteHTMLTablas(ElementosParaLaTabla, ParametrosExcluidos = [], ParametrosExtra = []) {
|
|
189
|
+
if (!ElementosParaLaTabla?.length) return '';
|
|
190
|
+
|
|
191
|
+
const baseColumnas = Object.keys(ElementosParaLaTabla[0]).filter(col => !ParametrosExcluidos.includes(col));
|
|
192
|
+
const columnas = [...baseColumnas, ...ParametrosExtra.filter(p => !baseColumnas.includes(p))];
|
|
193
|
+
|
|
194
|
+
const tableHeaders = `<th>N°</th>\` + columnas.map(col => \`<th>\${col}</th>\`).join('');
|
|
195
|
+
|
|
196
|
+
const rows = ElementosParaLaTabla.map((fila, index) => {
|
|
197
|
+
const rowCells = columnas.map(col => {
|
|
198
|
+
const valor = fila[col] ?? '';
|
|
199
|
+
return \`<td>\${valor}</td>\`;
|
|
200
|
+
}).join('');
|
|
201
|
+
return \`<tr><td><strong>\${index + 1}</strong></td>\${rowCells}</tr>\`;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const colCount = columnas.length + 1;
|
|
205
|
+
const minRows = 1;
|
|
206
|
+
let currentIndex = rows.length;
|
|
207
|
+
while (rows.length < minRows) {
|
|
208
|
+
let emptyCells = \`<td><strong>\${currentIndex + 1}</strong></td>\`;
|
|
209
|
+
for (let i = 0; i < colCount - 1; i++) {
|
|
210
|
+
emptyCells += '<td></td>';
|
|
211
|
+
}
|
|
212
|
+
rows.push(\`<tr style="height:40px">\${emptyCells}</tr>\`);
|
|
213
|
+
currentIndex++;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const tableRows = rows.join('');
|
|
217
|
+
return \`
|
|
218
|
+
<table>
|
|
219
|
+
<thead>
|
|
220
|
+
<tr>\${tableHeaders}</tr>
|
|
221
|
+
</thead>
|
|
222
|
+
<tbody>
|
|
223
|
+
\${tableRows}
|
|
224
|
+
</tbody>
|
|
225
|
+
</table>`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
GenerarReporteHTMLPie() {
|
|
229
|
+
return `
|
|
230
|
+
</body>
|
|
231
|
+
</html>`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
module.exports = new ReporteHTML();
|