UNPKG

facturacionelectronicapy-xmlgen

Version:

API Node JS para generar el archivo XML del Documento electrónico exigido por SIFEN en base a JSON

789 lines (786 loc) 93.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const xml2js = __importStar(require("xml2js")); const StringUtil_service_1 = __importDefault(require("./StringUtil.service")); const FechaUtil_service_1 = __importDefault(require("./FechaUtil.service")); const Constante_service_1 = __importDefault(require("./Constante.service")); const jsonDteItem_service_1 = __importDefault(require("./jsonDteItem.service")); const jsonDteAlgoritmos_service_1 = __importDefault(require("./jsonDteAlgoritmos.service")); const jsonDteComplementario_service_1 = __importDefault(require("./jsonDteComplementario.service")); const jsonDteTransporte_service_1 = __importDefault(require("./jsonDteTransporte.service")); const jsonDteTotales_service_1 = __importDefault(require("./jsonDteTotales.service")); const jsonDteComplementariosComerciales_service_1 = __importDefault(require("./jsonDteComplementariosComerciales.service")); const jsonDteIdentificacionDocumento_service_1 = __importDefault(require("./jsonDteIdentificacionDocumento.service")); class JSonDteMainService { constructor() { this.codigoSeguridad = null; this.codigoControl = null; this.json = {}; } generateXML(params, data) { return new Promise((resolve, reject) => { try { resolve(this.generateXMLService(params, data)); } catch (error) { reject(error); } }); } /** * Metodo principal de generacion de XML * @param params * @param data * @returns */ generateXMLService(params, data) { this.validateValues(data); this.addDefaultValues(data); this.json = {}; this.generateCodigoSeguridad(params, data); //Primero genera el codigo de seguridad aleatorio único this.generateCodigoControl(params, data); //Luego genera el código de Control this.generateRte(params); this.json['rDE']['DE'] = this.generateDe(params, data); //--- this.generateDatosOperacion(params, data); this.generateDatosTimbrado(params, data); this.generateDatosGenerales(params, data); //--- this.generateDatosEspecificosPorTipoDE(params, data); this.generateDatosCondicionOperacionDE(params, data); //['gDtipDE']=E001 this.json['rDE']['DE']['gDtipDE']['gCamItem'] = jsonDteItem_service_1.default.generateDatosItemsOperacion(params, data); this.json['rDE']['DE']['gDtipDE']['gCamEsp'] = jsonDteComplementario_service_1.default.generateDatosComplementariosComercialesDeUsoEspecificos(params, data); if (data['tipoDocumento'] == 1 || data['tipoDocumento'] == 7) { //1 Opcional, 7 Obligatorio this.json['rDE']['DE']['gDtipDE']['gTransp'] = jsonDteTransporte_service_1.default.generateDatosTransporte(params, data); } if (data['tipoDocumento'] != 7) { const items = this.json['rDE']['DE']['gDtipDE']['gCamItem']; this.json['rDE']['DE']['gTotSub'] = jsonDteTotales_service_1.default.generateDatosTotales(params, data, items); } if (data['complementarios']) { this.json['rDE']['DE']['gCamGen'] = jsonDteComplementariosComerciales_service_1.default.generateDatosComercialesUsoGeneral(params, data); } if (data['tipoDocumento'] == 1 || data['tipoDocumento'] == 4 || data['tipoDocumento'] == 5 || data['tipoDocumento'] == 6 || data['tipoDocumento'] == 7) { //this.json['rDE']['DE']['gDtipDE']['gCamDEAsoc'] = jsonDteIdentificacionDocumento.generateDatosDocumentoAsociado(params, data); if (data['documentoAsociado']) { this.json['rDE']['DE']['gCamDEAsoc'] = jsonDteIdentificacionDocumento_service_1.default.generateDatosDocumentoAsociado(params, data); } } var builder = new xml2js.Builder({ xmldec: { version: '1.0', encoding: 'UTF-8', standalone: false } }); var xml = builder.buildObject(this.json); /* validator.validateXML(xml, __dirname + '\\xsd\\siRecepDE_v150.xsd', function(err, result) { //validator.validateXML(xml.split('\n').slice(1).join('\n'), __dirname + '\\xsd\\siRecepDE_v150.xsd', function(err, result) { if (err) { throw err; } }); */ return this.normalizeXML(xml); } generateCodigoSeguridad(params, data) { //this.codigoSeguridad = oThis.generateCodigoSeguridadAleatorio(params, data); this.codigoSeguridad = StringUtil_service_1.default.leftZero(data.codigoSeguridadAleatorio, 9); } /** * Genera el CDC para la Factura * Corresponde al Id del DE * * @param params * @param data */ generateCodigoControl(params, data) { this.codigoControl = jsonDteAlgoritmos_service_1.default.generateCodigoControl(params, data, this.codigoSeguridad); } /** * Valida los datos ingresados en el data del req.body * @param data */ validateValues(data) { } /** * Añade algunos valores por defecto al JSON de entrada, valido para * todas las operaciones * @param data */ addDefaultValues(data) { if (Constante_service_1.default.tiposDocumentos.filter(um => um.codigo === data["tipoDocumento"]).length == 0) { throw new Error("Tipo de Documento '" + data["tipoDocumento"]) + "' en data.tipoDocumento no válido. Valores: " + Constante_service_1.default.tiposDocumentos.map(a => a.codigo + '-' + a.descripcion); } data["tipoDocumentoDescripcion"] = Constante_service_1.default.tiposDocumentos.filter(td => td.codigo == data["tipoDocumento"])[0]['descripcion']; } generateRte(params) { this.json = { rDE: { $: { 'xmlns': 'http://ekuatia.set.gov.py/sifen/xsd', 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation': 'http://ekuatia.set.gov.py/sifen/xsd siRecepDE_v150.xsd' }, 'dVerFor': params.version } }; } generateDe(params, data) { if (params['ruc'].indexOf('-') == -1) { throw new Error("RUC debe contener dígito verificador en params.ruc"); } const rucEmisor = params['ruc'].split('-')[0]; const dvEmisor = params['ruc'].split('-')[1]; const id = this.codigoControl; //const digitoVerificador = jsonDteAlgoritmos.calcularDigitoVerificador(rucEmisor, 11 ); if (!(params.fechaFirmaDigital && params.fechaFirmaDigital.length >= 10)) { // throw new Error("Debe proveer la fecha de la firma digital en params.fechaFirmaDigital"); } const fechaFirmaDigital = new Date(params.fechaFirmaDigital); let digitoVerificadorString = this.codigoControl + ""; const jsonResult = { $: { 'Id': id }, dDVId: digitoVerificadorString.substring(digitoVerificadorString.length - 1, digitoVerificadorString.length), //dFecFirma : fechaUtilService.convertToJSONFormat(fechaFirmaDigital), //Fecha de la Firma Digital dFecFirma: FechaUtil_service_1.default.convertToJSONFormat(new Date()), dSisFact: 1 }; return jsonResult; } /** * Datos inerentes a la operacion * <gOpeDE> <iTipEmi>1</iTipEmi> <dDesTipEmi>Normal</dDesTipEmi> <dCodSeg>000000023</dCodSeg> <dInfoEmi>1</dInfoEmi> <dInfoFisc>Información de interés del Fisco respecto al DE</dInfoFisc> </gOpeDE> * @param params * @param data * @param options */ generateDatosOperacion(params, data) { if (params['ruc'].indexOf('-') == -1) { throw new Error("RUC debe contener dígito verificador en params.ruc"); } const rucEmisor = params['ruc'].split('-')[0]; const dvEmisor = params['ruc'].split('-')[1]; const id = jsonDteAlgoritmos_service_1.default.generateCodigoControl(params, data, this.codigoSeguridad); const digitoVerificador = jsonDteAlgoritmos_service_1.default.calcularDigitoVerificador(rucEmisor, 11); const codigoSeguridadAleatorio = this.codigoSeguridad; if (Constante_service_1.default.tiposEmisiones.filter(um => um.codigo === data["tipoEmision"]).length == 0) { throw new Error("Tipo de Emisión '" + data["tipoEmision"] + "' en data.tipoEmision no válido. Valores: " + Constante_service_1.default.tiposEmisiones.map(a => a.codigo + '-' + a.descripcion)); } this.json['rDE']['DE']['gOpeDE'] = { iTipEmi: data['tipoEmision'], dDesTipEmi: Constante_service_1.default.tiposEmisiones.filter(td => td.codigo == data["tipoEmision"])[0]['descripcion'], dCodSeg: codigoSeguridadAleatorio, dInfoEmi: data['observacion'], dInfoFisc: data['descripcion'], }; //Validar aqui "dInfoFisc" if (data['tipoDocumento'] == 7) { //Nota de Remision if (!(data['descripcion'] && data['descripcion'] != "")) { throw new Error("Debe informar la Descripción para el Documento Electrónico"); } } } /** * Genera los datos del timbrado * * <gTimb> <iTiDE>1</iTiDE> <dDesTiDE>Factura electrónica</dDesTiDE> <dNumTim>12345678</dNumTim> <dEst>001</dEst> <dPunExp>001</dPunExp> <dNumDoc>1000050</dNumDoc> <dSerieNum>AB</dSerieNum> <dFeIniT>2019-08-13</dFeIniT> </gTimb> * @param params * @param data * @param options */ generateDatosTimbrado(params, data) { this.json['rDE']['DE']['gTimb'] = { iTiDE: data['tipoDocumento'], dDesTiDE: data['tipoDocumentoDescripcion'], dNumTim: params['timbradoNumero'], dEst: StringUtil_service_1.default.leftZero(data['establecimiento'], 3), dPunExp: StringUtil_service_1.default.leftZero(data['punto'], 3), dNumDoc: StringUtil_service_1.default.leftZero(data['numero'], 7), //dSerieNum : null, dFeIniT: params['timbradoFecha'].substring(0, 10) }; if (data['numeroSerie']) { this.json['rDE']['DE']['gTimb']['dSerieNum'] = data['numeroSerie']; } } /** * Genera los campos generales, divide las actividades en diferentes metodos * * <gDatGralOpe> <dFeEmiDE>2020-05-07T15:03:57</dFeEmiDE> </gDatGralOpe> * * @param params * @param data * @param options */ generateDatosGenerales(params, data) { this.json['rDE']['DE']['gDatGralOpe'] = { dFeEmiDE: data['fecha'] }; this.generateDatosGeneralesInherentesOperacion(params, data); this.generateDatosGeneralesEmisorDE(params, data); this.generateDatosGeneralesResponsableGeneracionDE(params, data); this.generateDatosGeneralesReceptorDE(params, data); } /** * D1. Campos inherentes a la operación comercial (D010-D099) * Pertenece al grupo de datos generales * * <gOpeCom> <iTipTra>1</iTipTra> <dDesTipTra>Venta de mercadería</dDesTipTra> <iTImp>1</iTImp> <dDesTImp>IVA</dDesTImp> <cMoneOpe>PYG</cMoneOpe> <dDesMoneOpe>Guarani</dDesMoneOpe> </gOpeCom> * @param params * @param data * @param options */ generateDatosGeneralesInherentesOperacion(params, data) { if (data['tipoDocumento'] == 7) { //C002 return; //No informa si el tipo de documento es 7 } if (Constante_service_1.default.tiposImpuestos.filter(um => um.codigo === data["tipoImpuesto"]).length == 0) { throw new Error("Tipo de Impuesto '" + data["tipoImpuesto"]) + "' en data.tipoImpuesto no válido. Valores: " + Constante_service_1.default.tiposImpuestos.map(a => a.codigo + '-' + a.descripcion); } if (Constante_service_1.default.monedas.filter(um => um.codigo === data["moneda"]).length == 0) { throw new Error("Moneda '" + data["moneda"]) + "' en data.moneda no válido. Valores: " + Constante_service_1.default.monedas.map(a => a.codigo + '-' + a.descripcion); } if (data["condicionAnticipo"]) { if (Constante_service_1.default.globalPorItem.filter(um => um.codigo === data["condicionAnticipo"]).length == 0) { throw new Error("Condición de Anticipo '" + data["condicionAnticipo"]) + "' en data.condicionAnticipo no válido. Valores: " + Constante_service_1.default.globalPorItem.map(a => a.codigo + '-Anticipo ' + a.descripcion); } } if (Constante_service_1.default.tiposTransacciones.filter(um => um.codigo === data["tipoTransaccion"]).length == 0) { throw new Error("Tipo de Transacción '" + data["tipoTransaccion"]) + "' en data.tipoTransaccion no válido. Valores: " + Constante_service_1.default.tiposTransacciones.map(a => a.codigo + '-' + a.descripcion); } this.json['rDE']['DE']['gDatGralOpe']['gOpeCom'] = { iTipTra: null, dDesTipTra: null, iTImp: data['tipoImpuesto'], dDesTImp: Constante_service_1.default.tiposImpuestos.filter(ti => ti.codigo == data['tipoImpuesto'])[0]['descripcion'], cMoneOpe: data['moneda'], dDesMoneOpe: Constante_service_1.default.monedas.filter(m => m.codigo == data['moneda'])[0]['descripcion'], }; if (data['tipoDocumento'] == 1 || data['tipoDocumento'] == 4) { //Obligatorio informar iTipTra D011 this.json['rDE']['DE']['gDatGralOpe']['gOpeCom']['iTipTra'] = data['tipoTransaccion']; this.json['rDE']['DE']['gDatGralOpe']['gOpeCom']['dDesTipTra'] = Constante_service_1.default.tiposTransacciones.filter(tt => tt.codigo == data['tipoTransaccion'])[0]['descripcion']; } if (data['moneda'] != 'PYG') { if (!data['condicionTipoCambio']) { throw new Error("Debe informar el tipo de Cambio en data.condicionTipoCambio"); } //Obligatorio informar dCondTiCam D017 this.json['rDE']['DE']['gDatGralOpe']['gOpeCom']['dCondTiCam'] = data['condicionTipoCambio']; } if (data['cambio'] == 1 && data['moneda'] != 'PYG') { if (!(data['cambio'] && data['cambio'] > 0)) { throw new Error("Debe informar el valor del Cambio en data.cambio"); } //Obligatorio informar dCondTiCam D018 this.json['rDE']['DE']['gDatGralOpe']['gOpeCom']['dTiCam'] = data['cambio']; } if (data['condicionAnticipo']) { this.json['rDE']['DE']['gDatGralOpe']['gOpeCom']['iCondAnt'] = data['condicionAnticipo']; this.json['rDE']['DE']['gDatGralOpe']['gOpeCom']['dDesCondAnt'] = "Anticipo " + Constante_service_1.default.globalPorItem.filter(ca => ca.codigo == data['condicionAnticipo'])[0]['descripcion']; } } /** * D2. Campos que identifican al emisor del Documento Electrónico DE (D100-D129) * Pertenece al grupo de datos generales * * @param params * @param data * @param options */ generateDatosGeneralesEmisorDE(params, data) { if (!(params && params.establecimientos)) { throw new Error("Debe proveer un Array con la información de los establecimientos en params"); } //Validar si el establecimiento viene en params let establecimiento = StringUtil_service_1.default.leftZero(data['establecimiento'], 3); let punto = StringUtil_service_1.default.leftZero(data['punto'], 3); if (params.establecimientos.filter((um) => um.codigo === establecimiento).length == 0) { throw new Error("Establecimiento '" + establecimiento + "' no encontrado en params.establecimientos*.codigo. Valores: " + params.establecimientos.map((a) => a.codigo + '-' + a.denominacion)); } if (params['ruc'].indexOf('-') == -1) { throw new Error("RUC debe contener dígito verificador en params.ruc"); } this.json['rDE']['DE']['gDatGralOpe']['gEmis'] = { dRucEm: params['ruc'].split('-')[0], dDVEmi: params['ruc'].split('-')[1], iTipCont: params['tipoContribuyente'], cTipReg: params['tipoRegimen'], dNomEmi: params['razonSocial'], dNomFanEmi: params['nombreFantasia'], dDirEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['direccion'], dNumCas: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['numeroCasa'], dCompDir1: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['complementoDireccion1'], dCompDir2: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['complementoDireccion2'], cDepEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['departamento'], dDesDepEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['departamentoDescripcion'], cDisEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['distrito'], dDesDisEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['distritoDescripcion'], cCiuEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['ciudad'], dDesCiuEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['ciudadDescripcion'], dTelEmi: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['telefono'], dEmailE: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['email'], dDenSuc: params["establecimientos"].filter((e) => e.codigo === establecimiento)[0]['denominacion'], }; if (params["actividadesEconomicas"] && params["actividadesEconomicas"].length > 0) { this.json['rDE']['DE']['gDatGralOpe']['gEmis']['gActEco'] = []; for (let i = 0; i < params["actividadesEconomicas"].length; i++) { const actividadEconomica = params["actividadesEconomicas"][i]; const gActEco = { cActEco: actividadEconomica.codigo, dDesActEco: actividadEconomica.descripcion }; this.json['rDE']['DE']['gDatGralOpe']['gEmis']['gActEco'].push(gActEco); } } else { throw new Error("Debe proveer el array de actividades económicas en params.actividadesEconomicas"); } } /** * Datos generales del responsable de generacion del DE * * @param params * @param data * @param options */ generateDatosGeneralesResponsableGeneracionDE(params, data) { this.json['rDE']['DE']['gDatGralOpe']['gEmis']['gRespDE'] = { iTipIDRespDE: data['usuario']['documentoTipo'], dDTipIDRespDE: Constante_service_1.default.tiposDocumentosIdentidades.filter(td => td.codigo === data['usuario']['documentoTipo'])[0]["descripcion"], dNumIDRespDE: data['usuario']['documentoNumero'], dNomRespDE: data['usuario']['nombre'], dCarRespDE: data['usuario']['cargo'] }; } /** * Datos generales del receptor del documento electrónico * Pertenece al grupo de datos generales * * <gDatRec> <iNatRec>1</iNatRec> <iTiOpe>1</iTiOpe> <cPaisRec>PRY</cPaisRec> <dDesPaisRe>Paraguay</dDesPaisRe> <iTiContRec>2</iTiContRec> <dRucRec>00000002</dRucRec> <dDVRec>7</dDVRec> <dNomRec>RECEPTOR DEL DOCUMENTO</dNomRec> <dDirRec>CALLE 1 ENTRE CALLE 2 Y CALLE 3</dDirRec> <dNumCasRec>123</dNumCasRec> <cDepRec>1</cDepRec> <dDesDepRec>CAPITAL</dDesDepRec> <cDisRec>1</cDisRec> <dDesDisRec>ASUNCION (DISTRITO)</dDesDisRec> <cCiuRec>1</cCiuRec> <dDesCiuRec>ASUNCION (DISTRITO)</dDesCiuRec> <dTelRec>012123456</dTelRec> <dCodCliente>AAA</dCodCliente> </gDatRec> * * @param params * @param data * @param options */ generateDatosGeneralesReceptorDE(params, data) { if (!data['cliente']['contribuyente'] && data['cliente']['tipoOperacion'] != 4) { if (Constante_service_1.default.tiposDocumentosReceptor.filter((um) => um.codigo === data['cliente']['documentoTipo']).length == 0) { throw new Error("Tipo de Documento '" + data['cliente']['documentoTipo'] + "' del Cliente en data.cliente.documentoTipo no encontrado. Valores: " + Constante_service_1.default.tiposDocumentosReceptor.map((a) => a.codigo + '-' + a.descripcion)); } } if (data['cliente']['ruc'].indexOf('-') == -1) { throw new Error("RUC debe contener dígito verificador en data.cliente.ruc"); } this.json['rDE']['DE']['gDatGralOpe']['gDatRec'] = { iNatRec: data['cliente']['contribuyente'] ? 1 : 2, iTiOpe: data['cliente']['tipoOperacion'], cPaisRec: data['cliente']['pais'], dDesPaisRe: data['cliente']['paisDescripcion'], iTiContRec: data['cliente']['contribuyente'] ? data['cliente']['tipoContribuyente'] : null, dRucRec: data['cliente']['contribuyente'] ? data['cliente']['ruc'].split('-')[0] : null, dDVRec: data['cliente']['contribuyente'] ? data['cliente']['ruc'].split('-')[1] : null, //iTipIDRec : (!data['cliente']['contribuyente'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['documentoTipo'] : null, //dDTipIDRec : (!data['cliente']['contribuyente'] && data['cliente']['tipoOperacion'] != 4) ? constanteService.tiposDocumentosReceptor.filter(tdr => { tdr.codigo === data['cliente']['documentoTipo']})[0]["descripcion"] : null, //dNumIDRec : null, //Sera Sobreescito D210 dNomRec: (data['cliente']['documentoTipo'] === 5) ? "Sin Nombre" : data['cliente']['razonSocial'], dNomFanRec: (data['cliente']['documentoTipo'] === 5) ? null : data['cliente']['nombreFantasia'], //dDirRec : (data['tipoDocumento'] === 7 || data['cliente']['tipoOperacion'] === 4) ? data['cliente']['direccion'] : null, dNumCasRec: data['cliente']['direccion'] ? data['cliente']['numeroCasa'] : null, cDepRec: (data['cliente']['direccion'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['departamento'] : null, dDesDepRec: (data['cliente']['direccion'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['departamentoDescripcion'] : null, cDisRec: (data['cliente']['direccion'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['distrito'] : null, dDesDisRec: (data['cliente']['direccion'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['distritoDescripcion'] : null, cCiuRec: (data['cliente']['direccion'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['ciudad'] : null, dDesCiuRec: (data['cliente']['direccion'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['ciudadDescripcion'] : null, }; if (!data['cliente']['contribuyente'] && data['cliente']['tipoOperacion']) { //Obligatorio completar D210 if (data['cliente']['tipoOperacion'] != 4 && !data['cliente']['documentoNumero']) { throw new Error("Debe informar el número de documento en data.cliente.documentoNumero"); } //iTipIDRec : (!data['cliente']['contribuyente'] && data['cliente']['tipoOperacion'] != 4) ? data['cliente']['documentoTipo'] : null, //dDTipIDRec : (!data['cliente']['contribuyente'] && data['cliente']['tipoOperacion'] != 4) ? constanteService.tiposDocumentosReceptor.filter(tdr => { tdr.codigo === data['cliente']['documentoTipo']})[0]["descripcion"] : null, //dNumIDRec : null, //Sera Sobreescito D210 if (!data['cliente']['contribuyente'] && data['cliente']['tipoOperacion'] != 4) { this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['iTipIDRec'] = data['cliente']['documentoTipo']; this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dDTipIDRec'] = Constante_service_1.default.tiposDocumentosReceptor.filter(tdr => { tdr.codigo === data['cliente']['documentoTipo']; })[0]["descripcion"]; this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dNumIDRec'] = data['cliente']['documentoNumero']; } if (data['cliente']['documentoTipo'] = 5) { //Si es innominado completar con cero this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dNumIDRec'] = "0"; } } if (data['tipoDocumento'] === 7 || data['cliente']['tipoOperacion'] === 4) { if (data['cliente']['direccion']) { this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dDirRec'] = data['cliente']['direccion']; } } //Asignar null a departamento, distrito y ciudad si tipoOperacion = 4 if (data['cliente']['tipoOperacion'] === 4) { this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['cDepRec'] = null; this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dDesDepRec'] = null; this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['cDisRec'] = null; this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dDesDisRec'] = null; this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['cCiuRec'] = null; this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dDesCiuRec'] = null; } if (data['cliente']['telefono'] && data['cliente']['telefono'].lenght >= 6) { dTelRec: data['cliente']['telefono']; } if (data['cliente']['celular'] && data['cliente']['telefono'].lenght >= 10) { dCelRec: data['cliente']['celular']; } if (data['cliente']['email']) { dEmailRec: data['cliente']['email']; } if (data['cliente']['codigo']) { this.json['rDE']['DE']['gDatGralOpe']['gDatRec']['dCodCliente'] = data['cliente']['codigo']; } } /** * Campos que seran especificos de acuerdo a cada tipo de documento electronico * Se dividiran en diferentes métodos por cada tipo de factura. * * @param params * @param data * @param options */ generateDatosEspecificosPorTipoDE(params, data) { this.json['rDE']['DE']['gDtipDE'] = {}; if (data["tipoDocumento"] === 1) { this.generateDatosEspecificosPorTipoDE_FacturaElectronica(params, data); } if (data["tipoDocumento"] === 4) { this.generateDatosEspecificosPorTipoDE_Autofactura(params, data); } if (data["tipoDocumento"] === 5 || data["tipoDocumento"] === 6) { this.generateDatosEspecificosPorTipoDE_NotaCreditoDebito(params, data); } if (data["tipoDocumento"] === 7) { this.generateDatosEspecificosPorTipoDE_RemisionElectronica(params, data); } } /** * Datos especificos para la factura electronica * * @param params * @param data * @param options */ generateDatosEspecificosPorTipoDE_FacturaElectronica(params, data) { if (Constante_service_1.default.indicadoresPresencias.filter((um) => um.codigo === data['factura']['presencia']).length == 0) { throw new Error("Indicador de Presencia '" + data['factura']['presencia'] + "' en data.factura.presencia no encontrado. Valores: " + Constante_service_1.default.indicadoresPresencias.map((a) => a.codigo + '-' + a.descripcion)); } this.json['rDE']['DE']['gDtipDE']['gCamFE'] = { iIndPres: data['factura']['presencia'], dDesIndPres: Constante_service_1.default.indicadoresPresencias.filter(ip => ip.codigo === data['factura']['presencia'])[0]['descripcion'], }; if (data['factura']['fechaEnvio']) { this.json['rDE']['DE']['gDtipDE']['gCamFE']['dFecEmNR'] = data['factura']['fechaEnvio']; } if (data["cliente"]["tipoOperacion"] === 3) { this.generateDatosEspecificosPorTipoDE_ComprasPublicas(params, data); } } /** * Datos especificos cuando el tipo de operacion del receptor es B2G (Campo D202) * Dentro de la factura electronica * * @param params * @param data * @param options */ generateDatosEspecificosPorTipoDE_ComprasPublicas(params, data) { if (!(data['dncp'] && data['dncp']['modalidad'] && data['dncp']['modalidad'].lenght > 0)) { throw new Error("Debe informar la modalidad de Contratación DNCP en data.dncp.modalidad"); } if (!(data['dncp'] && data['dncp']['entidad'] && data['dncp']['entidad'].lenght > 0)) { throw new Error("Debe informar la entidad de Contratación DNCP en data.dncp.entidad"); } if (!(data['dncp'] && data['dncp']['año'] && data['dncp']['año'].lenght > 0)) { throw new Error("Debe informar la año de Contratación DNCP en data.dncp.año"); } if (!(data['dncp'] && data['dncp']['secuencia'] && data['dncp']['secuencia'].lenght > 0)) { throw new Error("Debe informar la secuencia de Contratación DNCP en data.dncp.secuencia"); } if (!(data['dncp'] && data['dncp']['fecha'] && data['dncp']['fecha'].lenght > 0)) { throw new Error("Debe informar la fecha de emisión de código de Contratación DNCP en data.dncp.fecha"); } this.json['rDE']['DE']['gDtipDE']['gCamFE']['gCompPub'] = { dModCont: data['dncp']['modalidad'], dEntCont: data['dncp']['entidad'], dAnoCont: data['dncp']['año'], dSecCont: data['dncp']['secuencia'], dFeCodCont: data['dncp']['fecha'] }; } generateDatosEspecificosPorTipoDE_Autofactura(params, data) { if (Constante_service_1.default.naturalezaVendedorAutofactura.filter((um) => um.codigo === data['autoFactura']['tipoVendedor']).length == 0) { throw new Error("Tipo de Vendedor '" + data['autoFactura']['tipoVendedor'] + "' en data.autoFactura.tipoVendedor no encontrado. Valores: " + Constante_service_1.default.naturalezaVendedorAutofactura.map((a) => a.codigo + '-' + a.descripcion)); } if (Constante_service_1.default.tiposDocumentosIdentidades.filter((um) => um.codigo === data['autoFactura']['documentoTipo']).length == 0) { throw new Error("Tipoo de Documento '" + data['autoFactura']['documentoTipo'] + "' en data.autoFactura.documentoTipo no encontrado. Valores: " + Constante_service_1.default.tiposDocumentosIdentidades.map((a) => a.codigo + '-' + a.descripcion)); } if (!data['autoFactura']['ubicacion']) { throw new Error("Debe especificar la ubicación de la transacción en data.autoFactura.ubicacion"); } console.log(data['autoFactura']['ubicacion']); this.json['rDE']['DE']['gDtipDE']['gCamAE'] = { iNatVen: data['autoFactura']['tipoVendedor'], dDesNatVen: Constante_service_1.default.naturalezaVendedorAutofactura.filter(nv => nv.codigo === data['autoFactura']['tipoVendedor'])[0]['descripcion'], iTipIDVen: data['autoFactura']['documentoTipo'], dDTipIDVen: Constante_service_1.default.tiposDocumentosIdentidades.filter(td => td.codigo === data['autoFactura']['documentoTipo'])[0]['descripcion'], dNumIDVen: data['autoFactura']['documentoNumero'], dNomVen: data['autoFactura']['nombre'], dDirVen: data['autoFactura']['direccion'], dNumCasVen: data['autoFactura']['numeroCasa'], cDepVen: data['autoFactura']['departamento'], dDesDepVen: data['autoFactura']['departamentoDescripcion'], cDisVen: data['autoFactura']['distrito'], dDesDisVen: data['autoFactura']['distritoDescripcion'], cCiuVen: data['autoFactura']['ciudad'], dDesCiuVen: data['autoFactura']['ciudadDescripcion'], dDirProv: data['autoFactura']['ubicacion']['lugar'], cDepProv: data['autoFactura']['ubicacion']['departamento'], dDesDepProv: data['autoFactura']['ubicacion']['departamentoDescripcion'], cDisProv: data['autoFactura']['ubicacion']['distrito'], dDesDisProv: data['autoFactura']['ubicacion']['distritoDescripcion'], cCiuProv: data['autoFactura']['ubicacion']['ciudad'], dDesCiuProv: data['autoFactura']['ubicacion']['ciudadDescripcion'], }; } generateDatosEspecificosPorTipoDE_NotaCreditoDebito(params, data) { if (!data['notaCreditoDebito']['motivo']) { throw new Error("Debe completar el motivo para la nota de crédito/débito en data.notaCreditoDebito.motivo"); } if (params.notasCreditosMotivos.filter((um) => um.codigo === data['notaCreditoDebito']['motivo']).length == 0) { throw new Error("Motivo de la Nota de Crédito/Débito '" + data['notaCreditoDebito']['motivo'] + "' en data.notaCreditoDebito.motivo no encontrado. Valores: " + params.notasCreditosMotivos.map((a) => a.codigo + '-' + a.descripcion)); } this.json['rDE']['DE']['gDtipDE']['gCamNCDE'] = { iMotEmi: data['notaCreditoDebito']['motivo'], dDesMotEmi: Constante_service_1.default.notasCreditosMotivos.filter(nv => nv.codigo === data['notaCreditoDebito']['motivo'])[0]['descripcion'], }; } generateDatosEspecificosPorTipoDE_RemisionElectronica(params, data) { if (params.remisionesMotivos.filter((um) => um.codigo === data['remision']['motivo']).length == 0) { throw new Error("Motivo de la Remisión '" + data['remision']['motivo'] + "' en data.remision.motivo no encontrado. Valores: " + params.remisionesMotivos.map((a) => a.codigo + '-' + a.descripcion)); } if (params.remisionesResponsables.filter((um) => um.codigo === data['remision']['remisionesResponsables']).length == 0) { throw new Error("Tipo de Documento '" + data['remision']['remisionesResponsables'] + "' en data.remision.remisionesResponsables no encontrado. Valores: " + params.remisionesResponsables.map((a) => a.codigo + '-' + a.descripcion)); } this.json['rDE']['DE']['gDtipDE']['gCamNRE'] = { iMotEmiNR: data['remision']['motivo'], dDesMotEmiNR: Constante_service_1.default.remisionesMotivos.filter(nv => nv.codigo === data['remision']['motivo'])[0]['descripcion'], iRespEmiNR: data['remision']['remisionesResponsables'], dDesRespEmiNR: Constante_service_1.default.remisionesResponsables.filter(nv => nv.codigo === data['remision']['remisionesResponsables'])[0]['descripcion'], dKmR: data['remision']['kms'], dFecEm: data['remision']['fechaFactura'] }; } /** * E7. Campos que describen la condición de la operación (E600-E699) * @param params * @param data * @param options */ generateDatosCondicionOperacionDE(params, data) { if (Constante_service_1.default.condicionesOperaciones.filter((um) => um.codigo === data['condicion']['tipo']).length == 0) { throw new Error("Condición de la Operación '" + data['condicion']['tipo'] + "' en data.condicion.tipo no encontrado. Valores: " + Constante_service_1.default.condicionesOperaciones.map((a) => a.codigo + '-' + a.descripcion)); } this.json['rDE']['DE']['gDtipDE']['gCamCond'] = { iCondOpe: data['condicion']['tipo'], dDCondOpe: Constante_service_1.default.condicionesOperaciones.filter(co => co.codigo === data['condicion']['tipo'])[0]['descripcion'], }; //if (data['condicion']['tipo'] === 1) { this.generateDatosCondicionOperacionDE_Contado(params, data); //} if (data['condicion']['tipo'] === 2) { this.generateDatosCondicionOperacionDE_Credito(params, data); } } /** * E7.1. Campos que describen la forma de pago de la operación al contado o del monto * de la entrega inicial (E605-E619) * @param params * @param data * @param options */ generateDatosCondicionOperacionDE_Contado(params, data) { if (data['condicion']['entregas'] && data['condicion']['entregas'].length > 0) { const entregas = []; for (let i = 0; i < data['condicion']['entregas'].length; i++) { const dataEntrega = data['condicion']['entregas'][i]; if (Constante_service_1.default.condicionesTiposPagos.filter((um) => um.codigo === dataEntrega['tipo']).length == 0) { throw new Error("Condición de Tipo de Pago '" + dataEntrega['tipo'] + "' en data.condicion.entregas[" + i + "].tipo no encontrado. Valores: " + Constante_service_1.default.condicionesTiposPagos.map((a) => a.codigo + '-' + a.descripcion)); } const cuotaInicialEntrega = { iTiPago: dataEntrega['tipo'], dDesTiPag: Constante_service_1.default.condicionesTiposPagos.filter(co => co.codigo === dataEntrega['tipo'])[0]['descripcion'], dMonTiPag: dataEntrega['monto'], cMoneTiPag: dataEntrega['moneda'], dDMoneTiPag: dataEntrega['monedaDescripcion'], }; if (dataEntrega['moneda'] != 'PYG') { if (dataEntrega['cambio']) { cuotaInicialEntrega['dTiCamTiPag'] = dataEntrega['cambio']; } } //Verificar si el Pago es con Tarjeta de crédito if (dataEntrega['tipo'] === 3 || dataEntrega['tipo'] === 4) { if (Constante_service_1.default.condicionesOperaciones.filter((um) => um.codigo === dataEntrega['infoTarjeta']["tipo"]).length == 0) { throw new Error("Tipo de Tarjeta de Crédito '" + dataEntrega['infoTarjeta']["tipo"] + "' en data.condicion.entregas[" + i + "].infoTarjeta.tipo no encontrado. Valores: " + Constante_service_1.default.condicionesOperaciones.map((a) => a.codigo + '-' + a.descripcion)); } if (dataEntrega['infoTarjeta']["ruc"].indexOf("-") == -1) { throw new Error("Ruc de Proveedor de Tarjeta debe contener digito verificador en data.condicion.entregas[" + i + "].infoTarjeta.ruc"); } cuotaInicialEntrega['gPagTarCD'] = { iDenTarj: dataEntrega['infoTarjeta']["tipo"], dDesDenTarj: dataEntrega['infoTarjeta']["tipo"] === 99 ? dataEntrega['infoTarjeta']["tipoDescripcion"] : Constante_service_1.default.tarjetasCreditosTipos.filter(co => co.codigo === dataEntrega['infoTarjeta']['tipo'])[0]['descripcion'], dRSProTar: dataEntrega['infoTarjeta']["razonSocial"], dRUCProTar: dataEntrega['infoTarjeta']["ruc"].split("-")[0], dDVProTar: dataEntrega['infoTarjeta']["ruc"].split("-")[1], iForProPa: dataEntrega['infoTarjeta']["medioPago"], dCodAuOpe: dataEntrega['infoTarjeta']["codigoAutorizacion"], dNomTit: dataEntrega['infoTarjeta']["titular"], dNumTarj: dataEntrega['infoTarjeta']["numero"] }; } //Verificar si el Pago es con Cheque if (dataEntrega['tipo'] === 2) { cuotaInicialEntrega['gPagCheq'] = { dNumCheq: StringUtil_service_1.default.leftZero(dataEntrega['infoCheque']["numeroCheque"], 8), dBcoEmi: dataEntrega['infoCheque']["banco"], }; } entregas.push(cuotaInicialEntrega); } this.json['rDE']['DE']['gDtipDE']['gCamCond']['gPaConEIni'] = entregas; //Array de Entregas } } /** * E7.2. Campos que describen la operación a crédito (E640-E649) * * @param params * @param data * @param options */ generateDatosCondicionOperacionDE_Credito(params, data) { if (Constante_service_1.default.condicionesCreditosTipos.filter((um) => um.codigo === data['condicion']['credito']['tipo']).length == 0) { throw new Error("Tipo de Crédito '" + data['condicion']['credito']['tipo'] + "' en data.condicion.credito.tipo no encontrado. Valores: " + Constante_service_1.default.condicionesCreditosTipos.map((a) => a.codigo + '-' + a.descripcion)); } this.json['rDE']['DE']['gDtipDE']['gCamCond']['gPagCred'] = { iCondCred: data['condicion']['credito']['tipo'], dDCondCred: Constante_service_1.default.condicionesCreditosTipos.filter(co => co.codigo === data['condicion']['credito']['tipo'])[0]['descripcion'], dPlazoCre: data['condicion']['credito']['tipo'] === 1 ? data['condicion']['credito']['plazo'] : null, //dCuotas : data['condicion']['credito']['tipo'] === 2 ? data['condicion']['credito']['cuotas'] : null, dMonEnt: data['condicion']['credito']['montoEntrega'], gCuotas: [] }; if (data['condicion']['credito']['tipo'] === 2) { if (data['condicion']['credito']['cuotas']) { this.json['rDE']['DE']['gDtipDE']['gCamCond']['gPagCred']['dCuotas'] = data['condicion']['credito']['cuotas']; } } //Recorrer array de infoCuotas e informar en el JSON if (data['condicion']['credito']['tipo'] === 2) { //A Cuotas if (data['condicion']['credito']['infoCuotas'] && data['condicion']['credito']['infoCuotas'].length > 0) { for (let i = 0; i < data['condicion']['credito']['infoCuotas'].length; i++) { const infoCuota = data['condicion']['credito']['infoCuotas'][i]; const gCuotas = { cMoneCuo: infoCuota['moneda'], dDMoneCuo: infoCuota['monedaDescripcion'], dMonCuota: infoCuota['monto'], dVencCuo: infoCuota['vencimiento'], }; this.json['rDE']['DE']['gDtipDE']['gCamCond']['gPagCred']['gCuotas'].push(gCuotas); } } else { throw new Error("Debe proporcionar data.condicion.credito.infoCuotas[]"); } } } normalizeXML(xml) { xml = xml.split('\r\n').join(''); xml = xml.split('\n').join(''); xml = xml.split('\t').join(''); xml = xml.split(' ').join(''); xml = xml.split('> <').join('><'); xml = xml.split('> <').join('><'); xml = xml.replace(/\r?\n|\r/g, ''); return xml; } } exports.default = new JSonDteMainService(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbkR0ZU1haW4uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9qc29uRHRlTWFpbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtDQUFpQztBQUVqQyw4RUFBcUQ7QUFDckQsNEVBQW1EO0FBQ25ELDRFQUFtRDtBQUNuRCxnRkFBZ0Q7QUFDaEQsNEZBQTREO0FBQzVELG9HQUFxRTtBQUNyRSw0RkFBNEQ7QUFDNUQsc0ZBQXNEO0FBQ3RELDRIQUF5RjtBQUN6RixzSEFBc0Y7QUFHdEYsTUFBTSxrQkFBa0I7SUFBeEI7UUFDSSxvQkFBZSxHQUFTLElBQUksQ0FBQztRQUM3QixrQkFBYSxHQUFTLElBQUksQ0FBQztRQUMzQixTQUFJLEdBQVMsRUFBRSxDQUFDO0lBczJCcEIsQ0FBQztJQXAyQlUsV0FBVyxDQUFDLE1BQVcsRUFBRSxJQUFTO1FBQ3JDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDbkMsSUFBSTtnQkFDQSxPQUFPLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2FBQ2xEO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ1osTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ2pCO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxrQkFBa0IsQ0FBQyxNQUFXLEVBQUUsSUFBUztRQUU3QyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTFCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU1QixJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUVmLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMs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