feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Checkpoint
This commit is contained in:
136
server/rr/rr-utils.js
Normal file
136
server/rr/rr-utils.js
Normal file
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Get last 8 chars of a string, uppercased
|
||||
* @param v
|
||||
* @returns {string}
|
||||
*/
|
||||
const last8 = (v) => {
|
||||
return (String(v || "") || "").slice(-8).toUpperCase();
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract owner customer numbers from VIN-based blocks
|
||||
* @param blocks
|
||||
* @param jobVin
|
||||
* @returns {Set<any>}
|
||||
*/
|
||||
const ownersFromVinBlocks = (blocks = [], jobVin = null) => {
|
||||
const out = new Set();
|
||||
const want8 = jobVin ? last8(jobVin) : null;
|
||||
|
||||
for (const blk of Array.isArray(blocks) ? blocks : []) {
|
||||
const serv = Array.isArray(blk?.ServVehicle) ? blk.ServVehicle : [];
|
||||
for (const sv of serv) {
|
||||
const svVin = String(sv?.Vehicle?.Vin || "");
|
||||
if (want8 && last8(svVin) !== want8) continue;
|
||||
const custNo = sv?.VehicleServInfo?.CustomerNo;
|
||||
if (custNo != null && String(custNo).trim() !== "") {
|
||||
out.add(String(custNo).trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make vehicle search payload from job data
|
||||
* @param job
|
||||
* @returns {null|{kind: string, license: string, maxResults: number}|{kind: string, vin: string, maxResults: number}}
|
||||
*/
|
||||
const makeVehicleSearchPayloadFromJob = (job) => {
|
||||
const vin = job?.v_vin;
|
||||
if (vin) return { kind: "vin", vin: String(vin).trim(), maxResults: 50 };
|
||||
const plate = job?.plate_no;
|
||||
if (plate) return { kind: "license", license: String(plate).trim(), maxResults: 50 };
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize customer candidates from VIN blocks
|
||||
* @param res
|
||||
* @param ownersSet
|
||||
* @returns {any[]}
|
||||
*/
|
||||
const normalizeCustomerCandidates = (res, { ownersSet = null } = {}) => {
|
||||
const blocks = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : [];
|
||||
const out = [];
|
||||
for (const blk of blocks) {
|
||||
const serv = Array.isArray(blk?.ServVehicle) ? blk.ServVehicle : [];
|
||||
const custNos = serv.map((sv) => sv?.VehicleServInfo?.CustomerNo).filter(Boolean);
|
||||
|
||||
const nci = blk?.NameContactId;
|
||||
const ind = nci?.NameId?.IndName;
|
||||
const bus = nci?.NameId?.BusName;
|
||||
const personal = [ind?.FirstName || ind?.FName, ind?.LastName || ind?.LName].filter(Boolean).join(" ").trim();
|
||||
const company = bus?.CompanyName || bus?.BName;
|
||||
const name = (personal || company || "").trim();
|
||||
|
||||
for (const custNo of custNos) {
|
||||
const cno = String(custNo).trim();
|
||||
const item = { custNo: cno, name: name || `Customer ${cno}` };
|
||||
if (ownersSet && ownersSet.has(cno)) item.isVehicleOwner = true;
|
||||
out.push(item);
|
||||
}
|
||||
}
|
||||
// Dedup by custNo, keep isVehicleOwner if any
|
||||
const seen = new Map();
|
||||
for (const c of out) {
|
||||
const key = (c.custNo || "").trim();
|
||||
if (!key) continue;
|
||||
const prev = seen.get(key);
|
||||
if (!prev) seen.set(key, c);
|
||||
else if (c.isVehicleOwner && !prev.isVehicleOwner) seen.set(key, { ...prev, isVehicleOwner: true });
|
||||
}
|
||||
return Array.from(seen.values());
|
||||
};
|
||||
|
||||
/**
|
||||
* Read advisor number from payload or cached value
|
||||
* @param payload
|
||||
* @param cached
|
||||
* @returns {string|null}
|
||||
*/
|
||||
const readAdvisorNo = (payload, cached) => {
|
||||
const v =
|
||||
(payload?.txEnvelope?.advisorNo != null && String(payload.txEnvelope.advisorNo)) ||
|
||||
(payload?.advisorNo != null && String(payload.advisorNo)) ||
|
||||
(cached != null && String(cached)) ||
|
||||
null;
|
||||
return v && v.trim() !== "" ? v : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache enum keys for RR session transaction data
|
||||
* @type {{txEnvelope: string, JobData: string, SelectedCustomer: string, AdvisorNo: string, VINCandidates: string, SelectedVin: string, ExportResult: string}}
|
||||
*/
|
||||
const RRCacheEnums = {
|
||||
txEnvelope: "RR.txEnvelope",
|
||||
JobData: "RR.JobData",
|
||||
SelectedCustomer: "RR.SelectedCustomer",
|
||||
AdvisorNo: "RR.AdvisorNo",
|
||||
VINCandidates: "RR.VINCandidates",
|
||||
SelectedVin: "RR.SelectedVin",
|
||||
ExportResult: "RR.ExportResult"
|
||||
};
|
||||
|
||||
/**
|
||||
* Get transaction type string for job ID
|
||||
* @param jobid
|
||||
* @returns {`rr:${string}`}
|
||||
*/
|
||||
const getTransactionType = (jobid) => `rr:${jobid}`;
|
||||
|
||||
/**
|
||||
* Default RR TTL (1 hour)
|
||||
* @type {number}
|
||||
*/
|
||||
const defaultRRTTL = 60 * 60;
|
||||
|
||||
module.exports = {
|
||||
RRCacheEnums,
|
||||
defaultRRTTL,
|
||||
getTransactionType,
|
||||
ownersFromVinBlocks,
|
||||
makeVehicleSearchPayloadFromJob,
|
||||
normalizeCustomerCandidates,
|
||||
readAdvisorNo
|
||||
};
|
||||
Reference in New Issue
Block a user