@devlas/dte-sii 2.5.11 → 2.5.13
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/CafSolicitor.js +378 -378
- package/ConsumoFolio.js +376 -376
- package/Envio.js +196 -196
- package/LICENSE +27 -27
- package/README.md +273 -273
- package/SiiCertificacion.js +137 -22
- package/SiiPortalAuth.js +474 -474
- package/cert/CertRunner.js +153 -21
- package/cert/ConfigLoader.js +131 -131
- package/cert/IntercambioCert.js +427 -427
- package/cert/LibroCompras.js +397 -357
- package/cert/LibroGuias.js +169 -169
- package/cert/LibroVentas.js +151 -151
- package/cert/MuestrasImpresas.js +676 -676
- package/cert/SetBase.js +319 -319
- package/cert/SetBasico.js +411 -411
- package/cert/SetCompra.js +470 -470
- package/cert/SetExenta.js +488 -488
- package/cert/SetGuia.js +281 -281
- package/cert/SetParser.js +1265 -1182
- package/cert/SetsProvider.js +497 -497
- package/cert/Simulacion.js +519 -519
- package/cert/comunaOficina.js +458 -458
- package/cert/index.js +122 -122
- package/cert/types.js +328 -328
- package/package.json +49 -49
package/SiiCertificacion.js
CHANGED
|
@@ -378,14 +378,22 @@ class SiiCertificacion {
|
|
|
378
378
|
// Parsear estado de cada set/libro
|
|
379
379
|
const estadoSets = {};
|
|
380
380
|
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
const
|
|
388
|
-
|
|
381
|
+
// Parsear estado de cada set/libro fila por fila para evitar falsos positivos
|
|
382
|
+
// (la regex global cruzaba filas y asignaba REVISADO CONFORME de SET CASO GENERAL a LIBRO DE VENTAS)
|
|
383
|
+
const rows = html.split(/<\/tr>/i);
|
|
384
|
+
for (const row of rows) {
|
|
385
|
+
const nameMatch = /(SET[^<\n\r]*|LIBRO[^<\n\r]*)<\/font><\/td>/i.exec(row);
|
|
386
|
+
if (!nameMatch) continue;
|
|
387
|
+
const nombre = nameMatch[1].trim();
|
|
388
|
+
// Estado explícito en <b>...</b>
|
|
389
|
+
const stateMatch = /<b>([^<]+)<\/b>/i.exec(row);
|
|
390
|
+
if (stateMatch) {
|
|
391
|
+
estadoSets[nombre] = stateMatch[1].trim().toUpperCase();
|
|
392
|
+
} else {
|
|
393
|
+
// Fila con campos input: leer valor EST oculto (S01 = sin declarar, S21 = declarado)
|
|
394
|
+
const estMatch = /name="EST\d+"[^>]*value="([^"]+)"/i.exec(row);
|
|
395
|
+
estadoSets[nombre] = estMatch ? estMatch[1] : 'S01';
|
|
396
|
+
}
|
|
389
397
|
}
|
|
390
398
|
|
|
391
399
|
// Verificar si todos los sets requeridos están REVISADO CONFORME
|
|
@@ -541,16 +549,17 @@ class SiiCertificacion {
|
|
|
541
549
|
// El SII cambia el orden según qué sets están aprobados
|
|
542
550
|
const fieldMapping = {};
|
|
543
551
|
|
|
544
|
-
|
|
552
|
+
// Guardar pe_avance2 para debug (siempre)
|
|
553
|
+
{
|
|
545
554
|
const fs = require('fs');
|
|
546
555
|
const path = require('path');
|
|
547
|
-
const debugDir = process.env.SII_DEBUG_DIR || path.join(__dirname, '../../debug');
|
|
556
|
+
const debugDir = process.env.SII_DEBUG_DIR || path.join(__dirname, '../../debug/cert-v2');
|
|
548
557
|
if (!fs.existsSync(debugDir)) {
|
|
549
558
|
fs.mkdirSync(debugDir, { recursive: true });
|
|
550
559
|
}
|
|
551
|
-
const debugPath = path.join(debugDir, '
|
|
560
|
+
const debugPath = path.join(debugDir, 'pe_avance2_form.html');
|
|
552
561
|
fs.writeFileSync(debugPath, formHtml, 'utf8');
|
|
553
|
-
console.log('
|
|
562
|
+
console.log(' 📄 HTML pe_avance2 formulario guardado en debug/cert-v2/pe_avance2_form.html');
|
|
554
563
|
}
|
|
555
564
|
|
|
556
565
|
// Extraer todas las filas <tr>...</tr> del formulario
|
|
@@ -737,13 +746,112 @@ class SiiCertificacion {
|
|
|
737
746
|
// Éxito si el form se envió sin errores de sesión/contenido.
|
|
738
747
|
// El estado del envío (ERRORES O REPAROS / EN REVISION / REVISADO CONFORME)
|
|
739
748
|
// NO determina el éxito de la declaración — eso se resuelve vía polling.
|
|
740
|
-
const
|
|
749
|
+
const postOk = (!hasError || hasSuccess) && !sesionExpirada && !contenidoNoCorresponde;
|
|
750
|
+
|
|
751
|
+
if (!postOk) {
|
|
752
|
+
return {
|
|
753
|
+
success: false,
|
|
754
|
+
error: errorMsg || undefined,
|
|
755
|
+
status: declareResponse.status,
|
|
756
|
+
rawHtml: body,
|
|
757
|
+
formHtml,
|
|
758
|
+
setsDeclarados: Object.keys(sets),
|
|
759
|
+
formDataSent: formData,
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Guardar HTML de pe_avance3 (respuesta de declaración) siempre para debug
|
|
764
|
+
{
|
|
765
|
+
const fs = require('fs');
|
|
766
|
+
const path = require('path');
|
|
767
|
+
const debugDir = process.env.SII_DEBUG_DIR || path.join(__dirname, '../../debug/cert-v2');
|
|
768
|
+
if (!fs.existsSync(debugDir)) fs.mkdirSync(debugDir, { recursive: true });
|
|
769
|
+
fs.writeFileSync(path.join(debugDir, 'pe_avance3_response.html'), body, 'utf8');
|
|
770
|
+
console.log(' 📄 HTML pe_avance3 guardado en debug/cert-v2/pe_avance3_response.html');
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// 7. VERIFICACIÓN POST-DECLARACIÓN: Re-leer pe_avance2 y confirmar que los TrackIDs se guardaron
|
|
774
|
+
// Si aparece "EN REVISION" → la declaración fue aceptada y el SII está procesando
|
|
775
|
+
// Si reaparecen inputs vacíos → la declaración no se guardó
|
|
776
|
+
let verificado = true;
|
|
777
|
+
let verificacionError = '';
|
|
778
|
+
let enRevision = false;
|
|
779
|
+
try {
|
|
780
|
+
const verifyResponse = await this.session.submitForm(
|
|
781
|
+
'/cvc_cgi/dte/pe_avance2',
|
|
782
|
+
{ RUT_EMP: this.rutEmpresa, DV_EMP: this.dvEmpresa, ACEPTAR: 'Continuar' },
|
|
783
|
+
'https://maullin.sii.cl/cvc_cgi/dte/pe_avance1'
|
|
784
|
+
);
|
|
785
|
+
const verifyHtml = verifyResponse.body || '';
|
|
786
|
+
|
|
787
|
+
// Guardar HTML de verificación pe_avance2 siempre
|
|
788
|
+
{
|
|
789
|
+
const fs = require('fs');
|
|
790
|
+
const path = require('path');
|
|
791
|
+
const debugDir = process.env.SII_DEBUG_DIR || path.join(__dirname, '../../debug/cert-v2');
|
|
792
|
+
if (!fs.existsSync(debugDir)) fs.mkdirSync(debugDir, { recursive: true });
|
|
793
|
+
fs.writeFileSync(path.join(debugDir, 'pe_avance2_verify.html'), verifyHtml, 'utf8');
|
|
794
|
+
console.log(' 📄 HTML pe_avance2 verificación guardado en debug/cert-v2/pe_avance2_verify.html');
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Para cada set que declaramos, verificar estado
|
|
798
|
+
const verifyRows = verifyHtml.split(/<\/tr>/i);
|
|
799
|
+
const camposVacios = [];
|
|
800
|
+
const camposEnRevision = [];
|
|
801
|
+
for (const [setName, index] of Object.entries(fieldMapping)) {
|
|
802
|
+
if (!sets[setName]) continue;
|
|
803
|
+
for (const row of verifyRows) {
|
|
804
|
+
const numEnvMatch = row.match(new RegExp(`NAME="NUM_ENV${index}"`, 'i'));
|
|
805
|
+
if (!numEnvMatch) {
|
|
806
|
+
// Si no hay input NUM_ENV, verificar si aparece REVISADO CONFORME o EN REVISION
|
|
807
|
+
const labelPattern = patterns.find(p => p.name === setName);
|
|
808
|
+
if (labelPattern && labelPattern.label.test(row)) {
|
|
809
|
+
if (/<b>[^<]*REVISADO CONFORME[^<]*<\/b>/i.test(row)) break;
|
|
810
|
+
if (/EN REVISION/i.test(row)) {
|
|
811
|
+
camposEnRevision.push(setName);
|
|
812
|
+
break;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
// Tiene input — verificar si tiene valor o está REVISADO CONFORME
|
|
818
|
+
const tieneConforme = /<b>[^<]*REVISADO CONFORME[^<]*<\/b>/i.test(row);
|
|
819
|
+
if (tieneConforme) break;
|
|
820
|
+
if (/EN REVISION/i.test(row)) {
|
|
821
|
+
camposEnRevision.push(setName);
|
|
822
|
+
break;
|
|
823
|
+
}
|
|
824
|
+
const valueMatch = row.match(new RegExp(`NAME="NUM_ENV${index}"[^>]*value="([^"]*)"`, 'i'));
|
|
825
|
+
const tieneValor = valueMatch && valueMatch[1] && valueMatch[1].trim() !== '';
|
|
826
|
+
if (!tieneValor) {
|
|
827
|
+
camposVacios.push(setName);
|
|
828
|
+
}
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
if (camposEnRevision.length > 0) {
|
|
834
|
+
enRevision = true;
|
|
835
|
+
console.log(` 🔄 EN REVISION: ${camposEnRevision.join(', ')} — declaración aceptada, SII procesando`);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
if (camposVacios.length > 0 && !enRevision) {
|
|
839
|
+
verificado = false;
|
|
840
|
+
verificacionError = `Declaración NO se guardó en el portal SII. Campos vacíos para: ${camposVacios.join(', ')}. Posible error de sesión o TrackID no reconocido.`;
|
|
841
|
+
console.log(` ⚠️ ${verificacionError}`);
|
|
842
|
+
}
|
|
843
|
+
} catch (verifyErr) {
|
|
844
|
+
console.log(` ⚠️ No se pudo verificar la declaración: ${verifyErr.message}`);
|
|
845
|
+
}
|
|
741
846
|
|
|
742
847
|
return {
|
|
743
|
-
success,
|
|
744
|
-
error: errorMsg || undefined,
|
|
848
|
+
success: verificado || enRevision,
|
|
849
|
+
error: verificacionError || errorMsg || undefined,
|
|
850
|
+
verificado,
|
|
851
|
+
enRevision,
|
|
745
852
|
status: declareResponse.status,
|
|
746
853
|
rawHtml: body,
|
|
854
|
+
formHtml,
|
|
747
855
|
setsDeclarados: Object.keys(sets),
|
|
748
856
|
formDataSent: formData,
|
|
749
857
|
};
|
|
@@ -1102,13 +1210,17 @@ class SiiCertificacion {
|
|
|
1102
1210
|
for (const [key, { nombre, regex }] of Object.entries(SiiCertificacion.ESTADO_PATTERNS)) {
|
|
1103
1211
|
const match = result.rawHtml?.match(regex);
|
|
1104
1212
|
if (match) {
|
|
1213
|
+
const estadoTexto = match[1].trim();
|
|
1214
|
+
const upper = estadoTexto.toUpperCase();
|
|
1105
1215
|
estados[key] = {
|
|
1106
1216
|
nombre,
|
|
1107
|
-
estado:
|
|
1108
|
-
esConforme:
|
|
1109
|
-
enRevision:
|
|
1110
|
-
esRechazado:
|
|
1111
|
-
|
|
1217
|
+
estado: estadoTexto,
|
|
1218
|
+
esConforme: upper.includes('REVISADO CONFORME'),
|
|
1219
|
+
enRevision: upper.includes('EN REVISION'),
|
|
1220
|
+
esRechazado: upper.includes('RECHAZADO') || upper.includes('ERRORES'),
|
|
1221
|
+
esReparos: upper.includes('REPAROS'),
|
|
1222
|
+
porRealizar: upper.includes('POR REALIZAR'),
|
|
1223
|
+
esAnulado: upper.includes('ANULADO'),
|
|
1112
1224
|
};
|
|
1113
1225
|
}
|
|
1114
1226
|
}
|
|
@@ -1119,9 +1231,12 @@ class SiiCertificacion {
|
|
|
1119
1231
|
estados.setSimulacion = {
|
|
1120
1232
|
nombre: 'SET SIMULACION',
|
|
1121
1233
|
estado: 'PENDIENTE CONFIRMAR',
|
|
1122
|
-
esConforme:
|
|
1123
|
-
enRevision:
|
|
1234
|
+
esConforme: false,
|
|
1235
|
+
enRevision: true,
|
|
1124
1236
|
esRechazado: false,
|
|
1237
|
+
esReparos: false,
|
|
1238
|
+
porRealizar: false,
|
|
1239
|
+
esAnulado: false,
|
|
1125
1240
|
pendienteConfirmar: true,
|
|
1126
1241
|
};
|
|
1127
1242
|
}
|