@devlas/dte-sii 2.18.1 → 2.18.2
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/cert/CertRunner.js +58 -7
- package/package.json +1 -1
package/cert/CertRunner.js
CHANGED
|
@@ -3842,9 +3842,25 @@ class CertRunner {
|
|
|
3842
3842
|
};
|
|
3843
3843
|
}
|
|
3844
3844
|
|
|
3845
|
-
//
|
|
3845
|
+
// ⚠️ `INGRESO` NO es "ya enviadas": es una revisión creada y **sin someter**.
|
|
3846
|
+
//
|
|
3847
|
+
// El portal deja la revisión en ese estado mientras se suben los PDFs, y solo pasa a
|
|
3848
|
+
// POR REVISAR cuando se llama a `solicitaRevisionSII`. Si la subida se corta a mitad
|
|
3849
|
+
// —el SII devuelve 503 de forma intermitente— queda una revisión con parte de los
|
|
3850
|
+
// archivos que el SII no va a mirar nunca.
|
|
3851
|
+
//
|
|
3852
|
+
// Tratarla como completada fue un bug real (24/08/2026): la subida murió en el archivo
|
|
3853
|
+
// 47 de 64 con un 503, el reintento vio `INGRESO`, devolvió `alreadyCompleted`, la etapa
|
|
3854
|
+
// se marcó cumplida y el pipeline avanzó al Cierre, donde el SII contestó que la empresa
|
|
3855
|
+
// seguía en DOCUMENTOS IMPRESOS. La corrida quedó trabada dando la subida por hecha.
|
|
3856
|
+
//
|
|
3857
|
+
// Ahora se retoma esa misma revisión: se saltea `creaLista` y se sube sobre su ID.
|
|
3858
|
+
const reanudarRevision = estadoActual === 'INGRESO';
|
|
3859
|
+
|
|
3860
|
+
// Si ya hay una revisión activa Y SOMETIDA (no rechazada ni aprobada), no se re-sube.
|
|
3846
3861
|
// El SII sólo permite crear nueva revisión cuando el estado es RECHAZADO o APROBADO.
|
|
3847
|
-
if (estadoActual &&
|
|
3862
|
+
if (estadoActual && !reanudarRevision
|
|
3863
|
+
&& estadoActual !== 'RECHAZADO' && estadoActual !== 'APROBADO') {
|
|
3848
3864
|
// Extraer detalles adicionales de la respuesta leeImpreso para diagnóstico.
|
|
3849
3865
|
//
|
|
3850
3866
|
// ⚠️ NO se intenta sacar de acá la cantidad de documentos. La tabla de strings trae
|
|
@@ -3869,9 +3885,27 @@ class CertRunner {
|
|
|
3869
3885
|
console.log(` → No hay revisión previa — creando primera revisión`);
|
|
3870
3886
|
}
|
|
3871
3887
|
|
|
3872
|
-
// ── Paso 2: crear
|
|
3888
|
+
// ── Paso 2: crear la revisión, o retomar la que quedó a medias ────────────
|
|
3889
|
+
let revId = null;
|
|
3890
|
+
let revIdEncoded = null;
|
|
3891
|
+
|
|
3892
|
+
if (reanudarRevision) {
|
|
3893
|
+
// El ID viaja como Long GWT en la respuesta de `leeImpreso`.
|
|
3894
|
+
for (const m of leeResp.body.matchAll(/'([A-Za-z0-9$_]{3,7})'/g)) {
|
|
3895
|
+
const n = decodeGwtLong(m[1]);
|
|
3896
|
+
if (n >= 10000 && n <= 9999999) { revId = n; revIdEncoded = m[1]; break; }
|
|
3897
|
+
}
|
|
3898
|
+
if (revId) {
|
|
3899
|
+
console.log(` → Revisión ${revId} quedó en INGRESO (creada, sin someter) — se retoma y se completa`);
|
|
3900
|
+
} else {
|
|
3901
|
+
console.log(' → Estado INGRESO pero no se pudo leer el ID de revisión — se crea una nueva');
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3905
|
+
// ── Paso 2b: crear nueva lista/revisión (creaLista) ───────────────────────
|
|
3873
3906
|
// Params (6): amb=Z, rutNum, dv, proveedor=rutNum, provDv=dv, provNomre=""
|
|
3874
3907
|
// String table (9): module, policy, svc, method, String type, Z, rutNum, dv, ""
|
|
3908
|
+
if (!revId) {
|
|
3875
3909
|
const creaBody =
|
|
3876
3910
|
`7|0|9|${GWT_BASE}|${policyHash}|${GWT_SVC}|creaLista|` +
|
|
3877
3911
|
`java.lang.String/2004016611|Z|${rutNum}|${dvChar}||` +
|
|
@@ -3899,8 +3933,6 @@ class CertRunner {
|
|
|
3899
3933
|
}
|
|
3900
3934
|
|
|
3901
3935
|
// Extraer ID de revisión (Long codificado en GWT base64, ej: 'BAqo' = 264872)
|
|
3902
|
-
let revId = null;
|
|
3903
|
-
let revIdEncoded = null;
|
|
3904
3936
|
for (const m of creaResp.body.matchAll(/'([A-Za-z0-9$_]{3,7})'/g)) {
|
|
3905
3937
|
const n = decodeGwtLong(m[1]);
|
|
3906
3938
|
if (n >= 10000 && n <= 9999999) { revId = n; revIdEncoded = m[1]; break; }
|
|
@@ -3911,8 +3943,10 @@ class CertRunner {
|
|
|
3911
3943
|
if (debugDir) {
|
|
3912
3944
|
fs.writeFileSync(path.join(debugDir, `pdfte-crea-lista-resp.txt`), creaResp.body, 'utf8');
|
|
3913
3945
|
}
|
|
3946
|
+
} // fin del bloque creaLista (se saltea al retomar una revisión en INGRESO)
|
|
3914
3947
|
|
|
3915
3948
|
// ── Paso 3: subir cada PDF ────────────────────────────────────────────────
|
|
3949
|
+
const SUBIDA_MAX_INTENTOS = 4; // 1 intento + 3 reintentos ante 5xx del portal
|
|
3916
3950
|
const uploadUrl = `${GWT_BASE}upload`;
|
|
3917
3951
|
let uploadedCount = 0;
|
|
3918
3952
|
for (const pdfPath of pdfPaths) {
|
|
@@ -3931,7 +3965,7 @@ class CertRunner {
|
|
|
3931
3965
|
const closing = Buffer.from(`--${boundary}--\r\n`);
|
|
3932
3966
|
const formBody = Buffer.concat([partFile, partId, partAmb, closing]);
|
|
3933
3967
|
|
|
3934
|
-
const
|
|
3968
|
+
const peticionSubida = {
|
|
3935
3969
|
method: 'POST',
|
|
3936
3970
|
body: formBody,
|
|
3937
3971
|
headers: {
|
|
@@ -3942,7 +3976,24 @@ class CertRunner {
|
|
|
3942
3976
|
'Pragma': 'no-cache',
|
|
3943
3977
|
},
|
|
3944
3978
|
cookies,
|
|
3945
|
-
}
|
|
3979
|
+
};
|
|
3980
|
+
let upResp = await makeReq(uploadUrl, peticionSubida);
|
|
3981
|
+
|
|
3982
|
+
// ⚠️ El portal del SII devuelve 5xx de forma intermitente, y cortar la subida a mitad
|
|
3983
|
+
// deja la revisión con parte de los archivos y sin someter. Pasó el 24/08/2026: un 503
|
|
3984
|
+
// en el archivo 47 de 64 dejó la revisión en INGRESO y la corrida trabada.
|
|
3985
|
+
//
|
|
3986
|
+
// Un 5xx no dice nada del archivo, dice que el servicio no está: se reintenta el mismo
|
|
3987
|
+
// POST. Un 4xx sí es del archivo o de la sesión, y ahí cortar es lo correcto.
|
|
3988
|
+
let intentoSubida = 1;
|
|
3989
|
+
while (upResp.status >= 500 && intentoSubida < SUBIDA_MAX_INTENTOS) {
|
|
3990
|
+
const espera = 2000 * intentoSubida;
|
|
3991
|
+
console.log(` [!] ${filename} → HTTP ${upResp.status}, reintentando en ${espera / 1000}s ` +
|
|
3992
|
+
`(${intentoSubida}/${SUBIDA_MAX_INTENTOS - 1})`);
|
|
3993
|
+
await sleep(espera);
|
|
3994
|
+
intentoSubida++;
|
|
3995
|
+
upResp = await makeReq(uploadUrl, peticionSubida);
|
|
3996
|
+
}
|
|
3946
3997
|
|
|
3947
3998
|
if (upResp.status !== 200) {
|
|
3948
3999
|
throw new Error(`pdfdteInternet upload ${filename} → HTTP ${upResp.status}: ${upResp.body.substring(0, 150)}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devlas/dte-sii",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.2",
|
|
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",
|