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;
}
};