@devlas/dte-sii 2.5.13 → 2.5.15
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/BoletaService.js +1 -1
- package/CafSolicitor.js +11 -12
- package/Certificado.js +2 -2
- package/ConsumoFolio.js +3 -3
- package/EnviadorSII.js +72 -99
- package/FolioService.js +1 -1
- package/SiiCertificacion.js +43 -20
- package/SiiPortalAuth.js +33 -9
- package/SiiSession.js +4 -4
- package/cert/BoletaCert.js +44 -44
- package/cert/CertRunner.js +466 -284
- package/cert/ConfigLoader.js +1 -1
- package/cert/IntercambioCert.js +19 -19
- package/cert/MuestrasImpresas.js +18 -18
- package/cert/SetBase.js +16 -16
- package/cert/SetBasico.js +6 -6
- package/cert/SetCompra.js +6 -6
- package/cert/SetExenta.js +6 -6
- package/cert/SetGuia.js +2 -2
- package/cert/SetsProvider.js +16 -19
- package/cert/Simulacion.js +1 -1
- package/package.json +2 -1
- package/utils/progress.js +78 -0
- package/utils/xml.js +2 -2
package/cert/ConfigLoader.js
CHANGED
|
@@ -51,7 +51,7 @@ function loadConfig(options = {}) {
|
|
|
51
51
|
const fch_resol = process.env.FECHA_RESOLUCION || new Date().toISOString().slice(0, 10);
|
|
52
52
|
const nro_resol = parseInt(process.env.NRO_RESOLUCION || '0', 10);
|
|
53
53
|
|
|
54
|
-
console.log(`[ConfigLoader]
|
|
54
|
+
console.log(`[ConfigLoader] Resolución: NroResol=${nro_resol} FchResol=${fch_resol} (AMBIENTE=${AMBIENTE})`);
|
|
55
55
|
|
|
56
56
|
const EMISOR = {
|
|
57
57
|
rut: process.env.EMISOR_RUT,
|
package/cert/IntercambioCert.js
CHANGED
|
@@ -361,57 +361,57 @@ class IntercambioCert {
|
|
|
361
361
|
fs.mkdirSync(outDir, { recursive: true });
|
|
362
362
|
|
|
363
363
|
console.log('\n' + '═'.repeat(60));
|
|
364
|
-
console.log('
|
|
364
|
+
console.log('INTERCAMBIO DE INFORMACIÓN DTE');
|
|
365
365
|
console.log('═'.repeat(60));
|
|
366
366
|
|
|
367
367
|
// Parsear EnvioDTE
|
|
368
|
-
console.log('\
|
|
368
|
+
console.log('\nParseando EnvioDTE...');
|
|
369
369
|
const meta = this.parseEnvioDTE(envioDteXml);
|
|
370
370
|
|
|
371
371
|
if (!meta?.items?.length) {
|
|
372
372
|
throw new Error('No se encontraron DTEs en el EnvioDTE de entrada');
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
-
console.log(`
|
|
376
|
-
console.log(`
|
|
377
|
-
console.log(`
|
|
375
|
+
console.log(` ✓ ${meta.items.length} documentos encontrados`);
|
|
376
|
+
console.log(` ✓ Emisor: ${meta.rutEmisor}`);
|
|
377
|
+
console.log(` ✓ Receptor: ${meta.rutReceptor}`);
|
|
378
378
|
|
|
379
379
|
meta.items.forEach((item, idx) => {
|
|
380
|
-
console.log(`
|
|
380
|
+
console.log(` ${idx + 1}. Tipo ${item.tipoDTE} Folio ${item.folio} - $${item.mntTotal.toLocaleString('es-CL')}`);
|
|
381
381
|
});
|
|
382
382
|
|
|
383
383
|
// Generar respuestas
|
|
384
|
-
console.log('\
|
|
384
|
+
console.log('\nGenerando respuestas de intercambio...');
|
|
385
385
|
|
|
386
386
|
// 1. Respuesta Recepción de Envío
|
|
387
|
-
console.log('
|
|
387
|
+
console.log(' 1. Respuesta Recepción de Envío...');
|
|
388
388
|
const recepcionXml = this.generarRespuestaRecepcionEnvio(meta, options.envioNombre);
|
|
389
389
|
const recepcionPath = path.join(outDir, 'respuesta-recepcion-envio.xml');
|
|
390
390
|
fs.writeFileSync(recepcionPath, recepcionXml, 'utf8');
|
|
391
|
-
console.log(`
|
|
391
|
+
console.log(` ✓ ${recepcionPath}`);
|
|
392
392
|
|
|
393
393
|
// 2. Respuesta Aprobación Comercial
|
|
394
|
-
console.log('
|
|
394
|
+
console.log(' 2. Respuesta Aprobación Comercial...');
|
|
395
395
|
const aprobacionXml = this.generarRespuestaAprobacionComercial(meta);
|
|
396
396
|
const aprobacionPath = path.join(outDir, 'respuesta-aprobacion-comercial.xml');
|
|
397
397
|
fs.writeFileSync(aprobacionPath, aprobacionXml, 'utf8');
|
|
398
|
-
console.log(`
|
|
398
|
+
console.log(` ✓ ${aprobacionPath}`);
|
|
399
399
|
|
|
400
400
|
// 3. Envío de Recibos
|
|
401
|
-
console.log('
|
|
401
|
+
console.log(' 3. Envío de Recibos (Mercaderías)...');
|
|
402
402
|
const recibosXml = this.generarEnvioRecibos(meta);
|
|
403
403
|
const recibosPath = path.join(outDir, 'envio-recibos.xml');
|
|
404
404
|
fs.writeFileSync(recibosPath, recibosXml, 'utf8');
|
|
405
|
-
console.log(`
|
|
405
|
+
console.log(` ✓ ${recibosPath}`);
|
|
406
406
|
|
|
407
407
|
console.log('\n' + '═'.repeat(60));
|
|
408
|
-
console.log('
|
|
408
|
+
console.log('[OK] INTERCAMBIO GENERADO');
|
|
409
409
|
console.log('═'.repeat(60));
|
|
410
|
-
console.log(`
|
|
411
|
-
console.log('
|
|
412
|
-
console.log('
|
|
413
|
-
console.log('
|
|
414
|
-
console.log('
|
|
410
|
+
console.log(` Directorio: ${outDir}`);
|
|
411
|
+
console.log(' Archivos generados:');
|
|
412
|
+
console.log(' - respuesta-recepcion-envio.xml');
|
|
413
|
+
console.log(' - respuesta-aprobacion-comercial.xml');
|
|
414
|
+
console.log(' - envio-recibos.xml');
|
|
415
415
|
|
|
416
416
|
return {
|
|
417
417
|
success: true,
|
package/cert/MuestrasImpresas.js
CHANGED
|
@@ -519,10 +519,10 @@ class MuestrasImpresas {
|
|
|
519
519
|
fs.mkdirSync(simulacionDir, { recursive: true });
|
|
520
520
|
|
|
521
521
|
console.log('\n' + '═'.repeat(60));
|
|
522
|
-
console.log('
|
|
522
|
+
console.log('GENERACIÓN DE MUESTRAS IMPRESAS');
|
|
523
523
|
console.log('═'.repeat(60));
|
|
524
|
-
console.log(`
|
|
525
|
-
console.log(`
|
|
524
|
+
console.log(` SET-PRUEBAS: ${pruebasDir}`);
|
|
525
|
+
console.log(` SET-SIMULACION: ${simulacionDir}`);
|
|
526
526
|
|
|
527
527
|
const browser = await puppeteer.launch({ headless: true });
|
|
528
528
|
const resultado = {
|
|
@@ -537,20 +537,20 @@ class MuestrasImpresas {
|
|
|
537
537
|
|
|
538
538
|
try {
|
|
539
539
|
for (const filePath of xmlFiles) {
|
|
540
|
-
console.log(`\n
|
|
540
|
+
console.log(`\n Procesando: ${path.basename(filePath)}`);
|
|
541
541
|
const xml = fs.readFileSync(filePath, 'utf8');
|
|
542
542
|
|
|
543
543
|
let documentos;
|
|
544
544
|
try {
|
|
545
545
|
documentos = this.parseEnvioDTE(xml);
|
|
546
546
|
} catch (e) {
|
|
547
|
-
console.log(`
|
|
547
|
+
console.log(` [!] Error parseando: ${e.message}`);
|
|
548
548
|
resultado.errores.push({ file: filePath, error: e.message });
|
|
549
549
|
continue;
|
|
550
550
|
}
|
|
551
551
|
|
|
552
552
|
if (!documentos.length) {
|
|
553
|
-
console.log('
|
|
553
|
+
console.log(' [!] Sin documentos');
|
|
554
554
|
continue;
|
|
555
555
|
}
|
|
556
556
|
|
|
@@ -559,7 +559,7 @@ class MuestrasImpresas {
|
|
|
559
559
|
const isPruebas = /envio-set-(basico|guia|exenta|compra)\.xml/i.test(sourceFile);
|
|
560
560
|
const targetDir = isPruebas ? pruebasDir : simulacionDir;
|
|
561
561
|
const categoria = isPruebas ? 'PRUEBAS' : 'SIMULACION';
|
|
562
|
-
console.log(`
|
|
562
|
+
console.log(` Categoria: SET-${categoria}`);
|
|
563
563
|
|
|
564
564
|
for (const doc of documentos) {
|
|
565
565
|
resultado.totalDocs++;
|
|
@@ -579,13 +579,13 @@ class MuestrasImpresas {
|
|
|
579
579
|
resultado.archivos.push(outputPath);
|
|
580
580
|
if (isPruebas) resultado.setPruebas++;
|
|
581
581
|
else resultado.setSimulacion++;
|
|
582
|
-
console.log(`
|
|
582
|
+
console.log(` ✓ ${outputName}`);
|
|
583
583
|
|
|
584
584
|
// Generar copia cedible si corresponde
|
|
585
585
|
if (generarCedible && CEDIBLE_TIPOS.has(doc.tipoDte)) {
|
|
586
586
|
// Guía de traslado interno no tiene cedible
|
|
587
587
|
if (doc.tipoDte === 52 && [5, 6].includes(doc.indTraslado)) {
|
|
588
|
-
console.log(
|
|
588
|
+
console.log(' Guia traslado interno - sin cedible');
|
|
589
589
|
continue;
|
|
590
590
|
}
|
|
591
591
|
|
|
@@ -598,11 +598,11 @@ class MuestrasImpresas {
|
|
|
598
598
|
resultado.archivos.push(outputPathCedible);
|
|
599
599
|
if (isPruebas) resultado.setPruebas++;
|
|
600
600
|
else resultado.setSimulacion++;
|
|
601
|
-
console.log(`
|
|
601
|
+
console.log(` ✓ ${outputNameCedible}`);
|
|
602
602
|
}
|
|
603
603
|
|
|
604
604
|
} catch (e) {
|
|
605
|
-
console.log(`
|
|
605
|
+
console.log(` [ERR] Error: ${e.message}`);
|
|
606
606
|
resultado.errores.push({ tipo: doc.tipoDte, folio: doc.folio, error: e.message });
|
|
607
607
|
}
|
|
608
608
|
}
|
|
@@ -613,17 +613,17 @@ class MuestrasImpresas {
|
|
|
613
613
|
|
|
614
614
|
// Resumen
|
|
615
615
|
console.log('\n' + '═'.repeat(60));
|
|
616
|
-
console.log('
|
|
616
|
+
console.log('[OK] MUESTRAS IMPRESAS GENERADAS');
|
|
617
617
|
console.log('═'.repeat(60));
|
|
618
|
-
console.log(`
|
|
619
|
-
console.log(`
|
|
620
|
-
console.log(`
|
|
621
|
-
console.log(`
|
|
622
|
-
console.log(`
|
|
618
|
+
console.log(` Documentos procesados: ${resultado.totalDocs}`);
|
|
619
|
+
console.log(` PDFs generados: ${resultado.totalPdfs}`);
|
|
620
|
+
console.log(` SET-PRUEBAS: ${resultado.setPruebas} PDFs`);
|
|
621
|
+
console.log(` SET-SIMULACION: ${resultado.setSimulacion} PDFs`);
|
|
622
|
+
console.log(` Directorio base: ${outDir}`);
|
|
623
623
|
|
|
624
624
|
if (resultado.errores.length > 0) {
|
|
625
625
|
resultado.success = false;
|
|
626
|
-
console.log(`
|
|
626
|
+
console.log(` [!] Errores: ${resultado.errores.length}`);
|
|
627
627
|
}
|
|
628
628
|
|
|
629
629
|
return resultado;
|
package/cert/SetBase.js
CHANGED
|
@@ -37,8 +37,8 @@ class SetBase {
|
|
|
37
37
|
this.logger = deps.logger || console;
|
|
38
38
|
|
|
39
39
|
// Subclases deben definir estos
|
|
40
|
-
this.key = '';
|
|
41
|
-
this.label = '';
|
|
40
|
+
this.key = ''; // 'basico', 'exenta', 'guia', 'compra'
|
|
41
|
+
this.label = ''; // 'Set Básico (Facturas)'
|
|
42
42
|
this.tiposDte = []; // [33, 56, 61]
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -82,7 +82,7 @@ class SetBase {
|
|
|
82
82
|
async ejecutar(casos, preloadedCafs = null) {
|
|
83
83
|
const startTime = Date.now();
|
|
84
84
|
this.logger.log(`\n${'═'.repeat(60)}`);
|
|
85
|
-
this.logger.log(
|
|
85
|
+
this.logger.log(`${this.label}`);
|
|
86
86
|
this.logger.log(`${'═'.repeat(60)}\n`);
|
|
87
87
|
|
|
88
88
|
try {
|
|
@@ -90,26 +90,26 @@ class SetBase {
|
|
|
90
90
|
this._validarCasos(casos);
|
|
91
91
|
|
|
92
92
|
// 2. Asegurar CAFs disponibles (usa pre-cargados si existen)
|
|
93
|
-
this.logger.log('
|
|
93
|
+
this.logger.log('Verificando folios (CAFs)...');
|
|
94
94
|
const cafs = preloadedCafs || await this.ensureCafs(casos);
|
|
95
95
|
|
|
96
96
|
if (preloadedCafs) {
|
|
97
97
|
for (const [tipoDte, cafPath] of Object.entries(preloadedCafs)) {
|
|
98
|
-
this.logger.log(`
|
|
98
|
+
this.logger.log(` ✓ CAF tipo ${tipoDte} (pre-cargado)`);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// 3. Generar DTEs (subclases implementan)
|
|
103
|
-
this.logger.log('
|
|
103
|
+
this.logger.log('Generando DTEs...');
|
|
104
104
|
const dtes = await this.generarDtes(casos, cafs);
|
|
105
|
-
this.logger.log(`
|
|
105
|
+
this.logger.log(` ✓ ${dtes.length} DTEs generados`);
|
|
106
106
|
|
|
107
107
|
// 4. Crear envío firmado
|
|
108
|
-
this.logger.log('
|
|
108
|
+
this.logger.log('Firmando envío...');
|
|
109
109
|
const envio = await this.crearEnvio(dtes);
|
|
110
110
|
|
|
111
111
|
// 5. Enviar al SII
|
|
112
|
-
this.logger.log('
|
|
112
|
+
this.logger.log('Enviando al SII...');
|
|
113
113
|
const respuesta = await this.enviarSii(envio);
|
|
114
114
|
|
|
115
115
|
// 6. Construir resultado con documentos para libros
|
|
@@ -160,14 +160,14 @@ class SetBase {
|
|
|
160
160
|
duration: Date.now() - startTime,
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
this.logger.log(`\n
|
|
164
|
-
this.logger.log(`
|
|
165
|
-
this.logger.log(`
|
|
163
|
+
this.logger.log(`\n[OK] ${this.label} completado`);
|
|
164
|
+
this.logger.log(` Track ID: ${result.trackId}`);
|
|
165
|
+
this.logger.log(` Duración: ${result.duration}ms\n`);
|
|
166
166
|
|
|
167
167
|
return result;
|
|
168
168
|
|
|
169
169
|
} catch (error) {
|
|
170
|
-
this.logger.error(`\n
|
|
170
|
+
this.logger.error(`\n[ERR] Error en ${this.label}: ${error.message}\n`);
|
|
171
171
|
|
|
172
172
|
const result = SetResult.failure(error.message);
|
|
173
173
|
result.duration = Date.now() - startTime;
|
|
@@ -197,7 +197,7 @@ class SetBase {
|
|
|
197
197
|
|
|
198
198
|
for (const tipoDte of this.tiposDte) {
|
|
199
199
|
const cantidad = this._calcularCantidadFolios(casos, tipoDte);
|
|
200
|
-
this.logger.log(`
|
|
200
|
+
this.logger.log(` Tipo ${tipoDte}: ${cantidad} folios requeridos`);
|
|
201
201
|
|
|
202
202
|
const cafPath = await this.cafManager.ensureCaf({
|
|
203
203
|
tipoDte,
|
|
@@ -212,7 +212,7 @@ class SetBase {
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
cafs[tipoDte] = cafPath;
|
|
215
|
-
this.logger.log(`
|
|
215
|
+
this.logger.log(` ✓ CAF tipo ${tipoDte}: ${cafPath}`);
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
return cafs;
|
|
@@ -237,7 +237,7 @@ class SetBase {
|
|
|
237
237
|
/**
|
|
238
238
|
* Genera los DTEs del set
|
|
239
239
|
*
|
|
240
|
-
*
|
|
240
|
+
* [!] DEBE SER IMPLEMENTADO POR SUBCLASES
|
|
241
241
|
*
|
|
242
242
|
* @abstract
|
|
243
243
|
* @param {Object} casos - Casos parseados del SII
|
package/cert/SetBasico.js
CHANGED
|
@@ -72,21 +72,21 @@ class SetBasico extends SetBase {
|
|
|
72
72
|
const dtes = [];
|
|
73
73
|
|
|
74
74
|
// 1. Generar facturas primero (las NC/ND referencian facturas)
|
|
75
|
-
this.logger.log('
|
|
75
|
+
this.logger.log(' Generando facturas...');
|
|
76
76
|
for (const caso of casos.casosFactura || []) {
|
|
77
77
|
const dte = await this._generarFactura(caso, cafs[33]);
|
|
78
78
|
dtes.push(dte);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// 2. Generar notas de crédito
|
|
82
|
-
this.logger.log('
|
|
82
|
+
this.logger.log(' Generando notas de crédito...');
|
|
83
83
|
for (const caso of casos.casosNC || []) {
|
|
84
84
|
const dte = await this._generarNotaCredito(caso, cafs[61]);
|
|
85
85
|
dtes.push(dte);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// 3. Generar notas de débito
|
|
89
|
-
this.logger.log('
|
|
89
|
+
this.logger.log(' Generando notas de débito...');
|
|
90
90
|
for (const caso of casos.casosND || []) {
|
|
91
91
|
const dte = await this._generarNotaDebito(caso, cafs[56]);
|
|
92
92
|
dtes.push(dte);
|
|
@@ -161,7 +161,7 @@ class SetBasico extends SetBase {
|
|
|
161
161
|
descuentoGlobalPct: caso.descuentoGlobalPct,
|
|
162
162
|
};
|
|
163
163
|
|
|
164
|
-
this.logger.log(`
|
|
164
|
+
this.logger.log(` ✓ Factura caso ${caso.id}: folio ${folio}`);
|
|
165
165
|
return dte;
|
|
166
166
|
}
|
|
167
167
|
|
|
@@ -248,7 +248,7 @@ class SetBasico extends SetBase {
|
|
|
248
248
|
items: itemsFinal,
|
|
249
249
|
};
|
|
250
250
|
|
|
251
|
-
this.logger.log(`
|
|
251
|
+
this.logger.log(` ✓ NC caso ${caso.id}: folio ${folio} (ref: caso ${caso.referenciaCaso})`);
|
|
252
252
|
return dte;
|
|
253
253
|
}
|
|
254
254
|
|
|
@@ -309,7 +309,7 @@ class SetBasico extends SetBase {
|
|
|
309
309
|
const dte = new DTE(dteDatos);
|
|
310
310
|
this._timbrarYFirmar(dte, caf);
|
|
311
311
|
|
|
312
|
-
this.logger.log(`
|
|
312
|
+
this.logger.log(` ✓ ND caso ${caso.id}: folio ${folio} (ref: caso ${caso.referenciaCaso})`);
|
|
313
313
|
return dte;
|
|
314
314
|
}
|
|
315
315
|
|
package/cert/SetCompra.js
CHANGED
|
@@ -66,20 +66,20 @@ class SetCompra extends SetBase {
|
|
|
66
66
|
const dtes = [];
|
|
67
67
|
|
|
68
68
|
// 1. Generar factura de compra
|
|
69
|
-
this.logger.log('
|
|
69
|
+
this.logger.log(' Generando factura de compra...');
|
|
70
70
|
const dteFactura = await this._generarFacturaCompra(casos.casoFactura, cafs[46]);
|
|
71
71
|
dtes.push(dteFactura);
|
|
72
72
|
|
|
73
73
|
// 2. Generar nota de crédito
|
|
74
74
|
if (casos.casoNC) {
|
|
75
|
-
this.logger.log('
|
|
75
|
+
this.logger.log(' Generando nota de crédito...');
|
|
76
76
|
const dteNc = await this._generarNotaCredito(casos.casoNC, cafs[61]);
|
|
77
77
|
dtes.push(dteNc);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// 3. Generar nota de débito
|
|
81
81
|
if (casos.casoND) {
|
|
82
|
-
this.logger.log('
|
|
82
|
+
this.logger.log(' Generando nota de débito...');
|
|
83
83
|
const dteNd = await this._generarNotaDebito(casos.casoND, cafs[56]);
|
|
84
84
|
dtes.push(dteNd);
|
|
85
85
|
}
|
|
@@ -139,7 +139,7 @@ class SetCompra extends SetBase {
|
|
|
139
139
|
items,
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
-
this.logger.log(`
|
|
142
|
+
this.logger.log(` ✓ Factura Compra caso ${caso.id}: folio ${folio}`);
|
|
143
143
|
return dte;
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -207,7 +207,7 @@ class SetCompra extends SetBase {
|
|
|
207
207
|
items,
|
|
208
208
|
};
|
|
209
209
|
|
|
210
|
-
this.logger.log(`
|
|
210
|
+
this.logger.log(` ✓ NC Compra caso ${caso.id}: folio ${folio} (ref: ${caso.referenciaCaso})`);
|
|
211
211
|
return dte;
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -265,7 +265,7 @@ class SetCompra extends SetBase {
|
|
|
265
265
|
const dte = new DTE(dteDatos);
|
|
266
266
|
this._timbrarYFirmar(dte, caf);
|
|
267
267
|
|
|
268
|
-
this.logger.log(`
|
|
268
|
+
this.logger.log(` ✓ ND Compra caso ${caso.id}: folio ${folio} (ref: ${caso.referenciaCaso})`);
|
|
269
269
|
return dte;
|
|
270
270
|
}
|
|
271
271
|
|
package/cert/SetExenta.js
CHANGED
|
@@ -69,21 +69,21 @@ class SetExenta extends SetBase {
|
|
|
69
69
|
const dtes = [];
|
|
70
70
|
|
|
71
71
|
// 1. Generar facturas exentas primero
|
|
72
|
-
this.logger.log('
|
|
72
|
+
this.logger.log(' Generando facturas exentas...');
|
|
73
73
|
for (const caso of casos.casosFactura || []) {
|
|
74
74
|
const dte = await this._generarFacturaExenta(caso, cafs[34]);
|
|
75
75
|
dtes.push(dte);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// 2. Generar notas de crédito
|
|
79
|
-
this.logger.log('
|
|
79
|
+
this.logger.log(' Generando notas de crédito...');
|
|
80
80
|
for (const caso of casos.casosNC || []) {
|
|
81
81
|
const dte = await this._generarNotaCredito(caso, cafs[61]);
|
|
82
82
|
dtes.push(dte);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// 3. Generar notas de débito
|
|
86
|
-
this.logger.log('
|
|
86
|
+
this.logger.log(' Generando notas de débito...');
|
|
87
87
|
for (const caso of casos.casosND || []) {
|
|
88
88
|
const dte = await this._generarNotaDebito(caso, cafs[56]);
|
|
89
89
|
dtes.push(dte);
|
|
@@ -144,7 +144,7 @@ class SetExenta extends SetBase {
|
|
|
144
144
|
items,
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
-
this.logger.log(`
|
|
147
|
+
this.logger.log(` ✓ Factura Exenta caso ${caso.id}: folio ${folio}`);
|
|
148
148
|
return dte;
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -212,7 +212,7 @@ class SetExenta extends SetBase {
|
|
|
212
212
|
items,
|
|
213
213
|
};
|
|
214
214
|
|
|
215
|
-
this.logger.log(`
|
|
215
|
+
this.logger.log(` ✓ NC Exenta caso ${caso.id}: folio ${folio} (ref: ${caso.referenciaCaso})`);
|
|
216
216
|
return dte;
|
|
217
217
|
}
|
|
218
218
|
|
|
@@ -270,7 +270,7 @@ class SetExenta extends SetBase {
|
|
|
270
270
|
const dte = new DTE(dteDatos);
|
|
271
271
|
this._timbrarYFirmar(dte, caf);
|
|
272
272
|
|
|
273
|
-
this.logger.log(`
|
|
273
|
+
this.logger.log(` ✓ ND Exenta caso ${caso.id}: folio ${folio} (ref: ${caso.referenciaCaso})`);
|
|
274
274
|
return dte;
|
|
275
275
|
}
|
|
276
276
|
|
package/cert/SetGuia.js
CHANGED
|
@@ -64,7 +64,7 @@ class SetGuia extends SetBase {
|
|
|
64
64
|
async generarDtes(casos, cafs) {
|
|
65
65
|
const dtes = [];
|
|
66
66
|
|
|
67
|
-
this.logger.log('
|
|
67
|
+
this.logger.log(' Generando guías de despacho...');
|
|
68
68
|
for (const caso of casos.casos || []) {
|
|
69
69
|
const dte = await this._generarGuia(caso, cafs[52]);
|
|
70
70
|
dtes.push(dte);
|
|
@@ -138,7 +138,7 @@ class SetGuia extends SetBase {
|
|
|
138
138
|
const dte = new DTE(dteDatos);
|
|
139
139
|
this._timbrarYFirmar(dte, caf);
|
|
140
140
|
|
|
141
|
-
this.logger.log(`
|
|
141
|
+
this.logger.log(` ✓ Guía caso ${caso.id}: folio ${folio} (IndTraslado: ${idDoc.IndTraslado})`);
|
|
142
142
|
return dte;
|
|
143
143
|
}
|
|
144
144
|
|
package/cert/SetsProvider.js
CHANGED
|
@@ -105,13 +105,13 @@ class SetsProvider {
|
|
|
105
105
|
* @returns {Promise<boolean>}
|
|
106
106
|
*/
|
|
107
107
|
async initSession() {
|
|
108
|
-
this.logger.log('[
|
|
108
|
+
this.logger.log('[SessionSii] Inicializando sesión SII...');
|
|
109
109
|
|
|
110
110
|
const siiCert = this._getSiiCert();
|
|
111
111
|
|
|
112
112
|
// Intentar cargar sesión existente
|
|
113
113
|
if (this.sessionPath && SiiCertificacion.isSessionValid(this.sessionPath)) {
|
|
114
|
-
this.logger.log('[
|
|
114
|
+
this.logger.log('[SessionSii] ✓ Sesión existente válida');
|
|
115
115
|
const loaded = siiCert.loadSession(this.sessionPath);
|
|
116
116
|
if (loaded) {
|
|
117
117
|
return true;
|
|
@@ -119,7 +119,7 @@ class SetsProvider {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
// Crear nueva sesión
|
|
122
|
-
this.logger.log('[
|
|
122
|
+
this.logger.log('[SessionSii] Estableciendo nueva sesión...');
|
|
123
123
|
try {
|
|
124
124
|
// verAvance() fuerza el login
|
|
125
125
|
await siiCert.verAvance();
|
|
@@ -128,12 +128,12 @@ class SetsProvider {
|
|
|
128
128
|
if (this.sessionPath) {
|
|
129
129
|
this._ensureDir(path.dirname(this.sessionPath));
|
|
130
130
|
siiCert.saveSession(this.sessionPath);
|
|
131
|
-
this.logger.log('[
|
|
131
|
+
this.logger.log('[SessionSii] ✓ Sesión guardada');
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
return true;
|
|
135
135
|
} catch (error) {
|
|
136
|
-
this.logger.error(`[
|
|
136
|
+
this.logger.error(`[SessionSii] [ERR] Error: ${error.message}`);
|
|
137
137
|
return false;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
@@ -153,11 +153,11 @@ class SetsProvider {
|
|
|
153
153
|
setsOpcionales = DEFAULT_SETS_OPCIONALES,
|
|
154
154
|
} = options;
|
|
155
155
|
|
|
156
|
-
this.logger.log('\n[
|
|
156
|
+
this.logger.log('\n[SessionSii] Obteniendo sets de prueba...');
|
|
157
157
|
|
|
158
158
|
// Si hay cache y no se fuerza refresh, retornar cache
|
|
159
159
|
if (!forceRefresh && this._estructurasCache) {
|
|
160
|
-
this.logger.log('[SetsProvider]
|
|
160
|
+
this.logger.log('[SetsProvider] ✓ Usando cache de estructuras');
|
|
161
161
|
return {
|
|
162
162
|
success: true,
|
|
163
163
|
regenerated: false,
|
|
@@ -212,7 +212,7 @@ class SetsProvider {
|
|
|
212
212
|
// Detectar si el set fue regenerado
|
|
213
213
|
const regenerated = this._detectRegeneration(result);
|
|
214
214
|
if (regenerated) {
|
|
215
|
-
this.logger.log('[SetsProvider]
|
|
215
|
+
this.logger.log('[SetsProvider] [!] Set regenerado - reiniciar proceso');
|
|
216
216
|
// Invalidar cualquier cache anterior
|
|
217
217
|
this.invalidateCache();
|
|
218
218
|
}
|
|
@@ -228,13 +228,13 @@ class SetsProvider {
|
|
|
228
228
|
(htmlLower.includes('postulacion factura electronica') && !htmlLower.includes('caso'))) {
|
|
229
229
|
// Distinguir: ¿es "no inscrito" o expiró la sesión?
|
|
230
230
|
if (htmlLower.includes('no inscrito') || (htmlLower.includes('no est') && htmlLower.includes('inscrito'))) {
|
|
231
|
-
this.logger.log('[
|
|
231
|
+
this.logger.log('[SessionSii] pe_generar2: empresa no inscrita en Postulación (fase avanzada).');
|
|
232
232
|
return { success: false, error: 'El contribuyente no está inscrito en Postulación en el portal SII.' };
|
|
233
233
|
}
|
|
234
234
|
// Sesión expiró en el portal aunque el archivo no lo sabía → forzar re-autenticación
|
|
235
235
|
// Cookies vencidas server-side: limpiar sesión guardada y pedir a
|
|
236
236
|
// generarSetPruebas que re-autentique por sí mismo via pe_generar
|
|
237
|
-
this.logger.log('[
|
|
237
|
+
this.logger.log('[SessionSii] [!] Sesión rechazada por portal, limpiando y reintentando...');
|
|
238
238
|
if (this.sessionPath) {
|
|
239
239
|
const SiiSession = require('../SiiSession');
|
|
240
240
|
SiiSession.clearSession(this.sessionPath);
|
|
@@ -284,7 +284,7 @@ class SetsProvider {
|
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
-
this.logger.log('[SetsProvider]
|
|
287
|
+
this.logger.log('[SetsProvider] ✓ Sets obtenidos correctamente');
|
|
288
288
|
|
|
289
289
|
return {
|
|
290
290
|
success: true,
|
|
@@ -296,7 +296,7 @@ class SetsProvider {
|
|
|
296
296
|
};
|
|
297
297
|
|
|
298
298
|
} catch (error) {
|
|
299
|
-
this.logger.error(`[SetsProvider]
|
|
299
|
+
this.logger.error(`[SetsProvider] [ERR] Error: ${error.message}`);
|
|
300
300
|
return {
|
|
301
301
|
success: false,
|
|
302
302
|
error: error.message,
|
|
@@ -329,7 +329,7 @@ class SetsProvider {
|
|
|
329
329
|
if (result.setDescargado?.rawHtml && this._lastNumeroAtencion) {
|
|
330
330
|
const match = result.setDescargado.rawHtml.match(/NUMERO DE ATENCI[^:]*:\s*(\d+)/i);
|
|
331
331
|
if (match && match[1] !== this._lastNumeroAtencion) {
|
|
332
|
-
this.logger.log(`[SetsProvider]
|
|
332
|
+
this.logger.log(`[SetsProvider] Número de atención cambió: ${this._lastNumeroAtencion} → ${match[1]}`);
|
|
333
333
|
return true;
|
|
334
334
|
}
|
|
335
335
|
}
|
|
@@ -351,19 +351,16 @@ class SetsProvider {
|
|
|
351
351
|
if (this.debugDir) {
|
|
352
352
|
this._saveDebug('set-texto.txt', textoLimpio);
|
|
353
353
|
}
|
|
354
|
-
|
|
355
|
-
// Usar SetParser del core
|
|
356
|
-
this.logger.log('[SetsProvider] Usando SetParser del core...');
|
|
357
354
|
|
|
358
355
|
const datosExtraidos = SetParser.extraerCasosDelSet(textoLimpio);
|
|
359
356
|
|
|
360
357
|
if (datosExtraidos.sets.length === 0) {
|
|
361
|
-
this.logger.log('[SetsProvider]
|
|
358
|
+
this.logger.log('[SetsProvider] [!] No se encontraron sets en el contenido');
|
|
362
359
|
return { estructuras: null, datosExtraidos: null };
|
|
363
360
|
}
|
|
364
361
|
|
|
365
|
-
this.logger.log(`[SetsProvider]
|
|
366
|
-
this.logger.log(`[SetsProvider]
|
|
362
|
+
this.logger.log(`[SetsProvider] Sets encontrados: ${datosExtraidos.sets.length}`);
|
|
363
|
+
this.logger.log(`[SetsProvider] Total casos: ${datosExtraidos.totalCasos}`);
|
|
367
364
|
|
|
368
365
|
// Guardar número de atención para detectar regeneración
|
|
369
366
|
if (datosExtraidos.sets[0]?.numeroAtencion) {
|
package/cert/Simulacion.js
CHANGED
|
@@ -53,7 +53,7 @@ class Simulacion {
|
|
|
53
53
|
const docRefs = {};
|
|
54
54
|
|
|
55
55
|
if (plan.length < 10) {
|
|
56
|
-
console.warn('
|
|
56
|
+
console.warn('[!] Se recomienda mínimo 10 documentos para simulación.');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
const envioDte = new EnvioDTE({ certificado: this.certificado });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devlas/dte-sii",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.15",
|
|
4
4
|
"description": "Facturación y boletas electrónicas para el SII de Chile. Genera, timbra, firma y envía DTEs, libros electrónicos y automatiza la certificación.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "dte-sii.d.ts",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@xmldom/xmldom": "^0.8.11",
|
|
33
33
|
"bwip-js": "^4.8.0",
|
|
34
|
+
"dotenv": "^17.3.1",
|
|
34
35
|
"fast-xml-parser": "^5.3.3",
|
|
35
36
|
"got": "^11.8.6",
|
|
36
37
|
"node-forge": "^1.3.3",
|