167 lines
4.7 KiB
JavaScript
167 lines
4.7 KiB
JavaScript
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 }; // <LName Name="..."/>
|
|
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 <FullName .../>
|
|
} 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
|
|
};
|