import { XMLParser } from "fast-xml-parser"; import { trx } from "./db.service.js"; import { actions } from "../actions/soap.actions.js"; const parser = new XMLParser({ removeNSPrefix: true, ignoreAttributes: false, parseTagValue: true, trimValues: true, }); const ALIAS_MAP = { Polizas: { service: "DescargaPolizas", method: "Descargar" }, Recibos: { service: "DescargaCompletaRecibos", method: "Descargar" }, Siniestros: { service: "DescargaSiniestros", method: "Descargar" }, Cartera: { service: "DescargaCartera", method: "DescargarCartera" }, TramiteSiniestro: { service: "ConsultaAgendaTramitacion", method: "ConsultaTramitacion" }, Poliza: { service: "ConsultaPolizas", method: "ConsultarPoliza" }, Recibo: { service: "ConsultaRecibos", method: "ConsultarRecibo" }, Siniestro: { service: "ConsultaSiniestros", method: "ConsultarSiniestro" }, }; const cleanNil = (obj) => { if (obj !== null && typeof obj === "object") { if (obj["@_nil"] === "true" || obj["@_nil"] === true) return null; if (Array.isArray(obj)) return obj.map(cleanNil); const newObj = {}; for (const [key, value] of Object.entries(obj)) { newObj[key] = cleanNil(value); } return newObj; } return obj; }; const fmt = (d) => (!isNaN(d.getTime()) ? d.toLocaleDateString("sv-SE") : null); const getFirstMonth = (m = 0) => { const now = new Date(); return fmt(new Date(now.getFullYear(), now.getMonth() + m, 1)); }; const getDate = (d = 0) => { const t = new Date(); t.setDate(t.getDate() + d); return fmt(t); }; const getXmlBody = (service, method, q) => { const templates = { DescargaPolizas: `${q.Clave}${q.CodigoRamo}${q.Empresa}${q.FechaFinal}${q.FechaInicial}${q.Identificador}${q.Plataforma}NPANRESP`, DescargaSiniestros: `truetrue${q.Clave}${q.CodigoRamo}${q.Empresa}${q.FechaFinal}${q.FechaInicial}${q.Identificador}true${q.Plataforma}`, DescargaCompletaRecibos: `${q.Clave}${q.Empresa}${q.FechaFinal}${q.FechaInicial}${q.Identificador}truetruetruetrue`, DescargaCartera: `${q.CodigoMediador}${q.Empresa}${q.FechaRenovacion}${q.Identificador}${q.Plataforma}`, ConsultaAgendaTramitacion: `${q.CodigoExpediente}${q.CodigoPoliza}${q.CodigoSiniestro}${q.Empresa}`, ConsultaPolizas: `${q.CodigoPoliza}${q.CodigoRamo}${q.CodigoSuplemento || 0}${q.Empresa}${q.Identificador}${q.Plataforma}`, ConsultaRecibos: `${q.CodigoPoliza}${q.CodigoRamo}${q.CodigoRecibo || 0}${q.CodigoSuplemento || 0}${q.Empresa}${q.Identificador}${q.Plataforma}`, ConsultaSiniestros: `${q.CodigoPoliza}${q.CodigoRamo}${q.CodigoSiniestro}${q.CodigoSuplemento || 0}${q.Empresa}${q.Identificador}${q.Plataforma}`, }; return templates[service] || `${q.Identificador}`; }; export const soapCall = async (params, query, save = true) => { const { CodigoMediador, alias } = params; const target = ALIAS_MAP[alias] || { service: params.service, method: params.method }; const { service, method } = target; if (!service) throw new Error(`Servicio o Alias '${alias || params.service}' no definido`); const url = `https://lba.realeonline.net/Reale.B2b.Services.Multitarificadores.IisHost/${service}.svc`; const Identificador = query.Identificador || process.env[`SOAP_${CodigoMediador}`]; if (!Identificador) throw new Error(`Identificador no configurado para ${CodigoMediador}`); const q = { ...query, Identificador, CodigoMediador, Clave: query.Clave || "10000", Empresa: query.Empresa || "4", Plataforma: query.Plataforma || "10000", CodigoRamo: query.CodigoRamo || "0", CodigoSuplemento: query.CodigoSuplemento || "0", CodigoPoliza: query.CodigoPoliza || "0", CodigoSiniestro: query.CodigoSiniestro || "0", CodigoExpediente: query.CodigoExpediente || "0", FechaFinal: query.FechaFinal || getDate(), FechaInicial: query.FechaInicial || (alias === "Cartera" ? getFirstMonth(0) : getFirstMonth(-1)), FechaRenovacion: query.FechaRenovacion || getFirstMonth(1), }; let nsBase = "http://reale.net/B2b/Multitarificadores"; let nsName = service; let contract = `I${service}`; let actMethod = method; let soapHeader = ""; if (service === "DescargaCartera") { nsName = "DescargaFicheros"; contract = "IDescargaCartera"; } else if (service === "ConsultaPolizas") { nsName = "ConsultaPolizas"; contract = "IConsultaPolizas"; } else if (service === "DescargaCompletaRecibos" && method === "Descargar") { actMethod = "DescargarNew"; } else if (service === "ConsultaAgendaTramitacion") { nsBase = "http://reale.net/wcf/internalServices"; nsName = ""; contract = "IAgendaTramitacion"; actMethod = "ConsultaTramitacion"; soapHeader = `${q.Plataforma}${q.Identificador}`; } const fullNs = nsName ? `${nsBase}/${nsName}` : nsBase; const soapAction = `"${fullNs}/${contract}/${actMethod}"`.replace(/([^:])\/\//g, "$1/"); const soapEnvelope = ` ${soapHeader} ${getXmlBody(service, method, q)} `.trim(); try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "text/xml;charset=UTF-8", "SOAPAction": soapAction }, body: soapEnvelope, }); const xmlData = await response.text(); const rawJson = parser.parse(xmlData); if (!response.ok) { const fault = rawJson.Envelope?.Body?.Fault?.faultstring; throw new Error(typeof fault === "object" ? JSON.stringify(fault) : fault || `Error ${response.status}`); } const resultBody = rawJson.Envelope?.Body; const responseName = Object.keys(resultBody || {})[0]; const result = cleanNil(resultBody?.[responseName] || {}); // CUIDADO DA ERROR CUANDO USAS /Poliza /Siniestro /Recibo porque no hay un action para ellos if (save) await trx({ action: service, data: result }, actions); return result; } catch (error) { console.error(`[SOAP ERROR] ${service}/${method}:`, error.message); throw error; } };