// File: server/rr/rr-customers.js const { RRClient } = require("./lib/index.cjs"); const { getRRConfigFromBodyshop } = require("./rr-config"); const RRLogger = require("./rr-logger"); // Build client + opts from bodyshop function buildClientAndOpts(bodyshop) { const cfg = getRRConfigFromBodyshop(bodyshop); const client = new RRClient({ baseUrl: cfg.baseUrl, username: cfg.username, password: cfg.password, timeoutMs: cfg.timeoutMs, retries: cfg.retries }); const opts = { routing: cfg.routing, envelope: { sender: { component: "Rome", task: "CU", referenceId: "Insert", creator: "RCI", senderName: "RCI" } } }; return { client, opts }; } function digitsOnly(s) { return String(s || "").replace(/\D/g, ""); } function uniq(arr) { return Array.from(new Set(arr)); } /** * Build a payload that matches the RR client expectations for insert/update: * - ibFlag: 'I' (individual) or 'B' (business). If we have a first name, default to 'I', else 'B' if company present. * - Must include lastName OR customerName. * - addresses[] / phones[] / emails[] per the library’s toView() contract. */ function buildCustomerPayloadFromJob(job, overrides = {}) { // Pull ONLY from job.ownr_* fields (no job.customer.*) const firstName = overrides.firstName ?? job?.ownr_fn ?? undefined; const lastName = overrides.lastName ?? job?.ownr_ln ?? undefined; const companyName = overrides.companyName ?? overrides.company ?? job?.ownr_co_nm ?? undefined; // Decide Individual vs Business (caller can force via overrides.ibFlag) const ibFlag = (overrides.ibFlag || (firstName ? "I" : companyName ? "B" : "I")).toUpperCase(); // Email(s) const email = overrides.email ?? job?.ownr_ea ?? undefined; const emails = email ? [{ address: String(email) }] : undefined; // Phones const phoneCandidates = [overrides.phone, job?.ownr_ph1, job?.ownr_ph2] .map((v) => digitsOnly(v)) .filter((v) => v && v.length >= 7); const phones = uniq(phoneCandidates).map((num) => ({ number: num })); // Address (include only if line1 exists; template requires Addr1 if address is present) const line1 = overrides.addressLine1 ?? job?.ownr_addr1 ?? undefined; const addresses = line1 ? [ { type: overrides.addressType || "P", line1, line2: overrides.addressLine2 ?? job?.ownr_addr2 ?? undefined, city: overrides.city ?? job?.ownr_city ?? undefined, state: overrides.state ?? job?.ownr_st ?? undefined, postalCode: overrides.postalCode ?? job?.ownr_zip ?? undefined, country: (overrides.country ?? job?.ownr_ctry ?? "CA") || undefined } ] : undefined; // Enforce lib requirement: lastName OR customerName if (!lastName && !companyName) { throw new Error( "Cannot build RR customer payload: lastName or companyName is required (no ownr_ln / ownr_co_nm on job)." ); } const payload = { ibFlag, // 'I' or 'B' firstName: firstName || undefined, lastName: lastName || undefined, customerName: companyName || undefined, createdBy: overrides.createdBy || "ImEX Online", customerType: overrides.customerType || "R", // Retail default addresses, phones, emails }; Object.keys(payload).forEach((k) => payload[k] === undefined && delete payload[k]); return payload; } /** * Create a customer in RR and return { customerNo, raw }. * Maps data.dmsRecKey -> customerNo for compatibility with existing callers. */ async function createRRCustomer({ bodyshop, job, overrides = {}, socket }) { const log = RRLogger(socket, { ns: "rr" }); const { client, opts } = buildClientAndOpts(bodyshop); const payload = buildCustomerPayloadFromJob(job, overrides); let res; try { res = await client.insertCustomer(payload, opts); } catch (e) { log("error", "RR insertCustomer transport error", { message: e?.message, stack: e?.stack, payload }); throw e; } const data = res?.data ?? res; const trx = res?.statusBlocks?.transaction; let customerNo = data?.dmsRecKey; if (!customerNo) { log("error", "RR insertCustomer returned no dmsRecKey/custNo", { status: trx?.status, statusCode: trx?.statusCode, message: trx?.message, data }); throw new Error( `RR insertCustomer returned no dmsRecKey (status=${trx?.status ?? "?"} code=${trx?.statusCode ?? "?"}${ trx?.message ? ` msg=${trx.message}` : "" })` ); } return { customerNo: String(customerNo), raw: data }; } module.exports = { createRRCustomer };