feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration -Dedupe

This commit is contained in:
Dave
2025-11-07 16:09:18 -05:00
parent c0157454e1
commit d45d557a81
2 changed files with 32 additions and 48 deletions

View File

@@ -160,36 +160,8 @@ async function rrGetAdvisors(bodyshop, args = {}) {
return res?.data ?? res;
}
/**
* Parts lookup (graceful if the underlying lib exposes a different name)
* @param bodyshop
* @param args - common fields like { partNumber, description, make, model, year }
*/
async function rrGetParts(bodyshop, args = {}) {
const { client, opts } = buildClientAndOpts(bodyshop);
const payload = {
partNumber: args.partNumber ?? args.partNo ?? args.number ?? undefined,
description: args.description ?? undefined,
make: args.make ?? undefined,
model: args.model ?? undefined,
year: args.year ?? undefined
};
// Try common method names. If none exist, return an empty list to avoid crashes.
if (typeof client.getParts === "function") {
const res = await client.getParts(payload, opts);
return res?.data ?? res;
}
if (typeof client.getPartNumbers === "function") {
const res = await client.getPartNumbers(payload, opts);
return res?.data ?? res;
}
return [];
}
module.exports = {
rrCombinedSearch,
rrGetAdvisors,
rrGetParts,
buildClientAndOpts
};

View File

@@ -2,7 +2,7 @@
// RR events aligned to Fortellis flow with Fortellis-style logging via CreateRRLogEvent
const CreateRRLogEvent = require("../rr/rr-logger-event");
const { rrCombinedSearch, rrGetAdvisors, rrGetParts, buildClientAndOpts } = require("../rr/rr-lookup");
const { rrCombinedSearch, rrGetAdvisors, buildClientAndOpts } = require("../rr/rr-lookup");
const { QueryJobData } = require("../rr/rr-job-helpers");
const { exportJobToRR } = require("../rr/rr-job-export");
const CdkCalculateAllocations = require("../cdk/cdk-calculate-allocations").default;
@@ -46,6 +46,33 @@ function sortVehicleOwnerFirst(list) {
.map(({ v }) => v);
}
/**
* NEW: merge candidates coming from multiple queries (name + vin) by custNo.
* - keeps first non-empty name
* - preserves/ORs vinOwner/isVehicleOwner
* - keeps first non-empty address
*/
function mergeByCustNo(items = []) {
const byId = new Map();
for (const c of items) {
const id = (c?.custNo || "").trim();
if (!id) continue;
const prev = byId.get(id);
if (!prev) {
byId.set(id, { ...c, isVehicleOwner: !!(c.vinOwner || c.isVehicleOwner) });
} else {
byId.set(id, {
...prev,
name: prev.name || c.name,
isVehicleOwner: !!(prev.isVehicleOwner || prev.vinOwner || c.isVehicleOwner || c.vinOwner),
vinOwner: !!(prev.vinOwner || c.vinOwner || prev.isVehicleOwner || c.isVehicleOwner),
address: prev.address || c.address
});
}
}
return Array.from(byId.values());
}
async function getSessionOrSocket(redisHelpers, socket) {
let sess = null;
try {
@@ -142,7 +169,10 @@ async function rrMultiCustomerSearch({ bodyshop, job, socket, redisHelpers }) {
}
}
return sortVehicleOwnerFirst(merged);
// NEW: dedupe across queries (name + vin)
const deduped = mergeByCustNo(merged);
return sortVehicleOwnerFirst(deduped);
}
// ---------------- register handlers ----------------
@@ -253,24 +283,6 @@ function registerRREvents({ socket, redisHelpers }) {
}
});
// ---------- Parts ----------
socket.on("rr-get-parts", async (args = {}, ack) => {
try {
const { bodyshopId } = await getSessionOrSocket(redisHelpers, socket);
const bodyshop = await getBodyshopForSocket({ bodyshopId, socket });
CreateRRLogEvent(socket, "DEBUG", "rr-get-parts: begin", { args });
const res = await rrGetParts(bodyshop, args);
ack?.({ ok: true, result: res });
socket.emit("rr-get-parts:result", res);
CreateRRLogEvent(socket, "DEBUG", "rr-get-parts: success", {
count: Array.isArray(res) ? res.length : undefined
});
} catch (err) {
CreateRRLogEvent(socket, "ERROR", "rr-get-parts: failed", { error: err?.message });
ack?.({ ok: false, error: err?.message || "get parts failed" });
}
});
// ================= Fortellis-style two-step export =================
// 1) Stage export -> search (Full Name + VIN) -> emit rr-select-customer
socket.on("rr-export-job", async ({ jobid, jobId, txEnvelope } = {}) => {