@devlas/dte-sii 2.5.0
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 +109 -0
- package/CAF.js +173 -0
- package/CafSolicitor.js +380 -0
- package/Certificado.js +123 -0
- package/ConsumoFolio.js +376 -0
- package/DTE.js +399 -0
- package/EnviadorSII.js +1304 -0
- package/Envio.js +196 -0
- package/FolioRegistry.js +553 -0
- package/FolioService.js +703 -0
- package/LICENSE +27 -0
- package/LibroBase.js +134 -0
- package/LibroCompraVenta.js +205 -0
- package/LibroGuia.js +225 -0
- package/README.md +239 -0
- package/Signer.js +94 -0
- package/SiiCertificacion.js +1189 -0
- package/SiiPortalAuth.js +460 -0
- package/SiiSession.js +499 -0
- package/cert/BoletaCert.js +731 -0
- package/cert/CertFolioHelper.js +185 -0
- package/cert/CertRunner.js +2658 -0
- package/cert/ConfigLoader.js +133 -0
- package/cert/IntercambioCert.js +429 -0
- package/cert/LibroCompras.js +359 -0
- package/cert/LibroGuias.js +171 -0
- package/cert/LibroVentas.js +153 -0
- package/cert/MuestrasImpresas.js +676 -0
- package/cert/SetBase.js +321 -0
- package/cert/SetBasico.js +413 -0
- package/cert/SetCompra.js +472 -0
- package/cert/SetExenta.js +490 -0
- package/cert/SetGuia.js +283 -0
- package/cert/SetParser.js +1184 -0
- package/cert/SetsProvider.js +499 -0
- package/cert/Simulacion.js +521 -0
- package/cert/comunaOficina.js +460 -0
- package/cert/index.js +124 -0
- package/cert/types.js +330 -0
- package/dte-sii.d.ts +458 -0
- package/index.js +428 -0
- package/package.json +48 -0
- package/utils/c14n.js +275 -0
- package/utils/calculo.js +396 -0
- package/utils/config.js +276 -0
- package/utils/constants.js +302 -0
- package/utils/emisor.js +174 -0
- package/utils/endpoints.js +225 -0
- package/utils/error.js +235 -0
- package/utils/index.js +339 -0
- package/utils/logger.js +239 -0
- package/utils/pfx.js +203 -0
- package/utils/receptor.js +218 -0
- package/utils/referencia.js +169 -0
- package/utils/resolucion.js +119 -0
- package/utils/rut.js +169 -0
- package/utils/sanitize.js +124 -0
- package/utils/tokenCache.js +214 -0
- package/utils/xml.js +358 -0
- package/utils.js +4 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// Copyright (c) 2026 Devlas SpA — https://devlas.cl
|
|
2
|
+
// Licencia MIT. Ver archivo LICENSE para mas detalles.
|
|
3
|
+
/**
|
|
4
|
+
* CertFolioHelper
|
|
5
|
+
*
|
|
6
|
+
* Helper para gestión de folios en certificación.
|
|
7
|
+
* Centraliza la lógica de reserva local de folios que estaba duplicada en todos los tests.
|
|
8
|
+
*
|
|
9
|
+
* @module dte-sii/cert/CertFolioHelper
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const crypto = require('crypto');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Clase helper para gestión de folios en certificación
|
|
16
|
+
* Reemplaza las funciones locales duplicadas en cada test
|
|
17
|
+
*/
|
|
18
|
+
class CertFolioHelper {
|
|
19
|
+
/**
|
|
20
|
+
* @param {Object} [options] - Opciones de configuración
|
|
21
|
+
* @param {string} [options.ambiente='certificacion'] - Ambiente (certificacion/produccion)
|
|
22
|
+
*/
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.ambiente = options.ambiente || 'certificacion';
|
|
25
|
+
this.counters = new Map(); // Contadores de folios por CAF
|
|
26
|
+
this.usedFolios = new Map(); // Folios usados por tipo DTE
|
|
27
|
+
this.sentFolios = new Map(); // Folios marcados como enviados
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Construye clave única para un CAF
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
_buildKey({ tipoDte, folioDesde, folioHasta }) {
|
|
35
|
+
return `${tipoDte}|${folioDesde}|${folioHasta}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Crea fingerprint de un CAF para identificación única
|
|
40
|
+
* @param {string} cafXml - XML del CAF
|
|
41
|
+
* @returns {string} Hash del CAF
|
|
42
|
+
*/
|
|
43
|
+
createCafFingerprint(cafXml) {
|
|
44
|
+
if (!cafXml) return 'local';
|
|
45
|
+
return crypto.createHash('sha256').update(cafXml).digest('hex').slice(0, 12);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Reserva el siguiente folio disponible para un CAF
|
|
50
|
+
*
|
|
51
|
+
* @param {Object} params - Parámetros
|
|
52
|
+
* @param {number} params.tipoDte - Tipo de DTE
|
|
53
|
+
* @param {number} params.folioDesde - Folio inicial del CAF
|
|
54
|
+
* @param {number} params.folioHasta - Folio final del CAF
|
|
55
|
+
* @returns {number} Folio reservado
|
|
56
|
+
* @throws {Error} Si no hay folios disponibles
|
|
57
|
+
*/
|
|
58
|
+
reserveNextFolio({ tipoDte, folioDesde, folioHasta }) {
|
|
59
|
+
const desde = Number(folioDesde);
|
|
60
|
+
const hasta = Number(folioHasta);
|
|
61
|
+
|
|
62
|
+
if (Number.isNaN(desde) || Number.isNaN(hasta)) {
|
|
63
|
+
throw new Error('Parámetros inválidos para reservar folio');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const key = this._buildKey({ tipoDte, folioDesde: desde, folioHasta: hasta });
|
|
67
|
+
const next = this.counters.has(key) ? this.counters.get(key) : desde;
|
|
68
|
+
|
|
69
|
+
if (next > hasta) {
|
|
70
|
+
throw new Error(`No hay más folios disponibles (${desde}-${hasta})`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.counters.set(key, next + 1);
|
|
74
|
+
return next;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Marca un folio como usado (para evitar reutilización)
|
|
79
|
+
*
|
|
80
|
+
* @param {number} tipoDte - Tipo de DTE
|
|
81
|
+
* @param {number} folio - Número de folio
|
|
82
|
+
*/
|
|
83
|
+
markFolioUsed(tipoDte, folio) {
|
|
84
|
+
if (!this.usedFolios.has(tipoDte)) {
|
|
85
|
+
this.usedFolios.set(tipoDte, new Set());
|
|
86
|
+
}
|
|
87
|
+
this.usedFolios.get(tipoDte).add(folio);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Verifica si un folio ya fue usado
|
|
92
|
+
*
|
|
93
|
+
* @param {number} tipoDte - Tipo de DTE
|
|
94
|
+
* @param {number} folio - Número de folio
|
|
95
|
+
* @returns {boolean}
|
|
96
|
+
*/
|
|
97
|
+
isFolioUsed(tipoDte, folio) {
|
|
98
|
+
return this.usedFolios.get(tipoDte)?.has(folio) || false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Marca un folio como enviado al SII
|
|
103
|
+
*
|
|
104
|
+
* @param {Object} params - Parámetros
|
|
105
|
+
* @param {number} params.tipoDte - Tipo de DTE
|
|
106
|
+
* @param {number} params.folio - Número de folio
|
|
107
|
+
* @param {string} [params.trackId] - TrackId del envío
|
|
108
|
+
* @param {Object} [params.extra] - Datos adicionales
|
|
109
|
+
*/
|
|
110
|
+
markFolioSent({ tipoDte, folio, trackId, extra }) {
|
|
111
|
+
const key = `${tipoDte}|${folio}`;
|
|
112
|
+
this.sentFolios.set(key, {
|
|
113
|
+
tipoDte,
|
|
114
|
+
folio,
|
|
115
|
+
trackId,
|
|
116
|
+
sentAt: new Date().toISOString(),
|
|
117
|
+
...extra,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Libera folios reservados (para cleanup en caso de error)
|
|
123
|
+
* Nota: En esta implementación simple no hace nada real
|
|
124
|
+
* ya que los counters son locales a la ejecución
|
|
125
|
+
*
|
|
126
|
+
* @param {Object} params - Parámetros
|
|
127
|
+
*/
|
|
128
|
+
releaseFolios(params) {
|
|
129
|
+
// En certificación local, no hay necesidad de liberar
|
|
130
|
+
// Esta función existe para compatibilidad con la interfaz
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Resetea contadores para un tipo de DTE específico
|
|
135
|
+
* Útil cuando se solicita un nuevo CAF
|
|
136
|
+
*
|
|
137
|
+
* @param {number} tipoDte - Tipo de DTE
|
|
138
|
+
*/
|
|
139
|
+
resetCountersForTipo(tipoDte) {
|
|
140
|
+
for (const [key] of this.counters) {
|
|
141
|
+
if (key.startsWith(`${tipoDte}|`)) {
|
|
142
|
+
this.counters.delete(key);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Obtiene estadísticas de folios usados
|
|
149
|
+
*
|
|
150
|
+
* @returns {Object} Estadísticas por tipo de DTE
|
|
151
|
+
*/
|
|
152
|
+
getStats() {
|
|
153
|
+
const stats = {};
|
|
154
|
+
for (const [tipoDte, folios] of this.usedFolios) {
|
|
155
|
+
stats[tipoDte] = {
|
|
156
|
+
count: folios.size,
|
|
157
|
+
folios: Array.from(folios).sort((a, b) => a - b),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return stats;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Verifica que un CAF tenga folios nuevos disponibles
|
|
165
|
+
* (que no hayan sido usados en esta sesión)
|
|
166
|
+
*
|
|
167
|
+
* @param {number} tipoDte - Tipo de DTE
|
|
168
|
+
* @param {number} folioDesde - Folio inicial
|
|
169
|
+
* @param {number} folioHasta - Folio final
|
|
170
|
+
* @returns {boolean}
|
|
171
|
+
*/
|
|
172
|
+
hasNewFolios(tipoDte, folioDesde, folioHasta) {
|
|
173
|
+
const usados = this.usedFolios.get(tipoDte);
|
|
174
|
+
if (!usados || usados.size === 0) return true;
|
|
175
|
+
|
|
176
|
+
for (let f = folioDesde; f <= folioHasta; f++) {
|
|
177
|
+
if (!usados.has(f)) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
module.exports = CertFolioHelper;
|