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
package/commands/frontend.js
CHANGED
|
@@ -387,17 +387,44 @@ function actualizarArchivosConfiguracion(nombreClase, nombreRuta, titulo, descri
|
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
// --- Modificar contenedor-principal.component.
|
|
391
|
-
console.log('Actualizando contenedor-principal.component.
|
|
392
|
-
const
|
|
393
|
-
if (fs.existsSync(
|
|
394
|
-
let
|
|
395
|
-
if (!
|
|
396
|
-
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
390
|
+
// --- Modificar contenedor-principal.component.ts ---
|
|
391
|
+
console.log('Actualizando contenedor-principal.component.ts...');
|
|
392
|
+
const rutaTs = path.join(process.cwd(), 'src', 'app', 'Paginas', 'contenedor-principal', 'contenedor-principal.component.ts');
|
|
393
|
+
if (fs.existsSync(rutaTs)) {
|
|
394
|
+
let contenidoTs = fs.readFileSync(rutaTs, 'utf-8');
|
|
395
|
+
if (!contenidoTs.includes(`rutaASeguir: '${nombreRuta}'`)) {
|
|
396
|
+
// Encontrar el array baseTarjetas y su contenido
|
|
397
|
+
const regexBaseTarjetas = /let baseTarjetas: AnyTarjetaConfig\[\] = \[([\s\S]*?)\];/;
|
|
398
|
+
const match = contenidoTs.match(regexBaseTarjetas);
|
|
399
|
+
|
|
400
|
+
if (match) {
|
|
401
|
+
const contenidoArray = match[1];
|
|
402
|
+
// Buscar la última posición para incrementar
|
|
403
|
+
const regexPosiciones = /position: (\d+)/g;
|
|
404
|
+
let ultimaPosicion = 0;
|
|
405
|
+
let m;
|
|
406
|
+
while ((m = regexPosiciones.exec(contenidoArray)) !== null) {
|
|
407
|
+
const pos = parseInt(m[1]);
|
|
408
|
+
if (pos > ultimaPosicion) ultimaPosicion = pos;
|
|
409
|
+
}
|
|
410
|
+
const nuevaPosicion = ultimaPosicion + 10;
|
|
411
|
+
|
|
412
|
+
const nuevaTarjeta = `,
|
|
413
|
+
{
|
|
414
|
+
type: 'single',
|
|
415
|
+
position: ${nuevaPosicion},
|
|
416
|
+
rutaASeguir: '${nombreRuta}',
|
|
417
|
+
titulo: '${titulo}',
|
|
418
|
+
descripcion: '${descripcion}',
|
|
419
|
+
icono: 'table_chart'
|
|
420
|
+
}`;
|
|
421
|
+
|
|
422
|
+
// Insertar antes del cierre del array (el ]; que sigue al contenidoArray)
|
|
423
|
+
const indiceCierre = contenidoTs.indexOf('];', match.index);
|
|
424
|
+
if (indiceCierre !== -1) {
|
|
425
|
+
contenidoTs = contenidoTs.slice(0, indiceCierre).trimEnd() + nuevaTarjeta + '\n ' + contenidoTs.slice(indiceCierre);
|
|
426
|
+
fs.writeFileSync(rutaTs, contenidoTs);
|
|
427
|
+
}
|
|
401
428
|
}
|
|
402
429
|
}
|
|
403
430
|
}
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { ejecutarConsulta, ejecutarConsultaSIGU,
|
|
1
|
+
const { ejecutarConsulta, ejecutarConsultaSIGU, crearObjetoConexionSIGU } = require('./db.js');
|
|
2
2
|
const ManejadorDeErrores = require('./ManejadorDeErrores.js');
|
|
3
3
|
const InformacionDelModulo = require('../InformacionDelModulo.js');
|
|
4
4
|
const { envioDeCorreo } = require('./EnvioDeCorreos.js');
|
|
@@ -103,325 +103,35 @@ class Miscelaneo {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
//REPORTE INICIA AQUÍ
|
|
107
|
-
|
|
108
106
|
async generarFirmaHTML(Identificador, FechaDeLaFirma) {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
if (!persona) return '';
|
|
112
|
-
|
|
113
|
-
const nombre = persona.NombreCompleto;
|
|
114
|
-
const identificacion = persona.Identificacion;
|
|
115
|
-
const instancia = await (async () => {
|
|
116
|
-
try {
|
|
117
|
-
const result = await ejecutarConsultaSIGU(`
|
|
118
|
-
SELECT
|
|
119
|
-
CASE
|
|
120
|
-
WHEN i.TipoDeResponsabilidad = 'Ninguna' THEN sup.Nombre
|
|
121
|
-
ELSE i.Nombre
|
|
122
|
-
END AS Nombre
|
|
123
|
-
FROM SIGU.EstructuraOrganizacional_Instancias i
|
|
124
|
-
LEFT JOIN SIGU.EstructuraOrganizacional_Instancias sup
|
|
125
|
-
ON i.IdentificadorDeInstanciaSuperior = sup.IdentificadorDeInstancia
|
|
126
|
-
WHERE i.Identificador = ?
|
|
127
|
-
`, [Identificador]);
|
|
128
|
-
return result?.[0]?.Nombre || 'N/A';
|
|
129
|
-
} catch {
|
|
130
|
-
return 'N/A';
|
|
131
|
-
}
|
|
132
|
-
})();
|
|
133
|
-
|
|
134
|
-
return ` <div style="
|
|
135
|
-
font-size: 9px;
|
|
136
|
-
border: 1px solid #eee;
|
|
137
|
-
padding: 6px;
|
|
138
|
-
display: inline-flex;
|
|
139
|
-
align-items: center;
|
|
140
|
-
background-color: #fcfcfc;
|
|
141
|
-
gap: 8px;
|
|
142
|
-
">
|
|
143
|
-
<div class="logo" style="display:flex; align-items:center;">
|
|
144
|
-
<img src="https://storage.sigu.utn.ac.cr/images/cards/LogoUTN.svg"
|
|
145
|
-
alt="Logo UTN"
|
|
146
|
-
style="height:25px;">
|
|
147
|
-
</div>
|
|
148
|
-
<div style="
|
|
149
|
-
width: 1px;
|
|
150
|
-
height: 50px;
|
|
151
|
-
background-color: #ccc;
|
|
152
|
-
"></div>
|
|
153
|
-
<div style="text-align: left;">
|
|
154
|
-
<strong>FIRMADO DIGITALMENTE POR:</strong><br>
|
|
155
|
-
${nombre}<br>
|
|
156
|
-
Cédula: ${identificacion}<br>
|
|
157
|
-
Instancia: ${instancia}<br>
|
|
158
|
-
Fecha: ${FechaDeLaFirma}
|
|
159
|
-
</div>
|
|
160
|
-
|
|
161
|
-
</div>`;
|
|
107
|
+
const ReporteHTML = require('./ReporteHTML.js');
|
|
108
|
+
return await ReporteHTML.generarFirmaHTML(Identificador, FechaDeLaFirma);
|
|
162
109
|
}
|
|
163
110
|
|
|
164
111
|
GenerarReporteHTMLRegistrosVerticales(ElementosParaLaTabla, ParametrosExcluidos = [], ParametrosExtra = [], MostrarEncabezado = true) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
// {
|
|
168
|
-
// "Fecha del traslado": "16-03-2026",
|
|
169
|
-
// "Justificacion": "Traslado por mantenimiento",
|
|
170
|
-
// "Dependencia que entrega": "Juan Pérez",
|
|
171
|
-
// "Dependencia que recibe": "María Gómez",
|
|
172
|
-
// Placa: "ABC123",
|
|
173
|
-
// "Descripción": "Laptop Dell",
|
|
174
|
-
// "Código de activo": "ACT-001",
|
|
175
|
-
// "N° de serie": "SN123456",
|
|
176
|
-
// Marca: "Dell",
|
|
177
|
-
// Modelo: "Latitude 5420",
|
|
178
|
-
// Estado: "Bueno",
|
|
179
|
-
// IdentificadorOrigen: 101,
|
|
180
|
-
// IdentificadorDestino: 202
|
|
181
|
-
// },
|
|
182
|
-
// {
|
|
183
|
-
// "Fecha del traslado": "16-03-2026",
|
|
184
|
-
// "Justificacion": "Traslado por mantenimiento",
|
|
185
|
-
// "Dependencia que entrega": "Juan Pérez",
|
|
186
|
-
// "Dependencia que recibe": "María Gómez",
|
|
187
|
-
// Placa: "XYZ789",
|
|
188
|
-
// "Descripción": "Monitor Samsung",
|
|
189
|
-
// "Código de activo": "ACT-002",
|
|
190
|
-
// "N° de serie": "SN654321",
|
|
191
|
-
// Marca: "Samsung",
|
|
192
|
-
// Modelo: "S24F350",
|
|
193
|
-
// Estado: "Excelente",
|
|
194
|
-
// IdentificadorOrigen: 101,
|
|
195
|
-
// IdentificadorDestino: 202
|
|
196
|
-
// ]
|
|
197
|
-
// Espera un Array de objetos.
|
|
198
|
-
//
|
|
199
|
-
// Ejemplo ParametrosExcluidos:
|
|
200
|
-
// const ParametrosExcluidos = ['IdentificadorOrigen', 'Justificacion', 'IdentificadorDestino'];
|
|
201
|
-
// Valores devueltos por el QUERY que no sean necesarios mostrar en la tabla.
|
|
202
|
-
//
|
|
203
|
-
// Ejemplo ParametrosExtra:
|
|
204
|
-
// const ParametrosExtra = ['Toma física'];
|
|
205
|
-
// En caso de necesitar un espacio extra en la tabla que no se encuentra en la lista principal.
|
|
206
|
-
//
|
|
207
|
-
// Ejemplo MostrarEncabezado:
|
|
208
|
-
// MostrarEncabezado = true (Valor por defecto, muestra la barra azul "Registro N° 1")
|
|
209
|
-
// MostrarEncabezado = false (Oculta la barra azul, ideal para usar la función con un único registro)
|
|
210
|
-
|
|
211
|
-
if (!ElementosParaLaTabla?.length) return '<p>No hay datos para mostrar.</p>';
|
|
212
|
-
|
|
213
|
-
const baseColumnas = Object.keys(ElementosParaLaTabla[0]).filter(col => !ParametrosExcluidos.includes(col));
|
|
214
|
-
const columnas = [...baseColumnas, ...ParametrosExtra.filter(p => !baseColumnas.includes(p))];
|
|
215
|
-
|
|
216
|
-
let htmlFinal = '';
|
|
217
|
-
|
|
218
|
-
ElementosParaLaTabla.forEach((fila, index) => {
|
|
219
|
-
|
|
220
|
-
const filasHTML = columnas.map(col => {
|
|
221
|
-
const valor = fila[col] ?? '-';
|
|
222
|
-
return `
|
|
223
|
-
<tr>
|
|
224
|
-
<th style="width: 20%;">${col}</th>
|
|
225
|
-
<td style="width: 80%;">${valor}</td>
|
|
226
|
-
</tr>
|
|
227
|
-
`;
|
|
228
|
-
}).join('');
|
|
229
|
-
|
|
230
|
-
const encabezadoHTML = MostrarEncabezado ? `
|
|
231
|
-
<div style="background-color: #002f6b; color: white; padding: 6px 10px; font-weight: bold; font-size: 14px;">
|
|
232
|
-
Registro N° ${index + 1}
|
|
233
|
-
</div>
|
|
234
|
-
` : '';
|
|
235
|
-
|
|
236
|
-
htmlFinal += `
|
|
237
|
-
<div style="margin-top: 20px; page-break-inside: avoid; border: 1px solid #ccc; border-radius: 8px; overflow: hidden;">
|
|
238
|
-
|
|
239
|
-
${encabezadoHTML}
|
|
240
|
-
|
|
241
|
-
<table style="border: none; border-radius: 0; margin-top: 0;">
|
|
242
|
-
<tbody>
|
|
243
|
-
${filasHTML}
|
|
244
|
-
</tbody>
|
|
245
|
-
</table>
|
|
246
|
-
|
|
247
|
-
</div>`;
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
return htmlFinal;
|
|
112
|
+
const ReporteHTML = require('./ReporteHTML.js');
|
|
113
|
+
return ReporteHTML.GenerarReporteHTMLRegistrosVerticales(ElementosParaLaTabla, ParametrosExcluidos, ParametrosExtra, MostrarEncabezado);
|
|
251
114
|
}
|
|
252
115
|
|
|
253
116
|
GenerarReporteHTMLEncabezado(InformacionDeLaDerecha, titulares, marcaDeAgua = '') {
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
return ` <!DOCTYPE html>
|
|
258
|
-
<html lang="es">
|
|
259
|
-
<head>
|
|
260
|
-
<meta charset="UTF-8">
|
|
261
|
-
<title>${titulares.titulo}</title>
|
|
262
|
-
|
|
263
|
-
<style>
|
|
264
|
-
@media print {
|
|
265
|
-
* { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
|
266
|
-
}
|
|
267
|
-
body { font-family: Roboto, "Helvetica Neue", sans-serif; margin: 8px; }
|
|
268
|
-
.header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px; min-height: 70px; }
|
|
269
|
-
.header > div { flex: 1; }
|
|
270
|
-
.logo { flex-shrink: 0; }
|
|
271
|
-
.title-container { text-align: center; flex-grow: 1; }
|
|
272
|
-
.title { font-size: 16px; font-weight: bold; white-space: nowrap; flex-shrink: 0; }
|
|
273
|
-
.subtitle { font-size: 13px; font-weight: bold; margin-top: 4px; }
|
|
274
|
-
.info { text-align: right; font-size: 11px; margin-left: 10px; flex-shrink: 0; }
|
|
275
|
-
table { width: 100%; border-collapse: separate; border-spacing: 0; border-radius: 10px; overflow: hidden; }
|
|
276
|
-
th, td { border: 1px solid #ccc; padding: 4px; text-align: left; font-size: 12px; }
|
|
277
|
-
th { background-color: #002f6b; color: white; }
|
|
278
|
-
tr:nth-child(even) { background-color: #f9f9f9; }
|
|
279
|
-
td:last-child { width: 100px; }
|
|
280
|
-
hr { border: none; border-top: 2px solid #838383; margin: 8px 0; }
|
|
281
|
-
.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; }
|
|
282
|
-
</style>
|
|
283
|
-
|
|
284
|
-
</head>
|
|
285
|
-
<body>
|
|
286
|
-
<div class="watermark">${marcaDeAgua}</div>
|
|
287
|
-
<div class="header">
|
|
288
|
-
<div class="logo">
|
|
289
|
-
<img src="https://storage.sigu.utn.ac.cr/images/cards/LogoUTN.svg" alt="Logo UTN" style="height:50px;">
|
|
290
|
-
</div>
|
|
291
|
-
<div class="title-container">
|
|
292
|
-
<div class="title">Universidad Técnica Nacional</div>
|
|
293
|
-
<div class="subtitle">${titulares.primerSubtitulo}</div>
|
|
294
|
-
<div class="subtitle">${titulares.segundoSubtitulo}</div>
|
|
295
|
-
</div>
|
|
296
|
-
<div class="info">
|
|
297
|
-
${InformacionDeLaDerecha}
|
|
298
|
-
</div>
|
|
299
|
-
|
|
300
|
-
</div> `;
|
|
117
|
+
const ReporteHTML = require('./ReporteHTML.js');
|
|
118
|
+
return ReporteHTML.GenerarReporteHTMLEncabezado(InformacionDeLaDerecha, titulares, marcaDeAgua);
|
|
301
119
|
}
|
|
302
120
|
|
|
303
121
|
GenerarReporteHTMLFecha() {
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
const day = now.getDate().toString().padStart(2, '0');
|
|
307
|
-
const month = (now.getMonth() + 1).toString().padStart(2, '0');
|
|
308
|
-
const year = now.getFullYear();
|
|
309
|
-
|
|
310
|
-
let hours = now.getHours();
|
|
311
|
-
const minutes = now.getMinutes().toString().padStart(2, '0');
|
|
312
|
-
const ampm = hours >= 12 ? 'PM' : 'AM';
|
|
313
|
-
|
|
314
|
-
hours = hours % 12;
|
|
315
|
-
hours = hours ? hours : 12;
|
|
316
|
-
hours = hours.toString().padStart(2, '0');
|
|
317
|
-
|
|
318
|
-
const fechaFormateada = `${day}-${month}-${year} ${hours}:${minutes} ${ampm}`;
|
|
319
|
-
|
|
320
|
-
return ` <div style="margin-left: 0; font-size: 11px; margin-top:4px;">
|
|
321
|
-
<strong>Fecha:</strong>
|
|
322
|
-
<span style="
|
|
323
|
-
border-bottom: 1px solid #000;
|
|
324
|
-
margin-left: 10px;
|
|
325
|
-
display: inline-block;
|
|
326
|
-
padding: 0 4px 2px 4px;
|
|
327
|
-
vertical-align: middle;
|
|
328
|
-
text-align: center;
|
|
329
|
-
min-width: 120px;
|
|
330
|
-
">${fechaFormateada}
|
|
331
|
-
</span>
|
|
332
|
-
</div>
|
|
333
|
-
`
|
|
122
|
+
const ReporteHTML = require('./ReporteHTML.js');
|
|
123
|
+
return ReporteHTML.GenerarReporteHTMLFecha();
|
|
334
124
|
}
|
|
335
125
|
|
|
336
126
|
GenerarReporteHTMLTablas(ElementosParaLaTabla, ParametrosExcluidos = [], ParametrosExtra = []) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
// {
|
|
340
|
-
// "Fecha del traslado": "16-03-2026",
|
|
341
|
-
// "Justificacion": "Traslado por mantenimiento",
|
|
342
|
-
// "Dependencia que entrega": "Juan Pérez",
|
|
343
|
-
// "Dependencia que recibe": "María Gómez",
|
|
344
|
-
// Placa: "ABC123",
|
|
345
|
-
// "Descripción": "Laptop Dell",
|
|
346
|
-
// "Código de activo": "ACT-001",
|
|
347
|
-
// "N° de serie": "SN123456",
|
|
348
|
-
// Marca: "Dell",
|
|
349
|
-
// Modelo: "Latitude 5420",
|
|
350
|
-
// Estado: "Bueno",
|
|
351
|
-
// IdentificadorOrigen: 101,
|
|
352
|
-
// IdentificadorDestino: 202
|
|
353
|
-
// },
|
|
354
|
-
// {
|
|
355
|
-
// "Fecha del traslado": "16-03-2026",
|
|
356
|
-
// "Justificacion": "Traslado por mantenimiento",
|
|
357
|
-
// "Dependencia que entrega": "Juan Pérez",
|
|
358
|
-
// "Dependencia que recibe": "María Gómez",
|
|
359
|
-
// Placa: "XYZ789",
|
|
360
|
-
// "Descripción": "Monitor Samsung",
|
|
361
|
-
// "Código de activo": "ACT-002",
|
|
362
|
-
// "N° de serie": "SN654321",
|
|
363
|
-
// Marca: "Samsung",
|
|
364
|
-
// Modelo: "S24F350",
|
|
365
|
-
// Estado: "Excelente",
|
|
366
|
-
// IdentificadorOrigen: 101,
|
|
367
|
-
// IdentificadorDestino: 202
|
|
368
|
-
// }
|
|
369
|
-
// ]
|
|
370
|
-
// Espera un Array
|
|
371
|
-
//Ejemplo ParametrosExcluidos:
|
|
372
|
-
//const ParametrosExcluidos = ['IdentificadorOrigen', 'Justificacion', 'IdentificadorDestino'];
|
|
373
|
-
//Valores devueltos por el QUERY que no sean necesarios mostrar en la tabla.
|
|
374
|
-
|
|
375
|
-
//Ejemplo ParametrosExtra:
|
|
376
|
-
//const ParametrosExtra = ['Toma física'];
|
|
377
|
-
//En caso de necesitar un espacio extra en la tabla que no se encuentra en la lista principal.
|
|
378
|
-
|
|
379
|
-
if (!ElementosParaLaTabla?.length) return '';
|
|
380
|
-
|
|
381
|
-
const baseColumnas = Object.keys(ElementosParaLaTabla[0]).filter(col => !ParametrosExcluidos.includes(col));
|
|
382
|
-
const columnas = [...baseColumnas, ...ParametrosExtra.filter(p => !baseColumnas.includes(p))];
|
|
383
|
-
|
|
384
|
-
const tableHeaders = `<th>N°</th>` + columnas.map(col => `<th>${col}</th>`).join('');
|
|
385
|
-
|
|
386
|
-
const rows = ElementosParaLaTabla.map((fila, index) => {
|
|
387
|
-
const rowCells = columnas.map(col => {
|
|
388
|
-
const valor = fila[col] ?? '';
|
|
389
|
-
return `<td>${valor}</td>`;
|
|
390
|
-
}).join('');
|
|
391
|
-
return `<tr><td><strong>${index + 1}</strong></td>${rowCells}</tr>`;
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
const colCount = columnas.length + 1;
|
|
395
|
-
const minRows = 1;
|
|
396
|
-
let currentIndex = rows.length;
|
|
397
|
-
while (rows.length < minRows) {
|
|
398
|
-
let emptyCells = `<td><strong>${currentIndex + 1}</strong></td>`;
|
|
399
|
-
for (let i = 0; i < colCount - 1; i++) {
|
|
400
|
-
emptyCells += '<td></td>';
|
|
401
|
-
}
|
|
402
|
-
rows.push(`<tr style="height:40px">${emptyCells}</tr>`);
|
|
403
|
-
currentIndex++;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const tableRows = rows.join('');
|
|
407
|
-
return `
|
|
408
|
-
<table>
|
|
409
|
-
<thead>
|
|
410
|
-
<tr>${tableHeaders}</tr>
|
|
411
|
-
</thead>
|
|
412
|
-
<tbody>
|
|
413
|
-
${tableRows}
|
|
414
|
-
</tbody>
|
|
415
|
-
</table>`;
|
|
127
|
+
const ReporteHTML = require('./ReporteHTML.js');
|
|
128
|
+
return ReporteHTML.GenerarReporteHTMLTablas(ElementosParaLaTabla, ParametrosExcluidos, ParametrosExtra);
|
|
416
129
|
}
|
|
417
130
|
|
|
418
131
|
GenerarReporteHTMLPie() {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
</html>`;
|
|
132
|
+
const ReporteHTML = require('./ReporteHTML.js');
|
|
133
|
+
return ReporteHTML.GenerarReporteHTMLPie();
|
|
422
134
|
}
|
|
423
|
-
//la información adicional se concatena desde la llamada
|
|
424
|
-
//REPORTE TERMINA AQUÍ
|
|
425
135
|
|
|
426
136
|
obtenerNombreLaBaseDeDatos() {
|
|
427
137
|
return this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3);
|
|
@@ -751,68 +461,6 @@ class Miscelaneo {
|
|
|
751
461
|
return;
|
|
752
462
|
}
|
|
753
463
|
|
|
754
|
-
async AutenticarConGoogle(Solicitud) {
|
|
755
|
-
const { OAuth2Client } = require('google-auth-library');
|
|
756
|
-
const jwt = require('jsonwebtoken');
|
|
757
|
-
const clientId = await this.googleClientId();
|
|
758
|
-
const client = new OAuth2Client(clientId);
|
|
759
|
-
const ConexionSigu = await crearObjetoConexionSIGU();
|
|
760
|
-
const LastUser = await this.generarLastUser(Solicitud);
|
|
761
|
-
|
|
762
|
-
try {
|
|
763
|
-
const ticket = await client.verifyIdToken({
|
|
764
|
-
idToken: Solicitud.body.token,
|
|
765
|
-
audience: clientId,
|
|
766
|
-
});
|
|
767
|
-
const payload = ticket.getPayload();
|
|
768
|
-
const email = payload['email'];
|
|
769
|
-
|
|
770
|
-
const resultadosEmail = await ConexionSigu.query("SELECT `Identificador` FROM `SIGU`.`SIGU_CorreosPersona` WHERE `CorreoElectronico` = ? AND `Principal` = TRUE LIMIT 1", [email]);
|
|
771
|
-
|
|
772
|
-
if (resultadosEmail[0].length === 0) {
|
|
773
|
-
console.log("El correo de Google", email, "no está registrado como principal en SIGU");
|
|
774
|
-
return { error: "Su cuenta de Google no está vinculada a ningún usuario de SIGU." };
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
const Identificador = resultadosEmail[0][0]['Identificador'];
|
|
778
|
-
const resultadosUsuario = await ConexionSigu.query("SELECT `Identificacion` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ? AND `Activo` = TRUE", [Identificador]);
|
|
779
|
-
|
|
780
|
-
if (resultadosUsuario[0].length === 0) {
|
|
781
|
-
return { error: "El usuario asociado a esta cuenta no está activo." };
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
const Identificacion = resultadosUsuario[0][0]['Identificacion'];
|
|
785
|
-
|
|
786
|
-
// Generar Token
|
|
787
|
-
const Token = await jwt.sign({ Identificador: Identificador, uid: Identificador }, await this.palabraSecretaParaTokens(), { expiresIn: '2h' });
|
|
788
|
-
await ConexionSigu.query("INSERT INTO `SIGU`.`SIGU_Sesiones` VALUES (?, ?, ?, NOW(4), ?) ON DUPLICATE KEY UPDATE `Token` = ?, `LastUser` = ?", [Identificador, Solicitud.headers.host.trim(), Token, LastUser, Token, LastUser]);
|
|
789
|
-
await ConexionSigu.query("DELETE FROM `SIGU`.`SIGU_SesionesFallidas` WHERE `Identificador` = ?", [Identificador]);
|
|
790
|
-
|
|
791
|
-
// OBTENER IP DEL USUARIO
|
|
792
|
-
const ipUsuario = (Solicitud.headers['x-forwarded-for'] || '').split(',').shift() || Solicitud.socket?.remoteAddress || Solicitud.connection?.remoteAddress || '-';
|
|
793
|
-
|
|
794
|
-
// SI LA IP YA EXISTE CONTINUA
|
|
795
|
-
await ConexionSigu.query("\
|
|
796
|
-
INSERT INTO `SIGU`.`SIGU_DireccionesUsadasPorLosUsuarios` \
|
|
797
|
-
(`DireccionUsadaPorElUsuario`, `Identificador`, `LastUpdate`, `LastUser`) \
|
|
798
|
-
VALUES (?, ?, NOW(4), ?) \
|
|
799
|
-
ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4), `LastUser` = ?;", [
|
|
800
|
-
ipUsuario,
|
|
801
|
-
Identificador,
|
|
802
|
-
LastUser,
|
|
803
|
-
LastUser
|
|
804
|
-
]);
|
|
805
|
-
|
|
806
|
-
return { Token, Dominio: ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '.181.193.85.44.nip.io') };
|
|
807
|
-
|
|
808
|
-
} catch (error) {
|
|
809
|
-
console.error("Error en AutenticarConGoogle:", error);
|
|
810
|
-
return { error: "Error al autenticar con Google" };
|
|
811
|
-
} finally {
|
|
812
|
-
if (ConexionSigu) await ConexionSigu.end();
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
|
|
816
464
|
async Autenticar(Solicitud) {
|
|
817
465
|
const crypto = require('crypto');
|
|
818
466
|
const bcrypt = require('bcryptjs');
|
|
@@ -1048,7 +696,7 @@ class Miscelaneo {
|
|
|
1048
696
|
`a`.`Tipo`, IF(`a`.`Icono` <> '', CONCAT('https://storage.sigu.utn.ac.cr/images/cards/', `a`.`Icono`), '') AS `Icono`, `a`.`Color`, `a`.`Correo`,\
|
|
1049
697
|
`a`.`Version`, `a`.`FechaDePublicacion`, `a`.`AcuerdoDeNivelDeServicio`, `a`.`DiccionarioDeDatos`, `a`.`Repositorios`,\
|
|
1050
698
|
`a`.`EnlaceDelVideo`,`a`.`EnlaceDelManual`\
|
|
1051
|
-
, `a`.`Estado`, REGEXP_SUBSTR(
|
|
699
|
+
, `a`.`Estado`, REGEXP_SUBSTR(`a`.`Repositorios`, '[^,]*front[^,]*') AS `Frontend`\
|
|
1052
700
|
FROM `SIGU`.`SIGU_ModulosV2` `a`\
|
|
1053
701
|
WHERE `a`.`Nombre` = ?", [this.NombreCanonicoDelModulo]);
|
|
1054
702
|
return Modulos.map((linea) => {
|
|
@@ -1114,7 +762,7 @@ class Miscelaneo {
|
|
|
1114
762
|
`a`.`Tipo`, IF(`a`.`Icono` <> '', CONCAT('https://storage.sigu.utn.ac.cr/images/cards/', `a`.`Icono`), '') AS `Icono`, `a`.`Color`, `a`.`Correo`,\
|
|
1115
763
|
`a`.`Version`, `a`.`FechaDePublicacion`, `a`.`AcuerdoDeNivelDeServicio`, `a`.`DiccionarioDeDatos`, `a`.`Repositorios`,\
|
|
1116
764
|
`a`.`EnlaceDelVideo`,`a`.`EnlaceDelManual`\
|
|
1117
|
-
, `a`.`Estado`, REGEXP_SUBSTR(
|
|
765
|
+
, `a`.`Estado`, REGEXP_SUBSTR(`a`.`Repositorios`, '[^,]*front[^,]*') AS `Frontend`\
|
|
1118
766
|
FROM `SIGU`.`SIGU_ModulosV2` `a`\
|
|
1119
767
|
JOIN `SIGU`.`SIGU_PermisosV2` `b` ON (`a`.`Nombre` = `b`.`Modulo`)\
|
|
1120
768
|
WHERE `a`.`Estado` = 'Activo' AND `a`.`Padre` = ? AND `b`.`PermisoId` IN (?)\
|
|
@@ -1242,10 +890,10 @@ class Miscelaneo {
|
|
|
1242
890
|
const Version = this.Version + "$$" + this.versionDelNucleo().split(' ')[0];
|
|
1243
891
|
await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_ModulosV2` VALUES\
|
|
1244
892
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(4), ?, 'DiccionarioDeDatos'\
|
|
1245
|
-
, ?, '-', '-', 'Activo', NOW(4), USER()) ON DUPLICATE KEY UPDATE `Version` =
|
|
893
|
+
, ?, '-', '-', 'Activo', NOW(4), USER()) ON DUPLICATE KEY UPDATE `Version` = ?"
|
|
1246
894
|
, [this.NombreCanonicoDelModulo, this.MenuPadre, this.DescripcionDelModulo, this.DetalleDelModulo
|
|
1247
895
|
, this.TipoDeCard, this.IconoDelModulo, this.ColorDelModulo, this.CorreoParaReportes, Version, this.versionDelNucleo().split(' ')[0], this.Repositorios
|
|
1248
|
-
, Version
|
|
896
|
+
, Version]);
|
|
1249
897
|
await ejecutarConsultaSIGU("SELECT IFNULL(MAX(`PermisoId`), 0) + 1 INTO @`SiguientePermisoId` FROM `SIGU`.`SIGU_PermisosV2`;\
|
|
1250
898
|
INSERT INTO `SIGU`.`SIGU_PermisosV2` VALUES\
|
|
1251
899
|
(@`SiguientePermisoId`, ?, ?, ?, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUser` = USER(), `Nombre` = ?, `Descripcion` = ?;"
|
|
@@ -1544,7 +1192,7 @@ class Miscelaneo {
|
|
|
1544
1192
|
}
|
|
1545
1193
|
|
|
1546
1194
|
versionDelNucleo() {
|
|
1547
|
-
return "
|
|
1195
|
+
return "2.0.82" + " " + this.NombreCanonicoDelModulo;
|
|
1548
1196
|
}
|
|
1549
1197
|
|
|
1550
1198
|
async destinatarioDeInformesDeError() {
|
|
@@ -1609,7 +1257,7 @@ class Miscelaneo {
|
|
|
1609
1257
|
console.log(error);
|
|
1610
1258
|
return;
|
|
1611
1259
|
}
|
|
1612
|
-
return
|
|
1260
|
+
return ejecutarConsultaSIGU("SELECT `a`.`Identificador`, `a`.`Identificacion`\
|
|
1613
1261
|
, `a`.`Nombre`, `a`.`PrimerApellido`, `a`.`SegundoApellido`\
|
|
1614
1262
|
, (SELECT GROUP_CONCAT(`b`.`CuentaIBAN`) FROM `SIGU`.`SIGU_CuentasBancariasPersonas` `b` WHERE `b`.`Estado` = TRUE AND `a`.`Identificador` = `b`.`Identificador`) AS `CuentasIBAN`\
|
|
1615
1263
|
FROM `SIGU`.`SIGU_Personas` `a` WHERE `a`.`Identificador` = ?"
|
|
@@ -1630,33 +1278,28 @@ class Miscelaneo {
|
|
|
1630
1278
|
(SELECT `Identificador` FROM `SIGU`.`SIGU_RolesPersonas` WHERE `PerfilGeneralId` = 1 /*El perfil 1 parece ser para Estudiantes*/)");
|
|
1631
1279
|
}
|
|
1632
1280
|
|
|
1633
|
-
|
|
1634
|
-
return
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
async obtenerIdentificacion(Identificador) {
|
|
1638
|
-
return await ejecutarConsultaSIGU("SELECT `Identificacion` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Identificador]);
|
|
1281
|
+
obtenerBeneficios() {
|
|
1282
|
+
return ejecutarConsultaSIGU("SELECT `BeneficioId`, `Beneficio`, `Estado` FROM `SIGU`.`SIGU_Beneficios`");
|
|
1639
1283
|
}
|
|
1640
1284
|
|
|
1641
|
-
|
|
1642
|
-
return
|
|
1285
|
+
obtenerIdentificacion(Identificador) {
|
|
1286
|
+
return ejecutarConsultaSIGU("SELECT `Identificacion` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Identificador]);
|
|
1643
1287
|
}
|
|
1644
1288
|
|
|
1645
|
-
|
|
1646
|
-
return
|
|
1289
|
+
obtenerPeriodos() {
|
|
1290
|
+
return ejecutarConsultaSIGU("SELECT `PeriodoId`, `CodigoPeriodo`, `Anio`, `Periodo`, `FechaInicio`, `FechaFinal`, `Tipo`, `Estado` FROM `SIGU`.`SIGU_Periodos` ORDER BY `Anio` DESC, `CodigoPeriodo` DESC");
|
|
1647
1291
|
}
|
|
1648
1292
|
|
|
1649
|
-
|
|
1650
|
-
return
|
|
1293
|
+
obtenerAnios() {
|
|
1294
|
+
return ejecutarConsultaSIGU("SELECT DISTINCT `Anio` FROM `SIGU`.`SIGU_Periodos`");
|
|
1651
1295
|
}
|
|
1652
1296
|
|
|
1653
|
-
|
|
1654
|
-
return
|
|
1297
|
+
obtenerSedes() {
|
|
1298
|
+
return ejecutarConsultaSIGU("SELECT `SedesId`, `CodigoAvatar`, `Descripcion`, `Siglas` FROM `SIGU`.`SIGU_Sedes` ORDER BY `Descripcion`");
|
|
1655
1299
|
}
|
|
1656
1300
|
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
return clientId[0]?.['Valor'] || '';
|
|
1301
|
+
obtenerRecintos() {
|
|
1302
|
+
return ejecutarConsultaSIGU("SELECT `a`.`RecintoId`, CONCAT(`b`.`Descripcion`, '/', `a`.`Recinto`) AS `Recinto` FROM `SIGU`.`SIGU_Recintos` `a` LEFT JOIN `SIGU`.`SIGU_Sedes` `b` ON (`a`.`SedeId` = `b`.`SedesId`) ORDER BY `Recinto`");
|
|
1660
1303
|
}
|
|
1661
1304
|
|
|
1662
1305
|
async palabraSecretaParaTokens() {
|