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

This commit is contained in:
Dave
2025-10-08 13:57:34 -04:00
parent 2ffc4b81f4
commit de02b34a63
28 changed files with 2550 additions and 2443 deletions

View File

@@ -1,137 +1,99 @@
/**
* @file rr-customer.js
* @description Reynolds & Reynolds (Rome) Customer Insert/Update integration.
* Builds request payloads using rr-mappers and executes via rr-helpers.
* All dealer-specific data (DealerNumber, LocationId, etc.) is read from the DB (bodyshop.rr_configuration).
* @description Rome (Reynolds & Reynolds) Customer Insert / Update integration.
* Maps internal customer objects to Rome XML schemas and executes RCI calls.
*/
const { MakeRRCall, RRActions } = require("./rr-helpers");
const { assertRrOk } = require("./rr-error");
const { MakeRRCall } = require("./rr-helpers");
const { mapCustomerInsert, mapCustomerUpdate } = require("./rr-mappers");
const RRLogger = require("./rr-logger");
const { client } = require("../graphql-client/graphql-client");
const { GET_BODYSHOP_BY_ID } = require("../graphql-client/queries");
const { RrApiError } = require("./rr-error");
/**
* Fetch rr_configuration for the current bodyshop directly from DB.
* This ensures we always have the latest Dealer/Location mapping.
* Insert a new customer into Rome.
* @param {Socket} socket - WebSocket connection for logging context
* @param {Object} customer - Hasura customer record
* @param {Object} bodyshopConfig - DMS configuration
* @returns {Promise<Object>} result
*/
async function getDealerConfigFromDB(bodyshopId, logger) {
async function insertCustomer(socket, customer, bodyshopConfig) {
const action = "InsertCustomer";
const template = "InsertCustomer";
try {
const result = await client.request(GET_BODYSHOP_BY_ID, { id: bodyshopId });
const config = result?.bodyshops_by_pk?.rr_configuration || null;
RRLogger(socket, "info", `Starting RR ${action} for customer ${customer.id}`);
if (!config) {
throw new Error(`No rr_configuration found for bodyshop ID ${bodyshopId}`);
}
const data = mapCustomerInsert(customer, bodyshopConfig);
logger?.debug?.(`Fetched rr_configuration for bodyshop ${bodyshopId}`, config);
return config;
const resultXml = await MakeRRCall({
action,
body: { template, data },
socket,
dealerConfig: bodyshopConfig,
jobid: customer.id
});
RRLogger(socket, "debug", `${action} completed successfully`, { customerId: customer.id });
return {
success: true,
dms: "Rome",
action,
customerId: customer.id,
xml: resultXml
};
} catch (error) {
logger?.log?.("rr-get-dealer-config", "ERROR", "rr", null, {
bodyshopId,
RRLogger(socket, "error", `Error in ${action} for customer ${customer.id}`, {
message: error.message,
stack: error.stack
});
throw error;
throw new RrApiError(`RR InsertCustomer failed: ${error.message}`, "INSERT_CUSTOMER_ERROR");
}
}
/**
* CUSTOMER INSERT (Rome Customer Insert Specification 1.2)
* Creates a new customer record in the DMS.
*
* @param {object} options
* @param {object} options.socket - socket.io connection or express req
* @param {object} options.redisHelpers
* @param {object} options.JobData - normalized job record
* Update an existing customer in Rome.
* @param {Socket} socket
* @param {Object} customer
* @param {Object} bodyshopConfig
* @returns {Promise<Object>}
*/
async function RrCustomerInsert({ socket, redisHelpers, JobData }) {
const bodyshopId = socket?.bodyshopId || JobData?.bodyshopid;
const logger = socket?.logger || console;
async function updateCustomer(socket, customer, bodyshopConfig) {
const action = "UpdateCustomer";
const template = "UpdateCustomer";
try {
RRLogger(socket, "info", "RR Customer Insert started", { jobid: JobData?.id, bodyshopId });
RRLogger(socket, "info", `Starting RR ${action} for customer ${customer.id}`);
const dealerConfig = await getDealerConfigFromDB(bodyshopId, logger);
const data = mapCustomerUpdate(customer, bodyshopConfig);
// Build Mustache variables for the InsertCustomer.xml template
const vars = mapCustomerInsert(JobData, dealerConfig);
const data = await MakeRRCall({
action: RRActions.CreateCustomer, // resolves to SOAPAction + URL
body: { template: "InsertCustomer", data: vars }, // render server/rr/xml-templates/InsertCustomer.xml
redisHelpers,
const resultXml = await MakeRRCall({
action,
body: { template, data },
socket,
jobid: JobData.id
dealerConfig: bodyshopConfig,
jobid: customer.id
});
const response = assertRrOk(data, { apiName: "RR Create Customer" });
RRLogger(socket, "debug", "RR Customer Insert success", {
jobid: JobData?.id,
dealer: dealerConfig?.dealerCode || dealerConfig?.dealer_code
});
RRLogger(socket, "debug", `${action} completed successfully`, { customerId: customer.id });
return response;
return {
success: true,
dms: "Rome",
action,
customerId: customer.id,
xml: resultXml
};
} catch (error) {
RRLogger(socket, "error", `RR Customer Insert failed: ${error.message}`, { jobid: JobData?.id });
throw error;
}
}
/**
* CUSTOMER UPDATE (Rome Customer Update Specification 1.2)
* Updates an existing RR customer record.
*
* @param {object} options
* @param {object} options.socket
* @param {object} options.redisHelpers
* @param {object} options.JobData
* @param {object} options.existingCustomer - current RR customer record (from Combined Search)
* @param {object} options.patch - updated fields from frontend
*/
async function RrCustomerUpdate({ socket, redisHelpers, JobData, existingCustomer, patch }) {
const bodyshopId = socket?.bodyshopId || JobData?.bodyshopid;
const logger = socket?.logger || console;
try {
RRLogger(socket, "info", "RR Customer Update started", {
jobid: JobData?.id,
bodyshopId,
existingCustomerId: existingCustomer?.CustomerId
RRLogger(socket, "error", `Error in ${action} for customer ${customer.id}`, {
message: error.message,
stack: error.stack
});
const dealerConfig = await getDealerConfigFromDB(bodyshopId, logger);
// Build Mustache variables for the UpdateCustomer.xml template
const vars = mapCustomerUpdate(existingCustomer, patch, dealerConfig);
const data = await MakeRRCall({
action: RRActions.UpdateCustomer, // resolves to SOAPAction + URL
body: { template: "UpdateCustomer", data: vars }, // render server/rr/xml-templates/UpdateCustomer.xml
redisHelpers,
socket,
jobid: JobData.id
});
const response = assertRrOk(data, { apiName: "RR Update Customer" });
RRLogger(socket, "debug", "RR Customer Update success", {
jobid: JobData?.id,
customerId: existingCustomer?.CustomerId
});
return response;
} catch (error) {
RRLogger(socket, "error", `RR Customer Update failed: ${error.message}`, {
jobid: JobData?.id,
customerId: existingCustomer?.CustomerId
});
throw error;
throw new RrApiError(`RR UpdateCustomer failed: ${error.message}`, "UPDATE_CUSTOMER_ERROR");
}
}
module.exports = {
RrCustomerInsert,
RrCustomerUpdate,
getDealerConfigFromDB
insertCustomer,
updateCustomer
};