feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Checkpoint
This commit is contained in:
@@ -1,24 +1,145 @@
|
||||
const { withClient } = require("./withClient");
|
||||
// server/rr/rr-lookup.js
|
||||
// Reynolds & Reynolds lookup helpers that adapt our bodyshop record to the RR client
|
||||
|
||||
async function getAdvisors({ bodyshopId, ...criteria }) {
|
||||
return withClient(bodyshopId, async (client, routing) => {
|
||||
const res = await client.getAdvisors(criteria, { routing });
|
||||
return res;
|
||||
const { RRClient } = require("./lib/index.cjs");
|
||||
const { getRRConfigFromBodyshop } = require("./rr-config");
|
||||
|
||||
/**
|
||||
* Build an RR client + common opts from a bodyshop row
|
||||
*/
|
||||
function 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
|
||||
// optional debug logger already inside lib; leave defaults
|
||||
});
|
||||
|
||||
// Common CallOptions for all ops; routing is CRITICAL for Destination block
|
||||
const opts = {
|
||||
routing: cfg.routing,
|
||||
envelope: {
|
||||
// You can override these per-call if needed
|
||||
sender: {
|
||||
component: "Rome",
|
||||
task: "CVC",
|
||||
referenceId: "Query",
|
||||
creator: "RCI",
|
||||
senderName: "RCI"
|
||||
}
|
||||
// bodId/creationDateTime auto-filled by the client if omitted
|
||||
}
|
||||
};
|
||||
|
||||
return { client, opts };
|
||||
}
|
||||
|
||||
async function getParts({ bodyshopId, ...criteria }) {
|
||||
return withClient(bodyshopId, async (client, routing) => {
|
||||
const res = await client.getParts(criteria, { routing });
|
||||
return res;
|
||||
});
|
||||
/**
|
||||
* Normalize the combined-search arguments into the RR shape.
|
||||
* We infer `kind` if not provided, based on the first detectable field.
|
||||
*/
|
||||
function toCombinedSearchPayload(args = {}) {
|
||||
const q = { ...args };
|
||||
let kind = (q.kind || "").toString().trim().toLowerCase();
|
||||
|
||||
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 (q.name && (q.name.fname || q.name.lname || q.name.mname || q.name.name)) kind = "name";
|
||||
else if (q.stkNo || q.stock) kind = "stkNo";
|
||||
}
|
||||
|
||||
// Map loose aliases into the RR builder’s expected fields
|
||||
const payload = { maxResults: q.maxResults || q.maxRecs || 50, kind };
|
||||
|
||||
switch (kind) {
|
||||
case "phone":
|
||||
payload.phone = q.phone;
|
||||
break;
|
||||
case "license":
|
||||
payload.license = q.license;
|
||||
break;
|
||||
case "vin":
|
||||
payload.vin = q.vin;
|
||||
break;
|
||||
case "namerecid":
|
||||
payload.nameRecId = q.nameRecId || q.custId;
|
||||
break;
|
||||
case "name":
|
||||
payload.name = q.name; // { fname, lname, mname } or { name }
|
||||
break;
|
||||
case "stkno":
|
||||
payload.stkNo = q.stkNo || q.stock;
|
||||
break;
|
||||
default:
|
||||
// Let the RR builder throw the canonical “Unsupported CombinedSearch kind”
|
||||
payload.kind = q.kind; // may be undefined; RR lib will validate
|
||||
}
|
||||
|
||||
// Optional vehicle narrowing; the RR builder defaults to ANY/ANY/ANY if omitted
|
||||
if (q.make || q.model || q.year) {
|
||||
payload.make = q.make;
|
||||
payload.model = q.model;
|
||||
payload.year = q.year;
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function combinedSearch({ bodyshopId, ...query }) {
|
||||
return withClient(bodyshopId, async (client, routing) => {
|
||||
const res = await client.combinedSearch(query, { routing });
|
||||
return res;
|
||||
});
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
async function rrCombinedSearch(bodyshop, args = {}) {
|
||||
const { client, opts } = buildClientAndOpts(bodyshop);
|
||||
const payload = toCombinedSearchPayload(args);
|
||||
const res = await client.combinedSearch(payload, opts);
|
||||
return res?.data ?? res; // lib returns { success, data, ... }
|
||||
}
|
||||
|
||||
module.exports = { getAdvisors, getParts, combinedSearch };
|
||||
/**
|
||||
* Advisors lookup
|
||||
* @param bodyshop
|
||||
* @param args - { department: 'B'|'S'|'P'|string, advisorNumber?: string }
|
||||
*/
|
||||
async function rrGetAdvisors(bodyshop, args = {}) {
|
||||
const { client, opts } = buildClientAndOpts(bodyshop);
|
||||
// Allow friendly department values
|
||||
const dep = (args.department || "").toString().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
|
||||
};
|
||||
|
||||
const res = await client.getAdvisors(payload, opts);
|
||||
return res?.data ?? res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parts on an internal RO
|
||||
* @param bodyshop
|
||||
* @param args - { roNumber: string } (ERA/DMS internal RO number)
|
||||
*/
|
||||
async function rrGetParts(bodyshop, args = {}) {
|
||||
const { client, opts } = buildClientAndOpts(bodyshop);
|
||||
const payload = { roNumber: String(args.roNumber || "").trim() };
|
||||
const res = await client.getParts(payload, opts);
|
||||
return res?.data ?? res;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
rrCombinedSearch,
|
||||
rrGetAdvisors,
|
||||
rrGetParts,
|
||||
buildClientAndOpts
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user