feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - rr-Utils hardening
This commit is contained in:
@@ -28,11 +28,38 @@ function normalizeRrList(list) {
|
|||||||
(custNo ? String(custNo) : "");
|
(custNo ? String(custNo) : "");
|
||||||
if (!custNo) return null;
|
if (!custNo) return null;
|
||||||
const vinOwner = !!(row.vinOwner ?? row.isVehicleOwner);
|
const vinOwner = !!(row.vinOwner ?? row.isVehicleOwner);
|
||||||
return { custNo: String(custNo), name, vinOwner };
|
|
||||||
|
// Pass through address from backend if present; tolerate various shapes
|
||||||
|
const address =
|
||||||
|
row.address && typeof row.address === "object"
|
||||||
|
? {
|
||||||
|
line1: row.address.line1 ?? row.address.addr1 ?? row.address.Address1 ?? undefined,
|
||||||
|
line2: row.address.line2 ?? row.address.addr2 ?? row.address.Address2 ?? undefined,
|
||||||
|
city: row.address.city ?? undefined,
|
||||||
|
state: row.address.state ?? row.address.stateOrProvince ?? undefined,
|
||||||
|
postalCode: row.address.postalCode ?? row.address.zip ?? undefined,
|
||||||
|
country: row.address.country ?? row.address.countryCode ?? undefined
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return { custNo: String(custNo), name, vinOwner, address };
|
||||||
})
|
})
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Small formatter used by the RR Address column render
|
||||||
|
function rrAddressToString(addr) {
|
||||||
|
if (!addr) return "";
|
||||||
|
const parts = [
|
||||||
|
addr.line1,
|
||||||
|
addr.line2,
|
||||||
|
[addr.city, addr.state].filter(Boolean).join(" "),
|
||||||
|
addr.postalCode,
|
||||||
|
addr.country
|
||||||
|
].filter(Boolean);
|
||||||
|
return parts.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
export function DmsCustomerSelector({ bodyshop, jobid }) {
|
export function DmsCustomerSelector({ bodyshop, jobid }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [customerList, setcustomerList] = useState([]);
|
const [customerList, setcustomerList] = useState([]);
|
||||||
@@ -278,6 +305,12 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
|
|||||||
|
|
||||||
const rrColumns = [
|
const rrColumns = [
|
||||||
{ title: t("jobs.fields.dms.id"), dataIndex: "custNo", key: "custNo" },
|
{ title: t("jobs.fields.dms.id"), dataIndex: "custNo", key: "custNo" },
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.dms.vinowner"),
|
||||||
|
dataIndex: "vinOwner",
|
||||||
|
key: "vinOwner",
|
||||||
|
render: (_t, r) => <Checkbox disabled checked={!!(r.vinOwner ?? r.isVehicleOwner)} />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.dms.name1"),
|
title: t("jobs.fields.dms.name1"),
|
||||||
dataIndex: "name",
|
dataIndex: "name",
|
||||||
@@ -285,10 +318,9 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
|
|||||||
sorter: (a, b) => alphaSort(a?.name, b?.name)
|
sorter: (a, b) => alphaSort(a?.name, b?.name)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.dms.vinowner"),
|
title: t("jobs.fields.dms.address"),
|
||||||
dataIndex: "vinOwner",
|
key: "address",
|
||||||
key: "vinOwner",
|
render: (record) => rrAddressToString(record.address)
|
||||||
render: (_t, r) => <Checkbox disabled checked={!!(r.vinOwner ?? r.isVehicleOwner)} />
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ const makeVehicleSearchPayloadFromJob = (job) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize customer candidates from VIN blocks
|
* Normalize customer candidates from VIN/name blocks, including address + owner flag
|
||||||
* Adds `vinOwner` (and keeps `isVehicleOwner` for backward compat).
|
|
||||||
* @param res
|
* @param res
|
||||||
* @param ownersSet
|
* @param ownersSet
|
||||||
* @returns {any[]}
|
* @returns {any[]}
|
||||||
@@ -54,6 +53,51 @@ const makeVehicleSearchPayloadFromJob = (job) => {
|
|||||||
const normalizeCustomerCandidates = (res, { ownersSet = null } = {}) => {
|
const normalizeCustomerCandidates = (res, { ownersSet = null } = {}) => {
|
||||||
const blocks = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : [];
|
const blocks = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : [];
|
||||||
const out = [];
|
const out = [];
|
||||||
|
|
||||||
|
const pickAddr = (addrArr) => {
|
||||||
|
const arr = Array.isArray(addrArr) ? addrArr : addrArr ? [addrArr] : [];
|
||||||
|
if (!arr.length) return null;
|
||||||
|
|
||||||
|
const chosen = arr.find((a) => (a?.Type || a?.type || "").toString().toUpperCase() === "P") || arr[0];
|
||||||
|
|
||||||
|
// NEW: include County
|
||||||
|
const line1 = chosen?.Addr1 ?? chosen?.AddressLine1 ?? chosen?.Line1 ?? chosen?.Street1 ?? undefined;
|
||||||
|
const line2 = chosen?.Addr2 ?? chosen?.AddressLine2 ?? chosen?.Line2 ?? chosen?.Street2 ?? undefined;
|
||||||
|
const city = chosen?.City ?? chosen?.city ?? undefined;
|
||||||
|
const state = chosen?.State ?? chosen?.StateOrProvince ?? chosen?.state ?? undefined;
|
||||||
|
const postalCode = chosen?.Zip ?? chosen?.PostalCode ?? chosen?.zip ?? undefined;
|
||||||
|
const country = chosen?.Country ?? chosen?.CountryCode ?? chosen?.country ?? undefined;
|
||||||
|
const county = chosen?.County ?? chosen?.county ?? undefined; // << added
|
||||||
|
|
||||||
|
// instrumentation (kept minimal; County is now expected)
|
||||||
|
if ((process.env.RR_DEBUG_ADDR ?? "1") !== "0") {
|
||||||
|
const allowed = new Set([
|
||||||
|
"Type",
|
||||||
|
"Addr1",
|
||||||
|
"AddressLine1",
|
||||||
|
"Line1",
|
||||||
|
"Street1",
|
||||||
|
"Addr2",
|
||||||
|
"AddressLine2",
|
||||||
|
"Line2",
|
||||||
|
"Street2",
|
||||||
|
"City",
|
||||||
|
"State",
|
||||||
|
"StateOrProvince",
|
||||||
|
"Zip",
|
||||||
|
"PostalCode",
|
||||||
|
"Country",
|
||||||
|
"CountryCode",
|
||||||
|
"County" // << allow County
|
||||||
|
]);
|
||||||
|
const unknown = Object.keys(chosen || {}).filter((k) => !allowed.has(k));
|
||||||
|
if (unknown.length) console.log("[RR:normCandidates] Unexpected address keys seen:", unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line1 && !city && !state && !postalCode && !country && !county) return null;
|
||||||
|
return { line1, line2, city, state, postalCode, country, county };
|
||||||
|
};
|
||||||
|
|
||||||
for (const blk of blocks) {
|
for (const blk of blocks) {
|
||||||
const serv = Array.isArray(blk?.ServVehicle) ? blk.ServVehicle : [];
|
const serv = Array.isArray(blk?.ServVehicle) ? blk.ServVehicle : [];
|
||||||
const custNos = serv.map((sv) => sv?.VehicleServInfo?.CustomerNo).filter(Boolean);
|
const custNos = serv.map((sv) => sv?.VehicleServInfo?.CustomerNo).filter(Boolean);
|
||||||
@@ -61,35 +105,49 @@ const normalizeCustomerCandidates = (res, { ownersSet = null } = {}) => {
|
|||||||
const nci = blk?.NameContactId;
|
const nci = blk?.NameContactId;
|
||||||
const ind = nci?.NameId?.IndName;
|
const ind = nci?.NameId?.IndName;
|
||||||
const bus = nci?.NameId?.BusName;
|
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 personal = [ind?.FirstName ?? ind?.FName, ind?.LastName ?? ind?.LName].filter(Boolean).join(" ").trim();
|
||||||
|
const company = bus?.CompanyName ?? bus?.BName;
|
||||||
const name = (personal || company || "").trim();
|
const name = (personal || company || "").trim();
|
||||||
|
|
||||||
|
const address = pickAddr(nci?.Address);
|
||||||
|
|
||||||
for (const custNo of custNos) {
|
for (const custNo of custNos) {
|
||||||
const cno = String(custNo).trim();
|
const cno = String(custNo).trim();
|
||||||
const isOwner = !!(ownersSet && ownersSet.has(cno));
|
if (!cno) continue;
|
||||||
|
|
||||||
const item = {
|
const item = {
|
||||||
custNo: cno,
|
custNo: cno,
|
||||||
name: name || `Customer ${cno}`,
|
name: name || `Customer ${cno}`,
|
||||||
vinOwner: isOwner,
|
address: address || undefined
|
||||||
isVehicleOwner: isOwner // legacy key kept for any older FE code
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (ownersSet && ownersSet.has(cno)) {
|
||||||
|
item.isVehicleOwner = true;
|
||||||
|
item.vinOwner = true;
|
||||||
|
}
|
||||||
|
|
||||||
out.push(item);
|
out.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Dedup by custNo, keep vinOwner/isVehicleOwner if any
|
|
||||||
const seen = new Map();
|
const byId = new Map();
|
||||||
for (const c of out) {
|
for (const c of out) {
|
||||||
const key = (c.custNo || "").trim();
|
const key = (c.custNo || "").trim();
|
||||||
if (!key) continue;
|
if (!key) continue;
|
||||||
const prev = seen.get(key);
|
const prev = byId.get(key);
|
||||||
if (!prev) {
|
if (!prev) byId.set(key, c);
|
||||||
seen.set(key, c);
|
else {
|
||||||
} else if ((c.vinOwner || c.isVehicleOwner) && !(prev.vinOwner || prev.isVehicleOwner)) {
|
byId.set(key, {
|
||||||
seen.set(key, { ...prev, vinOwner: true, isVehicleOwner: true });
|
...prev,
|
||||||
|
isVehicleOwner: prev.isVehicleOwner || c.isVehicleOwner,
|
||||||
|
vinOwner: prev.vinOwner || c.vinOwner,
|
||||||
|
address: prev.address || c.address
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Array.from(seen.values());
|
|
||||||
|
return Array.from(byId.values());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,12 +157,13 @@ const normalizeCustomerCandidates = (res, { ownersSet = null } = {}) => {
|
|||||||
* @returns {string|null}
|
* @returns {string|null}
|
||||||
*/
|
*/
|
||||||
const readAdvisorNo = (payload, cached) => {
|
const readAdvisorNo = (payload, cached) => {
|
||||||
const v =
|
const tx = payload?.txEnvelope || payload?.envelope || {};
|
||||||
(payload?.txEnvelope?.advisorNo != null && String(payload.txEnvelope.advisorNo)) ||
|
|
||||||
(payload?.advisorNo != null && String(payload.advisorNo)) ||
|
const get = (v) => (v != null && String(v).trim() !== "" ? String(v).trim() : null);
|
||||||
(cached != null && String(cached)) ||
|
|
||||||
null;
|
let value = get(tx?.advisorNo) || get(payload?.advisorNo) || get(cached) || null;
|
||||||
return v && v.trim() !== "" ? v : null;
|
|
||||||
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user