feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Checkpoint
This commit is contained in:
@@ -1,66 +1,137 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// RR Customer endpoints (create/update) wired through MakeRRCall.
|
||||
// Shapes are mapped via rr-mappers.js and validated via rr-error.js.
|
||||
//
|
||||
// What’s still missing (complete when you wire to the PDFs):
|
||||
// - Final request envelopes & field names in rr-mappers.js
|
||||
// - Definitive success/error envelope checks in rr-error.js
|
||||
// - Any RR-specific headers (dealer/tenant/site) once known
|
||||
// -----------------------------------------------------------------------------
|
||||
/**
|
||||
* @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).
|
||||
*/
|
||||
|
||||
const { MakeRRCall, RRActions } = require("./rr-helpers");
|
||||
const { assertRrOk } = require("./rr-error");
|
||||
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");
|
||||
|
||||
/**
|
||||
* Create a customer in RR.
|
||||
* Fetch rr_configuration for the current bodyshop directly from DB.
|
||||
* This ensures we always have the latest Dealer/Location mapping.
|
||||
*/
|
||||
async function getDealerConfigFromDB(bodyshopId, logger) {
|
||||
try {
|
||||
const result = await client.request(GET_BODYSHOP_BY_ID, { id: bodyshopId });
|
||||
const config = result?.bodyshops_by_pk?.rr_configuration || null;
|
||||
|
||||
if (!config) {
|
||||
throw new Error(`No rr_configuration found for bodyshop ID ${bodyshopId}`);
|
||||
}
|
||||
|
||||
logger?.debug?.(`Fetched rr_configuration for bodyshop ${bodyshopId}`, config);
|
||||
return config;
|
||||
} catch (error) {
|
||||
logger?.log?.("rr-get-dealer-config", "ERROR", "rr", null, {
|
||||
bodyshopId,
|
||||
message: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CUSTOMER INSERT (Rome Customer Insert Specification 1.2)
|
||||
* Creates a new customer record in the DMS.
|
||||
*
|
||||
* @param {Object} deps
|
||||
* @param {Socket|ExpressRequest} deps.socket
|
||||
* @param {Object} deps.redisHelpers - redisHelpers API (not used here directly)
|
||||
* @param {Object} deps.JobData - Rome Job data used to build the payload
|
||||
* @returns {Promise<any>} RR response (envelope TBD)
|
||||
* @param {object} options
|
||||
* @param {object} options.socket - socket.io connection or express req
|
||||
* @param {object} options.redisHelpers
|
||||
* @param {object} options.JobData - normalized job record
|
||||
*/
|
||||
async function RrCustomerInsert({ socket, redisHelpers, JobData }) {
|
||||
// Map JobData -> RR "Customer Insert" request body
|
||||
const body = mapCustomerInsert(JobData);
|
||||
const bodyshopId = socket?.bodyshopId || JobData?.bodyshopid;
|
||||
const logger = socket?.logger || console;
|
||||
|
||||
const data = await MakeRRCall({
|
||||
...RRActions.CreateCustomer, // POST /customer/v1/
|
||||
body,
|
||||
redisHelpers,
|
||||
socket,
|
||||
jobid: JobData?.id
|
||||
});
|
||||
try {
|
||||
RRLogger(socket, "info", "RR Customer Insert started", { jobid: JobData?.id, bodyshopId });
|
||||
|
||||
// TODO: assertRrOk should be updated once RR’s success envelope is finalized
|
||||
return assertRrOk(data, { apiName: "RR Create Customer" });
|
||||
const dealerConfig = await getDealerConfigFromDB(bodyshopId, logger);
|
||||
|
||||
// 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,
|
||||
socket,
|
||||
jobid: JobData.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
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
RRLogger(socket, "error", `RR Customer Insert failed: ${error.message}`, { jobid: JobData?.id });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing customer in RR.
|
||||
* CUSTOMER UPDATE (Rome Customer Update Specification 1.2)
|
||||
* Updates an existing RR customer record.
|
||||
*
|
||||
* @param {Object} deps
|
||||
* @param {Socket|ExpressRequest} deps.socket
|
||||
* @param {Object} deps.redisHelpers
|
||||
* @param {Object} deps.JobData - context only (job id for correlation)
|
||||
* @param {Object} deps.existingCustomer - Current RR customer record
|
||||
* @param {Object} deps.patch - Minimal delta from UI to apply onto existingCustomer
|
||||
* @returns {Promise<any>} RR response
|
||||
* @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 }) {
|
||||
// Build a merged/normalized payload for RR Update
|
||||
const body = mapCustomerUpdate(existingCustomer, patch);
|
||||
const bodyshopId = socket?.bodyshopId || JobData?.bodyshopid;
|
||||
const logger = socket?.logger || console;
|
||||
|
||||
const data = await MakeRRCall({
|
||||
...RRActions.UpdateCustomer, // PUT /customer/v1/ (append id inside body/path per final spec)
|
||||
body,
|
||||
redisHelpers,
|
||||
socket,
|
||||
jobid: JobData?.id
|
||||
});
|
||||
try {
|
||||
RRLogger(socket, "info", "RR Customer Update started", {
|
||||
jobid: JobData?.id,
|
||||
bodyshopId,
|
||||
existingCustomerId: existingCustomer?.CustomerId
|
||||
});
|
||||
|
||||
return assertRrOk(data, { apiName: "RR Update Customer" });
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { RrCustomerInsert, RrCustomerUpdate };
|
||||
module.exports = {
|
||||
RrCustomerInsert,
|
||||
RrCustomerUpdate,
|
||||
getDealerConfigFromDB
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user