@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
package/DTE.js
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
// Copyright (c) 2026 Devlas SpA — https://devlas.cl
|
|
2
|
+
// Licencia MIT. Ver archivo LICENSE para mas detalles.
|
|
3
|
+
/**
|
|
4
|
+
* Documento Tributario Electrónico
|
|
5
|
+
*
|
|
6
|
+
* Genera, timbra y firma documentos tributarios electrónicos
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
const { XMLBuilder } = require('fast-xml-parser');
|
|
11
|
+
const { DOMParser } = require('@xmldom/xmldom');
|
|
12
|
+
const {
|
|
13
|
+
sanitizeSiiText,
|
|
14
|
+
formatBase64InXml,
|
|
15
|
+
normalizeEmisor,
|
|
16
|
+
normalizeReceptor,
|
|
17
|
+
calcularTotalesDesdeDetalle,
|
|
18
|
+
TASA_IVA_DEFAULT,
|
|
19
|
+
TIPOS_BOLETA,
|
|
20
|
+
TASA_IVA,
|
|
21
|
+
} = require('./utils');
|
|
22
|
+
const { serializeNode, fixEntities, escapeAttr, escapeText, buildSignedInfo, buildSignature } = require('./utils/c14n');
|
|
23
|
+
|
|
24
|
+
// ============================================
|
|
25
|
+
// CONSTANTES
|
|
26
|
+
// ============================================
|
|
27
|
+
|
|
28
|
+
// Según schema SII EnvioDTE_v10.xsd, el orden de campos en IdDoc es:
|
|
29
|
+
// TipoDTE, Folio, FchEmis, IndNoRebaja, TipoDespacho, IndTraslado, TpoImpresion,
|
|
30
|
+
// IndServicio, MntBruto, TpoTranCompra, TpoTranVenta, FmaPago, FmaPagExp, ...
|
|
31
|
+
const CAMPOS_IDDOC_OPCIONALES = [
|
|
32
|
+
'IndNoRebaja', 'TipoDespacho', 'IndTraslado', 'TpoImpresion', 'IndServicio',
|
|
33
|
+
'MntBruto', 'TpoTranCompra', 'TpoTranVenta', 'FmaPago', 'FmaPagExp',
|
|
34
|
+
'FchCancel', 'MntCancel', 'SaldoInsol', 'MntPagos', 'FchVenc',
|
|
35
|
+
'PeriodoDesde', 'PeriodoHasta', 'MedioPago', 'TpoCtaPago', 'NumCtaPago',
|
|
36
|
+
'BcoPago', 'TermPagoCdg', 'TermPagoGlosa', 'TermPagoDias', 'FchVencPago',
|
|
37
|
+
'IndMntNeto',
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// ============================================
|
|
41
|
+
// CLASE DTE
|
|
42
|
+
// ============================================
|
|
43
|
+
|
|
44
|
+
class DTE {
|
|
45
|
+
/**
|
|
46
|
+
* @param {Object} datos - Datos del DTE (simplificado o estructurado)
|
|
47
|
+
*/
|
|
48
|
+
constructor(datos) {
|
|
49
|
+
if (this._esFormatoSimplificado(datos)) {
|
|
50
|
+
this.datos = this._convertirDatosSimplificados(datos);
|
|
51
|
+
this._certificado = datos.certificado;
|
|
52
|
+
this._caf = datos.caf;
|
|
53
|
+
} else {
|
|
54
|
+
this.datos = datos;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.montoTotal = this.datos.Encabezado?.Totales?.MntTotal || 0;
|
|
58
|
+
this.fechaEmision = this.datos.Encabezado?.IdDoc?.FchEmis;
|
|
59
|
+
this.xml = null;
|
|
60
|
+
this.tedXml = null;
|
|
61
|
+
this.tmstFirma = null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_esFormatoSimplificado(datos) {
|
|
65
|
+
return datos.tipo !== undefined && datos.folio !== undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ============================================
|
|
69
|
+
// CONVERSIÓN DE DATOS
|
|
70
|
+
// ============================================
|
|
71
|
+
|
|
72
|
+
_convertirDatosSimplificados(d) {
|
|
73
|
+
const esExenta = d.tipo === 41;
|
|
74
|
+
const { detalle, mntBruto, mntExento } = this._procesarItems(d.items, esExenta);
|
|
75
|
+
const totales = this._calcularTotales(mntBruto, mntExento, esExenta);
|
|
76
|
+
|
|
77
|
+
const resultado = {
|
|
78
|
+
Encabezado: {
|
|
79
|
+
IdDoc: {
|
|
80
|
+
TipoDTE: d.tipo,
|
|
81
|
+
Folio: d.folio,
|
|
82
|
+
FchEmis: d.fechaEmision,
|
|
83
|
+
IndServicio: d.indServicio || 3,
|
|
84
|
+
},
|
|
85
|
+
Emisor: d.emisor,
|
|
86
|
+
Receptor: {
|
|
87
|
+
RUTRecep: d.receptor?.RUTRecep ?? '66666666-6',
|
|
88
|
+
RznSocRecep: sanitizeSiiText(d.receptor?.RznSocRecep ?? 'Consumidor Final'),
|
|
89
|
+
DirRecep: sanitizeSiiText(d.receptor?.DirRecep ?? 'Sin Direccion'),
|
|
90
|
+
CmnaRecep: d.receptor?.CmnaRecep ?? 'Santiago',
|
|
91
|
+
},
|
|
92
|
+
Totales: totales,
|
|
93
|
+
},
|
|
94
|
+
Detalle: detalle,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
if (d.referencia) {
|
|
98
|
+
resultado.Referencia = {
|
|
99
|
+
NroLinRef: d.referencia.NroLinRef || 1,
|
|
100
|
+
CodRef: d.referencia.CodRef || d.referencia.codigo,
|
|
101
|
+
RazonRef: d.referencia.RazonRef || d.referencia.razon,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return resultado;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_procesarItems(items, esExenta) {
|
|
109
|
+
let mntBruto = 0;
|
|
110
|
+
let mntExento = 0;
|
|
111
|
+
|
|
112
|
+
const detalle = items.map((item, idx) => {
|
|
113
|
+
const qty = item.QtyItem || 1;
|
|
114
|
+
const prc = item.PrcItem;
|
|
115
|
+
const montoItem = Math.round(qty * prc);
|
|
116
|
+
|
|
117
|
+
if (esExenta || item.IndExe === 1) {
|
|
118
|
+
mntExento += montoItem;
|
|
119
|
+
} else {
|
|
120
|
+
mntBruto += montoItem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const det = {
|
|
124
|
+
NroLinDet: idx + 1,
|
|
125
|
+
...(esExenta || item.IndExe ? { IndExe: 1 } : {}),
|
|
126
|
+
NmbItem: sanitizeSiiText(item.NmbItem),
|
|
127
|
+
QtyItem: qty,
|
|
128
|
+
...(item.UnmdItem ? { UnmdItem: item.UnmdItem } : {}),
|
|
129
|
+
PrcItem: prc,
|
|
130
|
+
MontoItem: montoItem,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return det;
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return { detalle, mntBruto, mntExento };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
_calcularTotales(mntBruto, mntExento, esExenta) {
|
|
140
|
+
const mntNeto = esExenta ? 0 : Math.round(mntBruto / (1 + (TASA_IVA / 100)));
|
|
141
|
+
const iva = esExenta ? 0 : (mntBruto - mntNeto);
|
|
142
|
+
const mntTotal = mntNeto + iva + mntExento;
|
|
143
|
+
|
|
144
|
+
const totales = {};
|
|
145
|
+
if (mntNeto > 0) totales.MntNeto = mntNeto;
|
|
146
|
+
if (mntExento > 0) totales.MntExe = mntExento;
|
|
147
|
+
if (mntNeto > 0) totales.IVA = iva;
|
|
148
|
+
totales.MntTotal = mntTotal;
|
|
149
|
+
|
|
150
|
+
return totales;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ============================================
|
|
154
|
+
// GENERACIÓN XML
|
|
155
|
+
// ============================================
|
|
156
|
+
|
|
157
|
+
generarXML() {
|
|
158
|
+
const enc = this.datos.Encabezado;
|
|
159
|
+
const det = this.datos.Detalle;
|
|
160
|
+
const tipoDte = Number(enc.IdDoc.TipoDTE);
|
|
161
|
+
const esBoleta = TIPOS_BOLETA.includes(tipoDte);
|
|
162
|
+
|
|
163
|
+
this.id = `DTE_T${tipoDte}F${enc.IdDoc.Folio}`;
|
|
164
|
+
|
|
165
|
+
const idDoc = this._buildIdDoc(enc.IdDoc, esBoleta);
|
|
166
|
+
const emisor = this._buildEmisor(enc.Emisor, esBoleta);
|
|
167
|
+
const receptor = this._buildReceptor(enc.Receptor, esBoleta);
|
|
168
|
+
const detalle = this._buildDetalle(det);
|
|
169
|
+
|
|
170
|
+
this.documento = {
|
|
171
|
+
Documento: {
|
|
172
|
+
'@_ID': this.id,
|
|
173
|
+
Encabezado: { IdDoc: idDoc, Emisor: emisor, Receptor: receptor, Totales: enc.Totales },
|
|
174
|
+
Detalle: detalle,
|
|
175
|
+
...(this.datos.DscRcgGlobal ? { DscRcgGlobal: this.datos.DscRcgGlobal } : {}),
|
|
176
|
+
...(this.datos.Referencia ? { Referencia: this.datos.Referencia } : {}),
|
|
177
|
+
TED: null,
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return this;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
_buildIdDoc(idDoc, esBoleta) {
|
|
185
|
+
const result = {
|
|
186
|
+
TipoDTE: idDoc.TipoDTE,
|
|
187
|
+
Folio: idDoc.Folio,
|
|
188
|
+
FchEmis: idDoc.FchEmis,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
CAMPOS_IDDOC_OPCIONALES.forEach(campo => {
|
|
192
|
+
if (idDoc[campo] !== undefined && idDoc[campo] !== null) {
|
|
193
|
+
result[campo] = idDoc[campo];
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
if (esBoleta && !result.IndServicio) {
|
|
198
|
+
result.IndServicio = 3;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
_buildEmisor(emisor, esBoleta) {
|
|
205
|
+
return normalizeEmisor(emisor, esBoleta);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
_buildReceptor(receptor, esBoleta) {
|
|
209
|
+
return normalizeReceptor(receptor, esBoleta);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
_buildDetalle(det) {
|
|
213
|
+
return (Array.isArray(det) ? det : [det]).map(item => ({
|
|
214
|
+
...item,
|
|
215
|
+
NmbItem: sanitizeSiiText(item.NmbItem),
|
|
216
|
+
...(item.DscItem ? { DscItem: sanitizeSiiText(item.DscItem) } : {}),
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ============================================
|
|
221
|
+
// TIMBRAJE (TED)
|
|
222
|
+
// ============================================
|
|
223
|
+
|
|
224
|
+
timbrar(caf, timestampOverride) {
|
|
225
|
+
const enc = this.datos.Encabezado;
|
|
226
|
+
const det = this.datos.Detalle;
|
|
227
|
+
const primerItem = Array.isArray(det) ? det[0] : det;
|
|
228
|
+
const tipoDte = Number(enc.IdDoc.TipoDTE);
|
|
229
|
+
const esBoleta = TIPOS_BOLETA.includes(tipoDte);
|
|
230
|
+
|
|
231
|
+
this.tmstFirma = timestampOverride || new Date().toISOString().replace(/\.\d{3}Z$/, '');
|
|
232
|
+
|
|
233
|
+
const rznRecepRaw = sanitizeSiiText((enc.Receptor.RznSocRecep || '').substring(0, 40));
|
|
234
|
+
const it1Raw = sanitizeSiiText((primerItem.NmbItem || 'Producto').substring(0, 40));
|
|
235
|
+
const rznRecepXml = this._escapeXmlText(rznRecepRaw);
|
|
236
|
+
const it1Xml = this._escapeXmlText(it1Raw);
|
|
237
|
+
|
|
238
|
+
const dd = {
|
|
239
|
+
RE: enc.Emisor.RUTEmisor,
|
|
240
|
+
TD: enc.IdDoc.TipoDTE,
|
|
241
|
+
F: enc.IdDoc.Folio,
|
|
242
|
+
FE: enc.IdDoc.FchEmis,
|
|
243
|
+
RR: enc.Receptor.RUTRecep || (esBoleta ? '' : undefined),
|
|
244
|
+
MNT: enc.Totales.MntTotal,
|
|
245
|
+
CAF: caf.getCafXml(),
|
|
246
|
+
TSTED: this.tmstFirma,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const ddString = this._buildDDString(dd, rznRecepXml, it1Xml);
|
|
250
|
+
const firma = caf.sign(ddString);
|
|
251
|
+
|
|
252
|
+
this.tedXml = `<TED version="1.0"><DD><RE>${dd.RE}</RE><TD>${dd.TD}</TD><F>${dd.F}</F><FE>${dd.FE}</FE><RR>${dd.RR}</RR><RSR>${rznRecepXml}</RSR><MNT>${dd.MNT}</MNT><IT1>${it1Xml}</IT1>${dd.CAF}<TSTED>${dd.TSTED}</TSTED></DD><FRMT algoritmo="SHA1withRSA">${firma}</FRMT></TED>`;
|
|
253
|
+
|
|
254
|
+
this.documento.Documento.TED = '__TED_PLACEHOLDER__';
|
|
255
|
+
this.documento.Documento.TmstFirma = '__TMSTFIRMA_PLACEHOLDER__';
|
|
256
|
+
|
|
257
|
+
return this;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
_buildDDString(dd, rsrXml, it1Xml) {
|
|
261
|
+
return `<DD><RE>${dd.RE}</RE><TD>${dd.TD}</TD><F>${dd.F}</F><FE>${dd.FE}</FE><RR>${dd.RR}</RR><RSR>${rsrXml}</RSR><MNT>${dd.MNT}</MNT><IT1>${it1Xml}</IT1>${dd.CAF}<TSTED>${dd.TSTED}</TSTED></DD>`;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
_escapeXmlText(value) {
|
|
265
|
+
return String(value || '')
|
|
266
|
+
.replace(/&/g, '&')
|
|
267
|
+
.replace(/</g, '<')
|
|
268
|
+
.replace(/>/g, '>')
|
|
269
|
+
.replace(/"/g, '"')
|
|
270
|
+
.replace(/'/g, ''');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ============================================
|
|
274
|
+
// FIRMA ELECTRÓNICA
|
|
275
|
+
// ============================================
|
|
276
|
+
|
|
277
|
+
firmar(certificado) {
|
|
278
|
+
const dteXml = this._buildXmlSinFirma();
|
|
279
|
+
const doc = new DOMParser().parseFromString(dteXml, 'application/xml');
|
|
280
|
+
|
|
281
|
+
// Canonicalizar documento
|
|
282
|
+
const documentoC14N = this._c14nDocumento(doc);
|
|
283
|
+
const documentoC14NBytes = Buffer.from(documentoC14N, 'utf8');
|
|
284
|
+
const digestValue = crypto.createHash('sha1').update(documentoC14NBytes).digest('base64');
|
|
285
|
+
|
|
286
|
+
// Construir SignedInfo (usando c14n centralizado)
|
|
287
|
+
const signedInfoParaFirmar = buildSignedInfo(this.id, digestValue, { expandTags: true, includeXsi: true });
|
|
288
|
+
const signedInfoParaGuardar = buildSignedInfo(this.id, digestValue, { expandTags: false, includeXsi: false });
|
|
289
|
+
|
|
290
|
+
// Firmar
|
|
291
|
+
const sign = crypto.createSign('RSA-SHA1');
|
|
292
|
+
sign.update(Buffer.from(signedInfoParaFirmar, 'utf8'));
|
|
293
|
+
const signatureValue = sign.sign(certificado.getPrivateKeyPem(), 'base64');
|
|
294
|
+
const formattedSignature = signatureValue.match(/.{1,76}/g).join('\n');
|
|
295
|
+
|
|
296
|
+
// Construir Signature (usando c14n centralizado)
|
|
297
|
+
const signatureXml = buildSignature(signedInfoParaGuardar, formattedSignature, {
|
|
298
|
+
modulus: certificado.getModulus(),
|
|
299
|
+
exponent: certificado.getExponent(),
|
|
300
|
+
certificate: certificado.getCertificateBase64(),
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Insertar firma
|
|
304
|
+
const xmlFirmado = dteXml.replace('</Documento></DTE>', `</Documento>${signatureXml}</DTE>`);
|
|
305
|
+
this.xml = formatBase64InXml(xmlFirmado);
|
|
306
|
+
|
|
307
|
+
return this;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// NOTA: _buildSignedInfo y _buildSignature movidos a utils/c14n.js (v2.6.0)
|
|
311
|
+
|
|
312
|
+
_buildXmlSinFirma() {
|
|
313
|
+
const builder = new XMLBuilder({
|
|
314
|
+
ignoreAttributes: false,
|
|
315
|
+
attributeNamePrefix: '@_',
|
|
316
|
+
format: false,
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const dteConVersion = {
|
|
320
|
+
'@_xmlns': 'http://www.sii.cl/SiiDte',
|
|
321
|
+
'@_xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
|
322
|
+
'@_version': '1.0',
|
|
323
|
+
...this.documento
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
let dteXml = builder.build({ DTE: dteConVersion });
|
|
327
|
+
dteXml = dteXml.replace('<TED>__TED_PLACEHOLDER__</TED>', this.tedXml);
|
|
328
|
+
dteXml = dteXml.replace('<TmstFirma>__TMSTFIRMA_PLACEHOLDER__</TmstFirma>', `<TmstFirma>${this.tmstFirma}</TmstFirma>`);
|
|
329
|
+
|
|
330
|
+
return dteXml;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ============================================
|
|
334
|
+
// CANONICALIZACIÓN (C14N) - Usa utils/c14n.js
|
|
335
|
+
// ============================================
|
|
336
|
+
|
|
337
|
+
_c14nDocumento(doc) {
|
|
338
|
+
const documento = doc.getElementsByTagName('Documento')[0];
|
|
339
|
+
const dteRoot = doc.getElementsByTagName('DTE')[0];
|
|
340
|
+
if (!documento) return '';
|
|
341
|
+
|
|
342
|
+
const inheritedNs = new Map();
|
|
343
|
+
if (dteRoot) {
|
|
344
|
+
const defaultNs = dteRoot.getAttribute('xmlns');
|
|
345
|
+
if (defaultNs) inheritedNs.set('xmlns', defaultNs);
|
|
346
|
+
const xsiNs = dteRoot.getAttribute('xmlns:xsi');
|
|
347
|
+
if (xsiNs) inheritedNs.set('xmlns:xsi', xsiNs);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
let c14n = '<Documento';
|
|
351
|
+
if (inheritedNs.has('xmlns')) c14n += ` xmlns="${inheritedNs.get('xmlns')}"`;
|
|
352
|
+
if (inheritedNs.has('xmlns:xsi')) c14n += ` xmlns:xsi="${inheritedNs.get('xmlns:xsi')}"`;
|
|
353
|
+
const id = documento.getAttribute('ID');
|
|
354
|
+
if (id) c14n += ` ID="${id}"`;
|
|
355
|
+
c14n += '>';
|
|
356
|
+
|
|
357
|
+
for (let i = 0; i < documento.childNodes.length; i++) {
|
|
358
|
+
c14n += serializeNode(documento.childNodes[i], inheritedNs);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
c14n += '</Documento>';
|
|
362
|
+
return fixEntities(c14n);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// ============================================
|
|
366
|
+
// GETTERS
|
|
367
|
+
// ============================================
|
|
368
|
+
|
|
369
|
+
getXML() { return this.xml; }
|
|
370
|
+
getXMLSinFirma() { return this._buildXmlSinFirma(); }
|
|
371
|
+
getTED() { return this.tedXml; }
|
|
372
|
+
getId() { return this.id; }
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Obtiene el tipo de DTE
|
|
376
|
+
* @returns {number}
|
|
377
|
+
*/
|
|
378
|
+
getTipoDTE() {
|
|
379
|
+
return Number(this.datos?.Encabezado?.IdDoc?.TipoDTE);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Obtiene el folio del documento
|
|
384
|
+
* @returns {number}
|
|
385
|
+
*/
|
|
386
|
+
getFolio() {
|
|
387
|
+
return Number(this.datos?.Encabezado?.IdDoc?.Folio);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Obtiene el monto total del documento
|
|
392
|
+
* @returns {number}
|
|
393
|
+
*/
|
|
394
|
+
getMontoTotal() {
|
|
395
|
+
return Number(this.datos?.Encabezado?.Totales?.MntTotal || 0);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
module.exports = DTE;
|