feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Enhance logging

This commit is contained in:
Dave
2025-11-13 16:38:00 -05:00
parent 4c250f6189
commit 9cb1b25b1d
6 changed files with 66 additions and 15 deletions

View File

@@ -211,7 +211,7 @@ export default function RRCustomerSelector({
<div> <div>
<Space> <Space>
<Button type="primary" onClick={onValidationFinished}> <Button type="primary" onClick={onValidationFinished}>
Finished / Close Finished
</Button> </Button>
</Space> </Space>
</div> </div>

View File

@@ -310,7 +310,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
if (mode === DMS_MAP.reynolds && channels.partialResult) activeSocket.on(channels.partialResult, onPartialResult); if (mode === DMS_MAP.reynolds && channels.partialResult) activeSocket.on(channels.partialResult, onPartialResult);
if (mode === DMS_MAP.reynolds && channels.validationNeeded) if (mode === DMS_MAP.reynolds && channels.validationNeeded)
activeSocket.on(channels.validationrNeeded, onValidationRequired); activeSocket.on(channels.validationNeeded, onValidationRequired);
return () => { return () => {
activeSocket.off("connect", onConnect); activeSocket.off("connect", onConnect);

View File

@@ -208,17 +208,27 @@ const buildCustomerPayloadFromJob = (job, overrides = {}) => {
const createRRCustomer = async ({ bodyshop, job, overrides = {}, socket }) => { const createRRCustomer = async ({ bodyshop, job, overrides = {}, socket }) => {
const { client, opts } = buildClientAndOpts(bodyshop); const { client, opts } = buildClientAndOpts(bodyshop);
const payload = buildCustomerPayloadFromJob(job, overrides); const payload = buildCustomerPayloadFromJob(job, overrides);
const safePayload = sanitizeRRCustomerPayload(payload);
// Story step: clearly show we are about to hit Reynolds insertCustomer
CreateRRLogEvent(socket, "DEBUG", "{CU} insertCustomer: begin", {
ibFlag: safePayload.ibFlag,
hasAddress: Array.isArray(safePayload.addresses) && safePayload.addresses.length > 0,
hasPhones: Array.isArray(safePayload.phones) && safePayload.phones.length > 0,
hasEmails: Array.isArray(safePayload.emails) && safePayload.emails.length > 0
});
let response; let response;
try { try {
const safePayload = sanitizeRRCustomerPayload(payload);
response = await client.insertCustomer(safePayload, opts); response = await client.insertCustomer(safePayload, opts);
CreateRRLogEvent(socket, "SILLY", "RR createRRCustomer called", { response }); // Very noisy; only show when log level is cranked to SILLY
CreateRRLogEvent(socket, "SILLY", "{CU} insertCustomer: raw response", { response });
} catch (e) { } catch (e) {
CreateRRLogEvent(socket, "ERROR", "RR insertCustomer transport error", { CreateRRLogEvent(socket, "ERROR", "RR insertCustomer transport error", {
message: e?.message, message: e?.message,
stack: e?.stack, code: e?.code,
payload status: e?.meta?.status || e?.status,
payload: safePayload
}); });
throw e; throw e;
} }
@@ -242,7 +252,14 @@ const createRRCustomer = async ({ bodyshop, job, overrides = {}, socket }) => {
); );
} }
return { customerNo: String(customerNo), raw: data }; const out = { customerNo: String(customerNo), raw: data };
CreateRRLogEvent(socket, "INFO", "{CU} insertCustomer: success", {
customerNo: out.customerNo,
status: trx || null
});
return out;
}; };
module.exports = { module.exports = {

View File

@@ -9,7 +9,8 @@ const CreateRRLogEvent = require("./rr-logger-event");
* @returns {Promise<{success, data: *, roStatus: *, statusBlocks,customerNo: string, svId: null, roNo: *}>} * @returns {Promise<{success, data: *, roStatus: *, statusBlocks,customerNo: string, svId: null, roNo: *}>}
*/ */
const exportJobToRR = async (args) => { const exportJobToRR = async (args) => {
const { bodyshop, job, advisorNo, selectedCustomer, existing, socket } = args || {}; const { bodyshop, job, advisorNo, selectedCustomer, txEnvelope, socket } = args || {};
const existing = txEnvelope?.existing || {};
if (!bodyshop) throw new Error("exportJobToRR: bodyshop is required"); if (!bodyshop) throw new Error("exportJobToRR: bodyshop is required");
if (!job) throw new Error("exportJobToRR: job is required"); if (!job) throw new Error("exportJobToRR: job is required");
@@ -22,6 +23,7 @@ const exportJobToRR = async (args) => {
if (!selected) throw new Error("exportJobToRR: selectedCustomer.custNo/customerNo is required"); if (!selected) throw new Error("exportJobToRR: selectedCustomer.custNo/customerNo is required");
const { client, opts } = buildClientAndOpts(bodyshop); const { client, opts } = buildClientAndOpts(bodyshop);
const finalOpts = { const finalOpts = {
...opts, ...opts,
envelope: { envelope: {
@@ -37,6 +39,7 @@ const exportJobToRR = async (args) => {
// Ensure service vehicle for create flows (best-effort) // Ensure service vehicle for create flows (best-effort)
let svId = null; let svId = null;
if (!(existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId)) { if (!(existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId)) {
try { try {
const svRes = await ensureRRServiceVehicle({ const svRes = await ensureRRServiceVehicle({
@@ -53,11 +56,16 @@ const exportJobToRR = async (args) => {
} }
} }
const story = txEnvelope?.story ? String(txEnvelope.story).trim() : null;
const makeOverride = txEnvelope?.makeOverride ? String(txEnvelope.makeOverride).trim() : null;
// Build RO payload for create/update // Build RO payload for create/update
const payload = buildRRRepairOrderPayload({ const payload = buildRRRepairOrderPayload({
job, job,
selectedCustomer: { customerNo: String(selected), custNo: String(selected) }, selectedCustomer: { customerNo: String(selected), custNo: String(selected) },
advisorNo: String(advisorNo) advisorNo: String(advisorNo),
story,
makeOverride
}); });
// Canonical update key is "roNo" (prefer DMS RO number); accept fallbacks from "existing" // Canonical update key is "roNo" (prefer DMS RO number); accept fallbacks from "existing"
@@ -68,6 +76,7 @@ const exportJobToRR = async (args) => {
: await client.createRepairOrder(payload, finalOpts); : await client.createRepairOrder(payload, finalOpts);
CreateRRLogEvent(socket, "INFO", `RR raw Repair Order ${roNoForUpdate ? "updated" : "created"}`, { CreateRRLogEvent(socket, "INFO", `RR raw Repair Order ${roNoForUpdate ? "updated" : "created"}`, {
payload,
response response
}); });
@@ -150,6 +159,12 @@ const finalizeRRRepairOrder = async (args) => {
}); });
const rrRes = await client.updateRepairOrder(payload, finalOpts); const rrRes = await client.updateRepairOrder(payload, finalOpts);
CreateRRLogEvent(socket, "SILLY", "RR Repair Order finalized", {
payload,
response: rrRes
});
const data = rrRes?.data || null; const data = rrRes?.data || null;
const roStatus = data?.roStatus || null; const roStatus = data?.roStatus || null;

View File

@@ -62,13 +62,15 @@ const QueryJobData = async (ctx = {}, jobId) => {
}; };
/** /**
* Build RR Repair Order payload from job and customer data. * Build Repair Order payload for RR from job and customer data.
* @param job * @param job
* @param selectedCustomer * @param selectedCustomer
* @param advisorNo * @param advisorNo
* @param story
* @param makeOverride
* @returns {{outsdRoNo: string, repairOrderNumber: string, departmentType: string, vin: string, customerNo: string, advisorNo: string, mileageIn: *|null}} * @returns {{outsdRoNo: string, repairOrderNumber: string, departmentType: string, vin: string, customerNo: string, advisorNo: string, mileageIn: *|null}}
*/ */
const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo }) => { const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo, story }) => {
const customerNo = selectedCustomer?.customerNo const customerNo = selectedCustomer?.customerNo
? String(selectedCustomer.customerNo).trim() ? String(selectedCustomer.customerNo).trim()
: selectedCustomer?.custNo : selectedCustomer?.custNo
@@ -97,7 +99,7 @@ const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo }) => {
const roStr = String(ro); const roStr = String(ro);
return { const output = {
// ---- RO Number (all variants; library currently requires `outsdRoNo`) ---- // ---- RO Number (all variants; library currently requires `outsdRoNo`) ----
outsdRoNo: roStr, outsdRoNo: roStr,
repairOrderNumber: roStr, repairOrderNumber: roStr,
@@ -112,6 +114,12 @@ const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo }) => {
// ---- Mileage In (new) ---- // ---- Mileage In (new) ----
mileageIn mileageIn
}; };
if (story) {
output.roComment = String(story).trim();
}
return output;
}; };
/** /**

View File

@@ -409,6 +409,7 @@ const registerRREvents = ({ socket, redisHelpers }) => {
const rid = resolveJobId(jobid || jobId, { jobid, jobId }, null); const rid = resolveJobId(jobid || jobId, { jobid, jobId }, null);
let bodyshop = null; let bodyshop = null;
let job = null; let job = null;
let createdCustomer = false;
try { try {
if (!rid) throw new Error("jobid required"); if (!rid) throw new Error("jobid required");
@@ -445,6 +446,8 @@ const registerRREvents = ({ socket, redisHelpers }) => {
if (!selectedCustNo) throw new Error("RR create customer returned no custNo"); if (!selectedCustNo) throw new Error("RR create customer returned no custNo");
createdCustomer = true;
CreateRRLogEvent(socket, "DEBUG", `{3.2} Created customer`, { custNo: selectedCustNo }); CreateRRLogEvent(socket, "DEBUG", `{3.2} Created customer`, { custNo: selectedCustNo });
} }
@@ -594,7 +597,7 @@ const registerRREvents = ({ socket, redisHelpers }) => {
job, job,
selectedCustomer: { customerNo: effectiveCustNo, custNo: effectiveCustNo }, selectedCustomer: { customerNo: effectiveCustNo, custNo: effectiveCustNo },
advisorNo: String(advisorNo), advisorNo: String(advisorNo),
existing: txEnvelope?.existing, txEnvelope,
socket socket
}); });
@@ -640,8 +643,16 @@ const registerRREvents = ({ socket, redisHelpers }) => {
// Still emit info result if you want // Still emit info result if you want
socket.emit("rr-export-job:result", { jobId: rid, bodyshopId: bodyshop?.id, result }); socket.emit("rr-export-job:result", { jobId: rid, bodyshopId: bodyshop?.id, result });
// ACK but indicate it's pending finalize // ACK but indicate it's pending finalize + include customer number + created flag
ack?.({ ok: true, pendingFinalize: true, dmsRoNo, outsdRoNo, result }); ack?.({
ok: true,
pendingFinalize: true,
dmsRoNo,
outsdRoNo,
result,
custNo: String(effectiveCustNo),
createdCustomer
});
} else { } else {
// classify & fail (no finalize) // classify & fail (no finalize)
const vendorStatusCode = Number( const vendorStatusCode = Number(