feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Cashiering Checkpoint
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// server/rr/rr-job-export.js
|
||||
const { buildRRRepairOrderPayload } = require("./rr-job-helpers");
|
||||
const { buildClientAndOpts } = require("./rr-lookup");
|
||||
const { ensureRRServiceVehicle } = require("./rr-service-vehicles");
|
||||
@@ -8,6 +7,9 @@ const RRLogger = require("./rr-logger");
|
||||
* Orchestrate an RR export (assumes custNo already resolved):
|
||||
* - Ensure service vehicle (create flows)
|
||||
* - Create or update the Repair Order
|
||||
*
|
||||
* NOTE: This function performs the create/update step and returns the RO data.
|
||||
* "Mark exported" is handled later by the finalize step after cashiering.
|
||||
*/
|
||||
async function exportJobToRR(args) {
|
||||
const { bodyshop, job, advisorNo, selectedCustomer, existing, socket } = args || {};
|
||||
@@ -31,14 +33,15 @@ async function exportJobToRR(args) {
|
||||
sender: {
|
||||
...(opts?.envelope?.sender || {}),
|
||||
task: "BSMRO",
|
||||
referenceId: existing?.dmsRepairOrderId ? "Update" : "Insert"
|
||||
// If we have an existing RO number we'll be updating, otherwise inserting
|
||||
referenceId: existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId ? "Update" : "Insert"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure service vehicle for create flows (best-effort)
|
||||
let svId = null;
|
||||
if (!existing?.dmsRepairOrderId) {
|
||||
if (!(existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId)) {
|
||||
try {
|
||||
const svRes = await ensureRRServiceVehicle({
|
||||
bodyshop,
|
||||
@@ -54,19 +57,33 @@ async function exportJobToRR(args) {
|
||||
}
|
||||
}
|
||||
|
||||
// Build RO payload (now includes DeptType/departmentType + variants)
|
||||
// Build RO payload for create/update
|
||||
const payload = buildRRRepairOrderPayload({
|
||||
job,
|
||||
selectedCustomer: { customerNo: String(selected), custNo: String(selected) },
|
||||
advisorNo: String(advisorNo)
|
||||
});
|
||||
|
||||
const rrRes = existing?.dmsRepairOrderId
|
||||
? await client.updateRepairOrder({ ...payload, dmsRepairOrderId: existing.dmsRepairOrderId }, finalOpts)
|
||||
// Canonical update key is "roNo" (prefer DMS RO number); accept fallbacks from "existing"
|
||||
const roNoForUpdate = existing?.roNo || existing?.dmsRoNo || existing?.dmsRepairOrderId || null;
|
||||
|
||||
const rrRes = roNoForUpdate
|
||||
? await client.updateRepairOrder({ ...payload, roNo: String(roNoForUpdate) }, finalOpts) // ✅ use roNo on update
|
||||
: await client.createRepairOrder(payload, finalOpts);
|
||||
|
||||
const data = rrRes?.data || null;
|
||||
const roStatus = data?.roStatus || null;
|
||||
|
||||
// Extract canonical roNo you'll need for finalize step
|
||||
const roNo =
|
||||
data?.dmsRoNo ??
|
||||
data?.outsdRoNo ??
|
||||
roStatus?.dmsRoNo ??
|
||||
roStatus?.DMSRoNo ??
|
||||
roStatus?.outsdRoNo ??
|
||||
roStatus?.OutsdRoNo ??
|
||||
null;
|
||||
|
||||
return {
|
||||
success: rrRes?.success === true || roStatus?.status === "Success",
|
||||
data,
|
||||
@@ -75,8 +92,85 @@ async function exportJobToRR(args) {
|
||||
xml: rrRes?.xml,
|
||||
parsed: rrRes?.parsed,
|
||||
customerNo: String(selected),
|
||||
svId
|
||||
svId,
|
||||
roNo
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { exportJobToRR };
|
||||
/**
|
||||
* Finalize an RR Repair Order by sending finalUpdate: "Y".
|
||||
* The caller should pass the canonical `roNo` if available (prefer DMS RO #).
|
||||
* If not provided, we *safely* fall back to the external (Outsd) RO number.
|
||||
*/
|
||||
async function finalizeRRRepairOrder(args) {
|
||||
const { bodyshop, job, advisorNo, customerNo, roNo, vin, socket } = args || {};
|
||||
const log = RRLogger(socket, { ns: "rr-finalize" });
|
||||
|
||||
if (!bodyshop) throw new Error("finalizeRRRepairOrder: bodyshop is required");
|
||||
if (!job) throw new Error("finalizeRRRepairOrder: job is required");
|
||||
if (!advisorNo) throw new Error("finalizeRRRepairOrder: advisorNo is required");
|
||||
if (!customerNo) throw new Error("finalizeRRRepairOrder: customerNo is required");
|
||||
|
||||
// The external (Outsd) RO is our deterministic fallback and correlation id.
|
||||
const externalRo = job?.ro_number ?? job?.id;
|
||||
if (externalRo == null) throw new Error("finalizeRRRepairOrder: outsdRoNo (job.ro_number/id) is required");
|
||||
|
||||
// Prefer DMS RO for update; fall back to external when DMS RO isn't known
|
||||
const roNoToSend = roNo ? String(roNo) : String(externalRo);
|
||||
|
||||
const { client, opts } = buildClientAndOpts(bodyshop);
|
||||
const finalOpts = {
|
||||
...opts,
|
||||
envelope: {
|
||||
...(opts?.envelope || {}),
|
||||
sender: {
|
||||
...(opts?.envelope?.sender || {}),
|
||||
task: "BSMRO",
|
||||
referenceId: "Update"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const cleanVin =
|
||||
(job?.v_vin || vin || "")
|
||||
.toString()
|
||||
.replace(/[^A-Za-z0-9]/g, "")
|
||||
.toUpperCase()
|
||||
.slice(0, 17) || undefined;
|
||||
|
||||
// IMPORTANT: include "roNo" on updates (RR requires it). Also send outsdRoNo for correlation.
|
||||
const payload = {
|
||||
roNo: roNoToSend, // ✅ REQUIRED BY RR on update
|
||||
outsdRoNo: String(externalRo),
|
||||
finalUpdate: "Y",
|
||||
departmentType: "B",
|
||||
customerNo: String(customerNo),
|
||||
advisorNo: String(advisorNo),
|
||||
vin: cleanVin,
|
||||
mileageIn: job?.kmin,
|
||||
mileageOut: job?.kmout,
|
||||
estimate: { estimateType: "Final" }
|
||||
};
|
||||
|
||||
log("info", "RR finalize updateRepairOrder", {
|
||||
roNo: roNoToSend,
|
||||
outsdRoNo: String(externalRo),
|
||||
customerNo: String(customerNo),
|
||||
advisorNo: String(advisorNo)
|
||||
});
|
||||
|
||||
const rrRes = await client.updateRepairOrder(payload, finalOpts);
|
||||
const data = rrRes?.data || null;
|
||||
const roStatus = data?.roStatus || null;
|
||||
|
||||
return {
|
||||
success: rrRes?.success === true || roStatus?.status === "Success",
|
||||
data,
|
||||
roStatus,
|
||||
statusBlocks: rrRes?.statusBlocks || [],
|
||||
xml: rrRes?.xml,
|
||||
parsed: rrRes?.parsed
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { exportJobToRR, finalizeRRRepairOrder };
|
||||
|
||||
Reference in New Issue
Block a user