const { RRClient } = require("./lib/index.cjs"); const { getRRConfigFromBodyshop } = require("./rr-config"); /** * Build an RR client + common opts from a bodyshop row */ const buildClientAndOpts = (bodyshop) => { const cfg = getRRConfigFromBodyshop(bodyshop); const client = new RRClient({ baseUrl: cfg.baseUrl, username: cfg.username, password: cfg.password, timeoutMs: cfg.timeoutMs, retries: cfg.retries }); // Common CallOptions for all ops; routing is CRITICAL for Destination block const opts = { routing: cfg.routing, envelope: { sender: { component: "Rome", task: "CVC", referenceId: "Query", creator: "RCI", senderName: "RCI" } } }; return { client, opts }; }; /** * Normalize the combined-search arguments into the RR shape. * We infer `kind` if not provided, based on the first detectable field. */ const toCombinedSearchPayload = (args = {}) => { const q = { ...args }; // Decide kind if not provided let kind = (q.kind || "").toString().trim(); if (!kind) { if (q.phone) kind = "phone"; else if (q.license) kind = "license"; else if (q.vin) kind = "vin"; else if (q.nameRecId || q.custId) kind = "nameRecId"; else if (typeof q.name === "string" || (q.name && (q.name.fname || q.name.lname || q.name.mname || q.name.name))) { kind = "name"; } else if (q.stkNo || q.stock) kind = "stkNo"; } const payload = { // set both; the XML layer renders MaxRecs maxRecs: q.maxResults ?? q.maxRecs ?? 50, maxResults: q.maxResults ?? q.maxRecs ?? 50, kind }; switch ((kind || "").toLowerCase()) { case "phone": payload.kind = "phone"; payload.phone = String(q.phone ?? "").trim(); break; case "license": payload.kind = "license"; payload.license = String(q.license ?? "").trim(); break; case "vin": payload.kind = "vin"; payload.vin = String(q.vin ?? "").trim(); break; case "namerecid": payload.kind = "nameRecId"; payload.nameRecId = String(q.nameRecId ?? q.custId ?? "").trim(); break; case "stkno": case "stkNo": payload.kind = "stkNo"; payload.stkNo = String(q.stkNo ?? q.stock ?? "").trim(); break; case "name": { payload.kind = "name"; const n = q.name; if (typeof n === "string") { const last = n.trim(); if (last) payload.name = { name: last }; // break; } const fname = n?.fname && String(n.fname).trim(); const lname = n?.lname && String(n.lname).trim(); const mname = n?.mname && String(n.mname).trim(); const lastOnly = n?.name && String(n.name).trim(); if (fname || lname || mname) { const full = {}; if (fname) full.fname = fname; if (mname) full.mname = mname; if (lname) full.lname = lname; payload.name = full; // will render } else if (lastOnly) { payload.name = { name: lastOnly }; // explicit last-only } break; } default: payload.kind = kind; } if (q.make || q.model || q.year) { payload.make = q.make || "ANY"; payload.model = q.model || "ANY"; payload.year = q.year || "ANY"; } if (q.vin && payload.kind !== "vin") payload.vin = String(q.vin).trim(); if (q.phone && payload.kind !== "phone") payload.phone = String(q.phone).trim(); if (q.license && payload.kind !== "license") payload.license = String(q.license).trim(); return payload; }; /** * Combined customer/service/vehicle search * @param bodyshop - bodyshop row (must include rr_dealerid & rr_configuration with store/branch) * @param args - search inputs (phone | license | vin | nameRecId | name | stkNo) */ const rrCombinedSearch = async (bodyshop, args = {}) => { const { client, opts } = buildClientAndOpts(bodyshop); const payload = toCombinedSearchPayload(args); const res = await client.combinedSearch(payload, opts); return res; }; /** * Advisors lookup * @param bodyshop * @param args - { department: 'B'|'S'|'P'|string, advisorNumber?: string } */ const rrGetAdvisors = async (bodyshop, args = {}) => { const { client, opts } = buildClientAndOpts(bodyshop); // Accept either department or departmentType from FE const dep = String(args.department ?? args.departmentType ?? "").toUpperCase(); const department = dep === "BODY" || dep === "BODYSHOP" ? "B" : dep === "SERVICE" ? "S" : dep === "PARTS" ? "P" : dep || "B"; const payload = { department, advisorNumber: args.advisorNumber ? String(args.advisorNumber) : undefined }; return client.getAdvisors(payload, opts); }; module.exports = { rrCombinedSearch, rrGetAdvisors, buildClientAndOpts };