From 9cb1b25b1d380fcee42329fd44112c8d8db17e32 Mon Sep 17 00:00:00 2001 From: Dave Date: Thu, 13 Nov 2025 16:38:00 -0500 Subject: [PATCH] feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Enhance logging --- .../rr-customer-selector.jsx | 2 +- client/src/pages/dms/dms.container.jsx | 2 +- server/rr/rr-customers.js | 27 +++++++++++++++---- server/rr/rr-job-export.js | 19 +++++++++++-- server/rr/rr-job-helpers.js | 14 +++++++--- server/rr/rr-register-socket-events.js | 17 +++++++++--- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/client/src/components/dms-customer-selector/rr-customer-selector.jsx b/client/src/components/dms-customer-selector/rr-customer-selector.jsx index e8d830815..13d30f4c1 100644 --- a/client/src/components/dms-customer-selector/rr-customer-selector.jsx +++ b/client/src/components/dms-customer-selector/rr-customer-selector.jsx @@ -211,7 +211,7 @@ export default function RRCustomerSelector({
diff --git a/client/src/pages/dms/dms.container.jsx b/client/src/pages/dms/dms.container.jsx index 5f81ed8b4..2bea7464c 100644 --- a/client/src/pages/dms/dms.container.jsx +++ b/client/src/pages/dms/dms.container.jsx @@ -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.validationNeeded) - activeSocket.on(channels.validationrNeeded, onValidationRequired); + activeSocket.on(channels.validationNeeded, onValidationRequired); return () => { activeSocket.off("connect", onConnect); diff --git a/server/rr/rr-customers.js b/server/rr/rr-customers.js index 5ad966974..09940f2f3 100644 --- a/server/rr/rr-customers.js +++ b/server/rr/rr-customers.js @@ -208,17 +208,27 @@ const buildCustomerPayloadFromJob = (job, overrides = {}) => { const createRRCustomer = async ({ bodyshop, job, overrides = {}, socket }) => { const { client, opts } = buildClientAndOpts(bodyshop); 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; try { - const safePayload = sanitizeRRCustomerPayload(payload); 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) { CreateRRLogEvent(socket, "ERROR", "RR insertCustomer transport error", { message: e?.message, - stack: e?.stack, - payload + code: e?.code, + status: e?.meta?.status || e?.status, + payload: safePayload }); 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 = { diff --git a/server/rr/rr-job-export.js b/server/rr/rr-job-export.js index 64b38f280..75299cb74 100644 --- a/server/rr/rr-job-export.js +++ b/server/rr/rr-job-export.js @@ -9,7 +9,8 @@ const CreateRRLogEvent = require("./rr-logger-event"); * @returns {Promise<{success, data: *, roStatus: *, statusBlocks,customerNo: string, svId: null, roNo: *}>} */ 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 (!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"); const { client, opts } = buildClientAndOpts(bodyshop); + const finalOpts = { ...opts, envelope: { @@ -37,6 +39,7 @@ const exportJobToRR = async (args) => { // Ensure service vehicle for create flows (best-effort) let svId = null; + if (!(existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId)) { try { 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 const payload = buildRRRepairOrderPayload({ job, 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" @@ -68,6 +76,7 @@ const exportJobToRR = async (args) => { : await client.createRepairOrder(payload, finalOpts); CreateRRLogEvent(socket, "INFO", `RR raw Repair Order ${roNoForUpdate ? "updated" : "created"}`, { + payload, response }); @@ -150,6 +159,12 @@ const finalizeRRRepairOrder = async (args) => { }); const rrRes = await client.updateRepairOrder(payload, finalOpts); + + CreateRRLogEvent(socket, "SILLY", "RR Repair Order finalized", { + payload, + response: rrRes + }); + const data = rrRes?.data || null; const roStatus = data?.roStatus || null; diff --git a/server/rr/rr-job-helpers.js b/server/rr/rr-job-helpers.js index 6c89a5e25..003d0f528 100644 --- a/server/rr/rr-job-helpers.js +++ b/server/rr/rr-job-helpers.js @@ -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 selectedCustomer * @param advisorNo + * @param story + * @param makeOverride * @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 ? String(selectedCustomer.customerNo).trim() : selectedCustomer?.custNo @@ -97,7 +99,7 @@ const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo }) => { const roStr = String(ro); - return { + const output = { // ---- RO Number (all variants; library currently requires `outsdRoNo`) ---- outsdRoNo: roStr, repairOrderNumber: roStr, @@ -112,6 +114,12 @@ const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo }) => { // ---- Mileage In (new) ---- mileageIn }; + + if (story) { + output.roComment = String(story).trim(); + } + + return output; }; /** diff --git a/server/rr/rr-register-socket-events.js b/server/rr/rr-register-socket-events.js index 5cc9b845d..7a1bc9daa 100644 --- a/server/rr/rr-register-socket-events.js +++ b/server/rr/rr-register-socket-events.js @@ -409,6 +409,7 @@ const registerRREvents = ({ socket, redisHelpers }) => { const rid = resolveJobId(jobid || jobId, { jobid, jobId }, null); let bodyshop = null; let job = null; + let createdCustomer = false; try { 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"); + createdCustomer = true; + CreateRRLogEvent(socket, "DEBUG", `{3.2} Created customer`, { custNo: selectedCustNo }); } @@ -594,7 +597,7 @@ const registerRREvents = ({ socket, redisHelpers }) => { job, selectedCustomer: { customerNo: effectiveCustNo, custNo: effectiveCustNo }, advisorNo: String(advisorNo), - existing: txEnvelope?.existing, + txEnvelope, socket }); @@ -640,8 +643,16 @@ const registerRREvents = ({ socket, redisHelpers }) => { // Still emit info result if you want socket.emit("rr-export-job:result", { jobId: rid, bodyshopId: bodyshop?.id, result }); - // ACK but indicate it's pending finalize - ack?.({ ok: true, pendingFinalize: true, dmsRoNo, outsdRoNo, result }); + // ACK but indicate it's pending finalize + include customer number + created flag + ack?.({ + ok: true, + pendingFinalize: true, + dmsRoNo, + outsdRoNo, + result, + custNo: String(effectiveCustNo), + createdCustomer + }); } else { // classify & fail (no finalize) const vendorStatusCode = Number(