@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,472 @@
|
|
|
1
|
+
// Copyright (c) 2026 Devlas SpA — https://devlas.cl
|
|
2
|
+
// Licencia MIT. Ver archivo LICENSE para mas detalles.
|
|
3
|
+
/**
|
|
4
|
+
* Set Factura de Compra
|
|
5
|
+
*
|
|
6
|
+
* Tipos DTE: 46 (Factura de Compra), 61 (NC), 56 (ND)
|
|
7
|
+
*
|
|
8
|
+
* Particularidades:
|
|
9
|
+
* - El emisor actúa como comprador (retiene IVA)
|
|
10
|
+
* - ImptoReten con TipoImp=15 (IVA Retenido Total)
|
|
11
|
+
* - MntTotal = MntNeto (IVA se cancela con retención)
|
|
12
|
+
* - NC/ND referencian la factura de compra original
|
|
13
|
+
*
|
|
14
|
+
* @module dte-sii/cert/SetCompra
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const SetBase = require('./SetBase');
|
|
18
|
+
const { SET_LABELS, SETS_DTE } = require('./types');
|
|
19
|
+
|
|
20
|
+
class SetCompra extends SetBase {
|
|
21
|
+
constructor(deps) {
|
|
22
|
+
super(deps);
|
|
23
|
+
|
|
24
|
+
this.key = 'compra';
|
|
25
|
+
this.label = SET_LABELS.compra;
|
|
26
|
+
this.tiposDte = SETS_DTE.compra; // [46, 56, 61]
|
|
27
|
+
|
|
28
|
+
// Registro de referencias entre documentos
|
|
29
|
+
this._docRefs = {};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @override
|
|
34
|
+
* Valida casos específicos del set compra
|
|
35
|
+
*/
|
|
36
|
+
_validarCasos(casos) {
|
|
37
|
+
super._validarCasos(casos);
|
|
38
|
+
|
|
39
|
+
if (!casos.casoFactura) {
|
|
40
|
+
throw new Error('SetCompra: casoFactura es requerido');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @override
|
|
46
|
+
* Calcula folios necesarios por tipo
|
|
47
|
+
*/
|
|
48
|
+
_calcularCantidadFolios(casos, tipoDte) {
|
|
49
|
+
if (casos.cafRequired?.[tipoDte]) {
|
|
50
|
+
return casos.cafRequired[tipoDte];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Set compra tiene 1 documento de cada tipo
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @override
|
|
59
|
+
* Genera DTEs del set factura compra
|
|
60
|
+
*
|
|
61
|
+
* @param {Object} casos - { casoFactura, casoNC, casoND, cafRequired }
|
|
62
|
+
* @param {Object} cafs - { 46: cafPath, 56: cafPath, 61: cafPath }
|
|
63
|
+
* @returns {Promise<DTE[]>}
|
|
64
|
+
*/
|
|
65
|
+
async generarDtes(casos, cafs) {
|
|
66
|
+
const dtes = [];
|
|
67
|
+
|
|
68
|
+
// 1. Generar factura de compra
|
|
69
|
+
this.logger.log(' 📄 Generando factura de compra...');
|
|
70
|
+
const dteFactura = await this._generarFacturaCompra(casos.casoFactura, cafs[46]);
|
|
71
|
+
dtes.push(dteFactura);
|
|
72
|
+
|
|
73
|
+
// 2. Generar nota de crédito
|
|
74
|
+
if (casos.casoNC) {
|
|
75
|
+
this.logger.log(' 📄 Generando nota de crédito...');
|
|
76
|
+
const dteNc = await this._generarNotaCredito(casos.casoNC, cafs[61]);
|
|
77
|
+
dtes.push(dteNc);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 3. Generar nota de débito
|
|
81
|
+
if (casos.casoND) {
|
|
82
|
+
this.logger.log(' 📄 Generando nota de débito...');
|
|
83
|
+
const dteNd = await this._generarNotaDebito(casos.casoND, cafs[56]);
|
|
84
|
+
dtes.push(dteNd);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return dtes;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ═══════════════════════════════════════════════════════════════
|
|
91
|
+
// Generadores de DTEs
|
|
92
|
+
// ═══════════════════════════════════════════════════════════════
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Genera factura de compra (tipo 46)
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
async _generarFacturaCompra(caso, cafPath) {
|
|
99
|
+
const { DTE, CAF, buildDetalleCompra, buildSetReferencia } = require('../index');
|
|
100
|
+
const fs = require('fs');
|
|
101
|
+
|
|
102
|
+
const cafXml = fs.readFileSync(cafPath, 'utf8');
|
|
103
|
+
const caf = new CAF(cafXml);
|
|
104
|
+
const folio = this._reservarFolio(caf, cafXml);
|
|
105
|
+
|
|
106
|
+
// Construir detalle con buildDetalleCompra (incluye CodImpAdic)
|
|
107
|
+
const items = this._normalizarItems(caso.items);
|
|
108
|
+
const detalle = buildDetalleCompra(items, { codImpAdic: 15 });
|
|
109
|
+
const totales = this._calcularTotalesFacturaCompra(detalle);
|
|
110
|
+
|
|
111
|
+
const fechaEmision = this._getFechaEmision();
|
|
112
|
+
const setReferencia = buildSetReferencia(caso.id, fechaEmision);
|
|
113
|
+
|
|
114
|
+
const dteDatos = {
|
|
115
|
+
Encabezado: {
|
|
116
|
+
IdDoc: {
|
|
117
|
+
TipoDTE: 46,
|
|
118
|
+
Folio: folio,
|
|
119
|
+
FchEmis: fechaEmision,
|
|
120
|
+
},
|
|
121
|
+
Emisor: this._buildEmisor(),
|
|
122
|
+
Receptor: this._buildEmisorAsReceptor(), // Emisor es también receptor en F. Compra
|
|
123
|
+
Totales: totales,
|
|
124
|
+
},
|
|
125
|
+
Detalle: detalle,
|
|
126
|
+
Referencia: [setReferencia],
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const dte = new DTE(dteDatos);
|
|
130
|
+
this._timbrarYFirmar(dte, caf);
|
|
131
|
+
|
|
132
|
+
// Guardar referencia para NC/ND
|
|
133
|
+
this._docRefs[caso.id] = {
|
|
134
|
+
tipoDte: 46,
|
|
135
|
+
folio,
|
|
136
|
+
fecha: fechaEmision,
|
|
137
|
+
detalle,
|
|
138
|
+
totales,
|
|
139
|
+
items,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
this.logger.log(` ✓ Factura Compra caso ${caso.id}: folio ${folio}`);
|
|
143
|
+
return dte;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Genera nota de crédito para factura de compra (tipo 61)
|
|
148
|
+
* @private
|
|
149
|
+
*/
|
|
150
|
+
async _generarNotaCredito(caso, cafPath) {
|
|
151
|
+
const { DTE, CAF, buildDetalleCompra, buildSetReferencia } = require('../index');
|
|
152
|
+
const fs = require('fs');
|
|
153
|
+
|
|
154
|
+
const cafXml = fs.readFileSync(cafPath, 'utf8');
|
|
155
|
+
const caf = new CAF(cafXml);
|
|
156
|
+
const folio = this._reservarFolio(caf, cafXml);
|
|
157
|
+
|
|
158
|
+
// Obtener documento referenciado
|
|
159
|
+
const docRef = this._docRefs[caso.referenciaCaso];
|
|
160
|
+
if (!docRef) {
|
|
161
|
+
throw new Error(`SetCompra: Documento referencia ${caso.referenciaCaso} no encontrado para NC ${caso.id}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Resolver items: NC puede tener cantidades parciales
|
|
165
|
+
const items = this._resolverItemsNC(caso, docRef);
|
|
166
|
+
const detalle = buildDetalleCompra(items, { codImpAdic: 15 });
|
|
167
|
+
const totales = this._calcularTotalesFacturaCompra(detalle);
|
|
168
|
+
|
|
169
|
+
const fechaEmision = this._getFechaEmision();
|
|
170
|
+
const setReferencia = buildSetReferencia(caso.id, fechaEmision);
|
|
171
|
+
|
|
172
|
+
// Referencia al documento original
|
|
173
|
+
const docReferencia = {
|
|
174
|
+
NroLinRef: 2,
|
|
175
|
+
TpoDocRef: docRef.tipoDte,
|
|
176
|
+
FolioRef: docRef.folio,
|
|
177
|
+
FchRef: docRef.fecha,
|
|
178
|
+
CodRef: caso.codRef,
|
|
179
|
+
RazonRef: caso.razonRef,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const dteDatos = {
|
|
183
|
+
Encabezado: {
|
|
184
|
+
IdDoc: {
|
|
185
|
+
TipoDTE: 61,
|
|
186
|
+
Folio: folio,
|
|
187
|
+
FchEmis: fechaEmision,
|
|
188
|
+
},
|
|
189
|
+
Emisor: this._buildEmisor(),
|
|
190
|
+
Receptor: this._buildEmisorAsReceptor(),
|
|
191
|
+
Totales: totales,
|
|
192
|
+
},
|
|
193
|
+
Detalle: detalle,
|
|
194
|
+
Referencia: [setReferencia, docReferencia],
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const dte = new DTE(dteDatos);
|
|
198
|
+
this._timbrarYFirmar(dte, caf);
|
|
199
|
+
|
|
200
|
+
// Guardar referencia para ND
|
|
201
|
+
this._docRefs[caso.id] = {
|
|
202
|
+
tipoDte: 61,
|
|
203
|
+
folio,
|
|
204
|
+
fecha: fechaEmision,
|
|
205
|
+
detalle,
|
|
206
|
+
totales,
|
|
207
|
+
items,
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
this.logger.log(` ✓ NC Compra caso ${caso.id}: folio ${folio} (ref: ${caso.referenciaCaso})`);
|
|
211
|
+
return dte;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Genera nota de débito para factura de compra (tipo 56)
|
|
216
|
+
* @private
|
|
217
|
+
*/
|
|
218
|
+
async _generarNotaDebito(caso, cafPath) {
|
|
219
|
+
const { DTE, CAF, buildDetalleCompra, buildSetReferencia } = require('../index');
|
|
220
|
+
const fs = require('fs');
|
|
221
|
+
|
|
222
|
+
const cafXml = fs.readFileSync(cafPath, 'utf8');
|
|
223
|
+
const caf = new CAF(cafXml);
|
|
224
|
+
const folio = this._reservarFolio(caf, cafXml);
|
|
225
|
+
|
|
226
|
+
// Obtener documento referenciado
|
|
227
|
+
const docRef = this._docRefs[caso.referenciaCaso];
|
|
228
|
+
if (!docRef) {
|
|
229
|
+
throw new Error(`SetCompra: Documento referencia ${caso.referenciaCaso} no encontrado para ND ${caso.id}`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ND generalmente tiene los mismos items que NC (anula NC)
|
|
233
|
+
const items = this._resolverItemsND(caso, docRef);
|
|
234
|
+
const detalle = buildDetalleCompra(items, { codImpAdic: 15 });
|
|
235
|
+
const totales = this._calcularTotalesFacturaCompra(detalle);
|
|
236
|
+
|
|
237
|
+
const fechaEmision = this._getFechaEmision();
|
|
238
|
+
const setReferencia = buildSetReferencia(caso.id, fechaEmision);
|
|
239
|
+
|
|
240
|
+
// Referencia al documento original
|
|
241
|
+
const docReferencia = {
|
|
242
|
+
NroLinRef: 2,
|
|
243
|
+
TpoDocRef: docRef.tipoDte,
|
|
244
|
+
FolioRef: docRef.folio,
|
|
245
|
+
FchRef: docRef.fecha,
|
|
246
|
+
CodRef: caso.codRef,
|
|
247
|
+
RazonRef: caso.razonRef,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const dteDatos = {
|
|
251
|
+
Encabezado: {
|
|
252
|
+
IdDoc: {
|
|
253
|
+
TipoDTE: 56,
|
|
254
|
+
Folio: folio,
|
|
255
|
+
FchEmis: fechaEmision,
|
|
256
|
+
},
|
|
257
|
+
Emisor: this._buildEmisor(),
|
|
258
|
+
Receptor: this._buildEmisorAsReceptor(),
|
|
259
|
+
Totales: totales,
|
|
260
|
+
},
|
|
261
|
+
Detalle: detalle,
|
|
262
|
+
Referencia: [setReferencia, docReferencia],
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const dte = new DTE(dteDatos);
|
|
266
|
+
this._timbrarYFirmar(dte, caf);
|
|
267
|
+
|
|
268
|
+
this.logger.log(` ✓ ND Compra caso ${caso.id}: folio ${folio} (ref: ${caso.referenciaCaso})`);
|
|
269
|
+
return dte;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ═══════════════════════════════════════════════════════════════
|
|
273
|
+
// Helpers de cálculo
|
|
274
|
+
// ═══════════════════════════════════════════════════════════════
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Calcula totales para Factura de Compra con IVA Retenido Total
|
|
278
|
+
* @private
|
|
279
|
+
*/
|
|
280
|
+
_calcularTotalesFacturaCompra(detalle) {
|
|
281
|
+
let mntBruto = 0;
|
|
282
|
+
let mntExento = 0;
|
|
283
|
+
|
|
284
|
+
for (const det of detalle) {
|
|
285
|
+
if (det.IndExe === 1) {
|
|
286
|
+
mntExento += det.MontoItem || 0;
|
|
287
|
+
} else {
|
|
288
|
+
mntBruto += det.MontoItem || 0;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const tasaIva = 19;
|
|
293
|
+
// Precios son netos en certificación
|
|
294
|
+
const mntNeto = mntBruto;
|
|
295
|
+
const iva = mntNeto > 0 ? Math.round(mntNeto * (tasaIva / 100)) : 0;
|
|
296
|
+
|
|
297
|
+
// MntTotal = MntNeto (IVA se cancela con retención)
|
|
298
|
+
const mntTotal = mntNeto + mntExento;
|
|
299
|
+
|
|
300
|
+
// Orden según schema: MntNeto, MntExe, TasaIVA, IVA, ImptoReten, MntTotal
|
|
301
|
+
const totales = {};
|
|
302
|
+
if (mntNeto > 0) totales.MntNeto = mntNeto;
|
|
303
|
+
if (mntExento > 0) totales.MntExe = mntExento;
|
|
304
|
+
if (mntNeto > 0) totales.TasaIVA = tasaIva;
|
|
305
|
+
if (mntNeto > 0) totales.IVA = iva;
|
|
306
|
+
|
|
307
|
+
// ImptoReten con TipoImp=15 = IVA Retenido Total
|
|
308
|
+
if (iva > 0) {
|
|
309
|
+
totales.ImptoReten = [{
|
|
310
|
+
TipoImp: 15,
|
|
311
|
+
TasaImp: tasaIva,
|
|
312
|
+
MontoImp: iva,
|
|
313
|
+
}];
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
totales.MntTotal = mntTotal;
|
|
317
|
+
|
|
318
|
+
return totales;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// ═══════════════════════════════════════════════════════════════
|
|
322
|
+
// Helpers de items
|
|
323
|
+
// ═══════════════════════════════════════════════════════════════
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Normaliza items
|
|
327
|
+
* @private
|
|
328
|
+
*/
|
|
329
|
+
_normalizarItems(items) {
|
|
330
|
+
return (items || []).map(item => ({
|
|
331
|
+
nombre: item.nombre,
|
|
332
|
+
cantidad: item.cantidad || 1,
|
|
333
|
+
precio: item.precio || 0,
|
|
334
|
+
unidad: item.unidad || 'UN',
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Resuelve items para NC
|
|
340
|
+
* Si NC tiene items con cantidad pero sin precio, usar precio del original
|
|
341
|
+
* @private
|
|
342
|
+
*/
|
|
343
|
+
_resolverItemsNC(caso, docRef) {
|
|
344
|
+
const ncItems = caso.items || [];
|
|
345
|
+
|
|
346
|
+
return ncItems.map(ncItem => {
|
|
347
|
+
// Buscar item original por nombre para obtener precio
|
|
348
|
+
const originalItem = (docRef.items || []).find(
|
|
349
|
+
i => i.nombre === ncItem.nombre
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
return {
|
|
353
|
+
nombre: ncItem.nombre,
|
|
354
|
+
cantidad: ncItem.cantidad || 1,
|
|
355
|
+
precio: ncItem.precio || originalItem?.precio || 0,
|
|
356
|
+
unidad: ncItem.unidad || originalItem?.unidad || 'UN',
|
|
357
|
+
};
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Resuelve items para ND
|
|
363
|
+
* @private
|
|
364
|
+
*/
|
|
365
|
+
_resolverItemsND(caso, docRef) {
|
|
366
|
+
const ndItems = caso.items || [];
|
|
367
|
+
|
|
368
|
+
// Si ND tiene items propios
|
|
369
|
+
if (ndItems.length) {
|
|
370
|
+
return ndItems.map(ndItem => {
|
|
371
|
+
// Buscar item original por nombre para obtener precio
|
|
372
|
+
const originalItem = (docRef.items || []).find(
|
|
373
|
+
i => i.nombre === ndItem.nombre
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
nombre: ndItem.nombre,
|
|
378
|
+
cantidad: ndItem.cantidad || 1,
|
|
379
|
+
precio: ndItem.precio || originalItem?.precio || 0,
|
|
380
|
+
unidad: ndItem.unidad || originalItem?.unidad || 'UN',
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Si no, usar items del documento referenciado
|
|
386
|
+
return docRef.items || [];
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// ═══════════════════════════════════════════════════════════════
|
|
390
|
+
// Helpers comunes
|
|
391
|
+
// ═══════════════════════════════════════════════════════════════
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Reserva el siguiente folio disponible
|
|
395
|
+
* @private
|
|
396
|
+
*/
|
|
397
|
+
_reservarFolio(caf, cafXml) {
|
|
398
|
+
const cafFingerprint = this.folioHelper.createCafFingerprint(cafXml);
|
|
399
|
+
const folio = this.folioHelper.reserveNextFolio({
|
|
400
|
+
rutEmisor: this.config.emisor.rut,
|
|
401
|
+
tipoDte: caf.getTipoDTE(),
|
|
402
|
+
folioDesde: caf.getFolioDesde(),
|
|
403
|
+
folioHasta: caf.getFolioHasta(),
|
|
404
|
+
ambiente: this.config.ambiente || 'certificacion',
|
|
405
|
+
cafFingerprint,
|
|
406
|
+
});
|
|
407
|
+
return folio;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Obtiene la fecha de emisión
|
|
412
|
+
* @private
|
|
413
|
+
*/
|
|
414
|
+
_getFechaEmision() {
|
|
415
|
+
if (this._fechaEmision) return this._fechaEmision;
|
|
416
|
+
const now = new Date();
|
|
417
|
+
this._fechaEmision = now.toISOString().split('T')[0];
|
|
418
|
+
return this._fechaEmision;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Construye datos del emisor
|
|
423
|
+
* @private
|
|
424
|
+
*/
|
|
425
|
+
_buildEmisor() {
|
|
426
|
+
const e = this.config.emisor;
|
|
427
|
+
return {
|
|
428
|
+
RUTEmisor: e.rut,
|
|
429
|
+
RznSoc: e.razon_social,
|
|
430
|
+
GiroEmis: e.giro,
|
|
431
|
+
Acteco: e.acteco,
|
|
432
|
+
DirOrigen: e.direccion,
|
|
433
|
+
CmnaOrigen: e.comuna,
|
|
434
|
+
CiudadOrigen: e.ciudad || e.comuna || 'Santiago',
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Construye datos del emisor como receptor (Factura de Compra)
|
|
440
|
+
* @private
|
|
441
|
+
*/
|
|
442
|
+
_buildEmisorAsReceptor() {
|
|
443
|
+
const e = this.config.emisor;
|
|
444
|
+
return {
|
|
445
|
+
RUTRecep: e.rut,
|
|
446
|
+
RznSocRecep: e.razon_social,
|
|
447
|
+
GiroRecep: e.giro,
|
|
448
|
+
DirRecep: e.direccion,
|
|
449
|
+
CmnaRecep: e.comuna,
|
|
450
|
+
CiudadRecep: e.ciudad || e.comuna || 'Santiago',
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Timbra y firma el DTE
|
|
456
|
+
* @private
|
|
457
|
+
*/
|
|
458
|
+
_timbrarYFirmar(dte, caf) {
|
|
459
|
+
const { Certificado } = require('../index');
|
|
460
|
+
const fs = require('fs');
|
|
461
|
+
|
|
462
|
+
const pfxBuffer = fs.readFileSync(this.config.certificado.path);
|
|
463
|
+
const cert = new Certificado(pfxBuffer, this.config.certificado.password);
|
|
464
|
+
|
|
465
|
+
const timestamp = new Date().toISOString().replace('Z', '');
|
|
466
|
+
|
|
467
|
+
dte.generarXML().timbrar(caf, timestamp);
|
|
468
|
+
dte.firmar(cert);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
module.exports = SetCompra;
|