Files
bodyshop/server/rr/rr-customers.js

147 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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 librarys 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
};