feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration / Merges and adjustments

This commit is contained in:
Dave
2025-11-26 15:37:34 -05:00
parent f1bad01cec
commit fa7da3cad0
6 changed files with 73 additions and 23 deletions

View File

@@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { resolveRROpCodeFromBodyshop } from "../../utils/dmsUtils.js";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
@@ -97,7 +98,7 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title }) {
fetchAllocations(); fetchAllocations();
}, [fetchAllocations]); }, [fetchAllocations]);
const opCode = bodyshop?.rr_configuration?.baseOpCode || "28TOZ"; const opCode = resolveRROpCodeFromBodyshop(bodyshop);
const segmentLabelMap = { const segmentLabelMap = {
partsExtras: "Parts/Extras", partsExtras: "Parts/Extras",

View File

@@ -49,8 +49,8 @@ import {
validatePasswordResetSuccess validatePasswordResetSuccess
} from "./user.actions"; } from "./user.actions";
import UserActionTypes from "./user.types"; import UserActionTypes from "./user.types";
//import * as amplitude from '@amplitude/analytics-browser';
import posthog from "posthog-js"; import posthog from "posthog-js";
import { bodyshopHasDmsKey, determineDMSTypeByBodyshop, DMS_MAP } from "../../utils/dmsUtils";
const fpPromise = FingerprintJS.load(); const fpPromise = FingerprintJS.load();
@@ -387,16 +387,15 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
) )
]; ];
const hasDmsKey = bodyshopHasDmsKey(payload);
const dmsType = hasDmsKey ? determineDMSTypeByBodyshop(payload) : null;
const additionalSegments = [ const additionalSegments = [
payload.cdk_dealerid && "CDK", dmsType === DMS_MAP.cdk && DMS_MAP.cdk.toUpperCase(),
payload.pbs_serialnumber && "PBS", dmsType === DMS_MAP.pbs && DMS_MAP.pbs.toUpperCase(),
// payload.rr_dealerid && "Reynolds", dmsType === DMS_MAP.reynolds && DMS_MAP.reynolds.toUpperCase(),
payload.accountingconfig.qbo === true && "QBO", payload.accountingconfig?.qbo === true && "QBO",
payload.accountingconfig.qbo === false && payload.accountingconfig?.qbo === false && !hasDmsKey && "QBD"
!payload.cdk_dealerid &&
!payload.pbs_serialnumber &&
// !payload.rr_dealerid &&
"QBD"
].filter(Boolean); ].filter(Boolean);
featureSegments.push(...additionalSegments); featureSegments.push(...additionalSegments);

View File

@@ -70,3 +70,26 @@ export const isWssMode = (mode) => {
*/ */
export const bodyshopHasDmsKey = (bodyshop) => export const bodyshopHasDmsKey = (bodyshop) =>
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || bodyshop.rr_dealerid; bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || bodyshop.rr_dealerid;
/**
* Resolve RR OpCode from bodyshop.rr_configuration.defaults
* Is Duplicated on server/rr/rr-utils.js
* @param bodyshop
* @returns {`${string}${string}${string}`}
*/
export const resolveRROpCodeFromBodyshop = (bodyshop) => {
if (!bodyshop) throw new Error("bodyshop is required");
const cfg = bodyshop?.rr_configuration || {};
const defaults = cfg?.defaults || {};
const prefix = (defaults.prefix ?? "").toString().trim();
const base = (defaults.base ?? "").toString().trim();
const suffix = (defaults.suffix ?? "").toString().trim();
if (!prefix && !base && !suffix) {
throw new Error("No RR OpCode parts found in bodyshop configuration");
}
return `${prefix}${base}${suffix}`;
};

View File

@@ -3,7 +3,7 @@ const { buildClientAndOpts } = require("./rr-lookup");
const CreateRRLogEvent = require("./rr-logger-event"); const CreateRRLogEvent = require("./rr-logger-event");
const { extractRrResponsibilityCenters } = require("./rr-responsibility-centers"); const { extractRrResponsibilityCenters } = require("./rr-responsibility-centers");
const CdkCalculateAllocations = require("./rr-calculate-allocations").default; const CdkCalculateAllocations = require("./rr-calculate-allocations").default;
const { resolveRROpCodeFromBodyshop } = require("./rr-utils");
/** /**
* Derive RR status information from response object. * Derive RR status information from response object.
* @param rrRes * @param rrRes
@@ -137,19 +137,17 @@ const exportJobToRR = async (args) => {
allocations = []; allocations = [];
} }
// 3) OpCode (global, but overridable) const resolvedBaseOpCode = resolveRROpCodeFromBodyshop(bodyshop);
// - baseOpCode can come from bodyshop or rrCentersConfig (you'll map it in onboarding)
// - txEnvelope can carry an explicit override field (opCode/opcode/op_code)
const baseOpCode = bodyshop?.rr_configuration?.baseOpCode || "28TOZ"; // TODO Change / implement default handling policy
const opCodeOverride = txEnvelope?.opCode || txEnvelope?.opcode || txEnvelope?.op_code || null; const opCodeOverride = txEnvelope?.opCode || txEnvelope?.opcode || txEnvelope?.op_code || null;
if (opCodeOverride || baseOpCode) { if (opCodeOverride || resolvedBaseOpCode) {
opCode = String(opCodeOverride || baseOpCode).trim() || null; opCode = String(opCodeOverride || resolvedBaseOpCode).trim() || null;
} }
CreateRRLogEvent(socket, "SILLY", "RR OP config resolved", { CreateRRLogEvent(socket, "SILLY", "RR OP config resolved", {
opCode opCode,
baseFromConfig: resolvedBaseOpCode
}); });
// Build RO payload for create. // Build RO payload for create.

View File

@@ -16,6 +16,7 @@ const {
defaultRRTTL, defaultRRTTL,
RRCacheEnums RRCacheEnums
} = require("./rr-utils"); } = require("./rr-utils");
const { resolveRROpCodeFromBodyshop } = require("./rr-utils");
const { GraphQLClient } = require("graphql-request"); const { GraphQLClient } = require("graphql-request");
const queries = require("../graphql-client/queries"); const queries = require("../graphql-client/queries");
@@ -924,13 +925,17 @@ const registerRREvents = ({ socket, redisHelpers }) => {
jobAllocations = Array.isArray(ack.jobAllocations) ? ack.jobAllocations : []; jobAllocations = Array.isArray(ack.jobAllocations) ? ack.jobAllocations : [];
} }
// Try to derive OpCode from bodyshop; fall back to default // Try to derive OpCode from bodyshop.rr_configuration.defaults; fall back to default
let opCode = "28TOZ"; let opCode;
try { try {
const { bodyshopId } = await getSessionOrSocket(redisHelpers, socket); const { bodyshopId } = await getSessionOrSocket(redisHelpers, socket);
const bodyshop = await getBodyshopForSocket({ bodyshopId, socket }); const bodyshop = await getBodyshopForSocket({ bodyshopId, socket });
opCode = bodyshop?.rr_configuration?.baseOpCode || opCode; opCode = resolveRROpCodeFromBodyshop(bodyshop, opCode);
CreateRRLogEvent(socket, "DEBUG", "rr-calculate-allocations: resolved OpCode", {
opCode
});
} catch (e) { } catch (e) {
CreateRRLogEvent(socket, "WARN", "rr-calculate-allocations: bodyshop lookup failed, using default OpCode", { CreateRRLogEvent(socket, "WARN", "rr-calculate-allocations: bodyshop lookup failed, using default OpCode", {
error: e.message error: e.message

View File

@@ -182,6 +182,29 @@ const getTransactionType = (jobid) => `rr:${jobid}`;
*/ */
const defaultRRTTL = 60 * 60; const defaultRRTTL = 60 * 60;
/**
* Resolve RR OpCode from bodyshop.rr_configuration.defaults
* Is Duplicated on client/src/utils/dmsUtils.js
* @param bodyshop
* @returns {string}
*/
const resolveRROpCodeFromBodyshop = (bodyshop) => {
if (!bodyshop) throw new Error("bodyshop is required");
const cfg = bodyshop?.rr_configuration || {};
const defaults = cfg?.defaults || {};
const prefix = (defaults.prefix ?? "").toString().trim();
const base = (defaults.base ?? "").toString().trim();
const suffix = (defaults.suffix ?? "").toString().trim();
if (!prefix && !base && !suffix) {
throw new Error("No RR OpCode parts found in bodyshop configuration");
}
return `${prefix}${base}${suffix}`;
};
module.exports = { module.exports = {
RRCacheEnums, RRCacheEnums,
defaultRRTTL, defaultRRTTL,
@@ -189,5 +212,6 @@ module.exports = {
ownersFromVinBlocks, ownersFromVinBlocks,
makeVehicleSearchPayloadFromJob, makeVehicleSearchPayloadFromJob,
normalizeCustomerCandidates, normalizeCustomerCandidates,
readAdvisorNo readAdvisorNo,
resolveRROpCodeFromBodyshop
}; };