diff --git a/server/rr/rr-job-export.js b/server/rr/rr-job-export.js index 75299cb74..13a3daaf6 100644 --- a/server/rr/rr-job-export.js +++ b/server/rr/rr-job-export.js @@ -1,16 +1,19 @@ const { buildRRRepairOrderPayload } = require("./rr-job-helpers"); const { buildClientAndOpts } = require("./rr-lookup"); -const { ensureRRServiceVehicle } = require("./rr-service-vehicles"); const CreateRRLogEvent = require("./rr-logger-event"); /** - * Export a job to Reynolds & Reynolds as a Repair Order (create or update). + * Step 1: Export a job to Reynolds & Reynolds as a *new* Repair Order. + * + * This is the "create" phase only: + * - We always call createRepairOrder + * - Any follow-up / finalUpdate is handled by finalizeRRRepairOrder + * * @param args - * @returns {Promise<{success, data: *, roStatus: *, statusBlocks,customerNo: string, svId: null, roNo: *}>} + * @returns {Promise<{success, data: *, roStatus: *, statusBlocks, customerNo: string, svId: string|null, roNo: *}>} */ const exportJobToRR = async (args) => { - const { bodyshop, job, advisorNo, selectedCustomer, txEnvelope, socket } = args || {}; - const existing = txEnvelope?.existing || {}; + const { bodyshop, job, advisorNo, selectedCustomer, txEnvelope, socket, svId } = args || {}; if (!bodyshop) throw new Error("exportJobToRR: bodyshop is required"); if (!job) throw new Error("exportJobToRR: job is required"); @@ -24,6 +27,7 @@ const exportJobToRR = async (args) => { const { client, opts } = buildClientAndOpts(bodyshop); + // For step 1 we always "Insert" (create). Finalize handles the update. const finalOpts = { ...opts, envelope: { @@ -31,35 +35,15 @@ const exportJobToRR = async (args) => { sender: { ...(opts?.envelope?.sender || {}), task: "BSMRO", - // If we have an existing RO number we'll be updating, otherwise inserting - referenceId: existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId ? "Update" : "Insert" + referenceId: "Insert" } } }; - // Ensure service vehicle for create flows (best-effort) - let svId = null; - - if (!(existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId)) { - try { - const svRes = await ensureRRServiceVehicle({ - bodyshop, - job, - overrides: {}, - customerNo: String(selected), - socket - }); - svId = svRes?.svId || null; - CreateRRLogEvent(socket, "INFO", "RR service vehicle ensured", { created: svRes?.created, svId }); - } catch (e) { - CreateRRLogEvent(socket, "WARN", "RR ensure service vehicle failed; continuing", { error: e?.message }); - } - } - 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 const payload = buildRRRepairOrderPayload({ job, selectedCustomer: { customerNo: String(selected), custNo: String(selected) }, @@ -68,14 +52,9 @@ const exportJobToRR = async (args) => { makeOverride }); - // Canonical update key is "roNo" (prefer DMS RO number); accept fallbacks from "existing" - const roNoForUpdate = existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId || null; + const response = await client.createRepairOrder(payload, finalOpts); - const response = roNoForUpdate - ? await client.updateRepairOrder({ ...payload, roNo: String(roNoForUpdate) }, finalOpts) // ✅ use roNo on update - : await client.createRepairOrder(payload, finalOpts); - - CreateRRLogEvent(socket, "INFO", `RR raw Repair Order ${roNoForUpdate ? "updated" : "created"}`, { + CreateRRLogEvent(socket, "INFO", "RR raw Repair Order created", { payload, response }); @@ -92,13 +71,16 @@ const exportJobToRR = async (args) => { roStatus, statusBlocks: response?.statusBlocks || [], customerNo: String(selected), + // svId comes from the earlier ensureRRServiceVehicle call (if the caller passes it) svId, roNo }; }; /** - * Finalize an RR Repair Order by sending finalUpdate: "Y". + * Step 2: Finalize an RR Repair Order by sending finalUpdate: "Y". + * This is the *update* phase. + * * @param args * @returns {Promise<{success, data: *, roStatus: *, statusBlocks}>} */ @@ -146,7 +128,6 @@ const finalizeRRRepairOrder = async (args) => { customerNo: String(customerNo), advisorNo: String(advisorNo), vin: cleanVin, - mileageIn: job?.kmin, mileageOut: job?.kmout, estimate: { estimateType: "Final" } }; diff --git a/server/rr/rr-job-helpers.js b/server/rr/rr-job-helpers.js index 003d0f528..42323711b 100644 --- a/server/rr/rr-job-helpers.js +++ b/server/rr/rr-job-helpers.js @@ -80,7 +80,8 @@ const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo, story }) if (!customerNo) throw new Error("No RR customer selected (customerNo/CustNo missing)"); const adv = advisorNo != null && String(advisorNo).trim() !== "" ? String(advisorNo).trim() : null; - if (!adv) throw new Error("advisorNo is required for RR export"); + + if (!adv) throw new Error("advisorNo is required for RR export"); const vinRaw = job?.v_vin; const vin = @@ -95,24 +96,16 @@ const buildRRRepairOrderPayload = ({ job, selectedCustomer, advisorNo, story }) const ro = job?.ro_number != null ? job.ro_number : job?.id != null ? job.id : null; if (ro == null) throw new Error("Missing repair order identifier (ro_number/id)"); - const mileageIn = job.kmin; - const roStr = String(ro); const output = { - // ---- RO Number (all variants; library currently requires `outsdRoNo`) ---- outsdRoNo: roStr, repairOrderNumber: roStr, - // ---- Department type (Body) ---- departmentType: "B", - // ---- VIN variants ---- vin, - // ---- Customer number variants ---- customerNo: String(customerNo), - // ---- Advisor number variants ---- advisorNo: adv, - // ---- Mileage In (new) ---- - mileageIn + mileageIn: job.kmin }; if (story) { diff --git a/server/rr/rr-register-socket-events.js b/server/rr/rr-register-socket-events.js index 7a1bc9daa..16034d91c 100644 --- a/server/rr/rr-register-socket-events.js +++ b/server/rr/rr-register-socket-events.js @@ -598,7 +598,8 @@ const registerRREvents = ({ socket, redisHelpers }) => { selectedCustomer: { customerNo: effectiveCustNo, custNo: effectiveCustNo }, advisorNo: String(advisorNo), txEnvelope, - socket + socket, + svId: ensured?.svId || null }); // Cache raw export result + pending RO number for finalize