feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Checkpoint
This commit is contained in:
@@ -32,6 +32,22 @@ function getDSB(cfg) {
|
||||
return { dealerNumber, storeNumber, branchNumber };
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize an address-like object to the template's <Address> block.
|
||||
*/
|
||||
function mapAddress(addr) {
|
||||
if (!addr) return undefined;
|
||||
const out = {
|
||||
Line1: addr.line1,
|
||||
Line2: addr.line2,
|
||||
City: addr.city,
|
||||
State: addr.state,
|
||||
PostalCode: addr.postal_code || addr.postalCode,
|
||||
Country: addr.country
|
||||
};
|
||||
return hasAny(out) ? out : undefined;
|
||||
}
|
||||
|
||||
//
|
||||
// ===================== CUSTOMER =====================
|
||||
//
|
||||
@@ -39,71 +55,36 @@ function getDSB(cfg) {
|
||||
/**
|
||||
* Map internal customer record to Rome CustomerInsertRq.
|
||||
*/
|
||||
function mapCustomerInsert(customer, bodyshopConfig) {
|
||||
if (!customer) return {};
|
||||
const { dealerNumber, storeNumber, branchNumber } = getDSB(bodyshopConfig);
|
||||
|
||||
function mapCustomerInsert(src) {
|
||||
const name = src.company_name?.trim() || [src.first_name, src.last_name].filter(Boolean).join(" ").trim();
|
||||
return {
|
||||
DealerCode: bodyshopConfig?.dealer_code || "ROME",
|
||||
DealerNumber: dealerNumber,
|
||||
StoreNumber: storeNumber,
|
||||
BranchNumber: branchNumber,
|
||||
RequestId: `CUST-INSERT-${customer.id}`,
|
||||
Environment: process.env.NODE_ENV,
|
||||
|
||||
CustomerId: customer.external_id || undefined,
|
||||
CustomerType: customer.type || "RETAIL",
|
||||
CompanyName: customer.company_name,
|
||||
FirstName: customer.first_name,
|
||||
MiddleName: customer.middle_name,
|
||||
LastName: customer.last_name,
|
||||
PreferredName: customer.display_name || customer.first_name,
|
||||
ActiveFlag: customer.active ? "true" : "false",
|
||||
|
||||
CustomerGroup: customer.group_name,
|
||||
TaxExempt: customer.tax_exempt ? "true" : "false",
|
||||
DiscountLevel: num(customer.discount_level),
|
||||
PreferredLanguage: customer.language || "EN",
|
||||
|
||||
Addresses: (customer.addresses || []).map((a) => ({
|
||||
AddressType: a.type || "BILLING",
|
||||
AddressLine1: a.line1,
|
||||
AddressLine2: a.line2,
|
||||
CustomerNumber: src.external_id, // optional
|
||||
CustomerType: src.type === "BUSINESS" ? "BUSINESS" : "RETAIL",
|
||||
CustomerName: name,
|
||||
DisplayName: src.display_name || name,
|
||||
Language: src.language || "EN",
|
||||
TaxExempt: src.tax_exempt ? "Y" : "N",
|
||||
Active: src.active ? "Y" : "N",
|
||||
Addresses: (src.addresses || []).map((a) => ({
|
||||
Type: a.type || "P",
|
||||
Line1: a.line1,
|
||||
Line2: a.line2,
|
||||
City: a.city,
|
||||
State: a.state,
|
||||
PostalCode: a.postal_code,
|
||||
Country: a.country || "US"
|
||||
Country: a.country
|
||||
})),
|
||||
|
||||
Phones: (customer.phones || []).map((p) => ({
|
||||
PhoneNumber: p.number,
|
||||
PhoneType: p.type || "MOBILE",
|
||||
Preferred: p.preferred ? "true" : "false"
|
||||
Phones: (src.phones || []).map((p) => ({
|
||||
Type: p.type || "H",
|
||||
Number: p.number,
|
||||
Extension: p.extension,
|
||||
Preferred: p.preferred ? "Y" : "N"
|
||||
})),
|
||||
|
||||
Emails: (customer.emails || []).map((e) => ({
|
||||
EmailAddress: e.address,
|
||||
EmailType: e.type || "WORK",
|
||||
Preferred: e.preferred ? "true" : "false"
|
||||
})),
|
||||
|
||||
Insurance: customer.insurance
|
||||
? {
|
||||
CompanyName: customer.insurance.company,
|
||||
PolicyNumber: customer.insurance.policy,
|
||||
ExpirationDate: formatDate(customer.insurance.expiration_date),
|
||||
ContactName: customer.insurance.contact_name,
|
||||
ContactPhone: customer.insurance.contact_phone
|
||||
}
|
||||
: undefined,
|
||||
|
||||
LinkedAccounts: (customer.linked_accounts || []).map((a) => ({
|
||||
Type: a.type,
|
||||
AccountNumber: a.account_number,
|
||||
CreditLimit: num(a.credit_limit)
|
||||
})),
|
||||
|
||||
Notes: customer.notes?.length ? { Items: customer.notes.map((n) => n.text || n) } : undefined
|
||||
Emails: (src.emails || []).map((e) => ({
|
||||
Type: e.type || "W",
|
||||
Address: e.address,
|
||||
Preferred: e.preferred ? "Y" : "N"
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -184,6 +165,8 @@ function mapServiceVehicle(vehicle, ownerCustomer, bodyshopConfig) {
|
||||
|
||||
/**
|
||||
* Map internal job to Rome RepairOrderInsertRq.
|
||||
* NOTE: The CreateRepairOrder.xml template expects *flat* fields for Customer and ServiceVehicle
|
||||
* (no {{#Customer}} or {{#ServiceVehicle}} sections). Therefore, we flatten those values here.
|
||||
*/
|
||||
function mapRepairOrderCreate(job, bodyshopConfig) {
|
||||
if (!job) return {};
|
||||
@@ -192,7 +175,11 @@ function mapRepairOrderCreate(job, bodyshopConfig) {
|
||||
const cust = job.customer || {};
|
||||
const veh = job.vehicle || {};
|
||||
|
||||
// Prefer a concrete address on the customer, fall back to job-level
|
||||
const customerAddress = cust.address || job.customer_address || job.address || undefined;
|
||||
|
||||
return {
|
||||
// Routing/meta we keep available for logging or other templates
|
||||
DealerCode: bodyshopConfig?.dealer_code || "ROME",
|
||||
DealerNumber: dealerNumber,
|
||||
StoreNumber: storeNumber,
|
||||
@@ -200,6 +187,7 @@ function mapRepairOrderCreate(job, bodyshopConfig) {
|
||||
RequestId: `RO-${job.id}`,
|
||||
Environment: process.env.NODE_ENV,
|
||||
|
||||
// Header fields
|
||||
RepairOrderNumber: job.ro_number,
|
||||
DmsRepairOrderId: job.external_id,
|
||||
|
||||
@@ -215,26 +203,26 @@ function mapRepairOrderCreate(job, bodyshopConfig) {
|
||||
ROType: job.ro_type,
|
||||
Status: job.status,
|
||||
IsBodyShop: "true",
|
||||
DRPFlag: job.drp_flag ? "true" : "false",
|
||||
DRPFlag: toBoolStr(!!job.drp_flag) || "false",
|
||||
|
||||
Customer: {
|
||||
CustomerId: cust.external_id,
|
||||
CustomerName: cust.full_name,
|
||||
PhoneNumber: cust.phone,
|
||||
EmailAddress: cust.email
|
||||
},
|
||||
// Customer block is FLAT (template does not use {{#Customer}} section)
|
||||
CustomerId: cust.external_id,
|
||||
CustomerName: cust.full_name || [cust.first_name, cust.last_name].filter(Boolean).join(" ").trim() || undefined,
|
||||
PhoneNumber: cust.phone,
|
||||
EmailAddress: cust.email,
|
||||
Address: mapAddress(customerAddress),
|
||||
|
||||
Vehicle: {
|
||||
VehicleId: veh.external_id,
|
||||
VIN: veh.vin,
|
||||
LicensePlate: veh.license_plate,
|
||||
Year: num(veh.year),
|
||||
Make: veh.make,
|
||||
Model: veh.model,
|
||||
Odometer: num(veh.odometer),
|
||||
Color: veh.color
|
||||
},
|
||||
// ServiceVehicle block is FLAT (template does not use {{#ServiceVehicle}} section)
|
||||
VehicleId: veh.external_id,
|
||||
VIN: veh.vin,
|
||||
LicensePlate: veh.license_plate,
|
||||
Year: num(veh.year),
|
||||
Make: veh.make,
|
||||
Model: veh.model,
|
||||
Odometer: num(veh.odometer),
|
||||
Color: veh.color,
|
||||
|
||||
// Lines
|
||||
JobLines: (job.joblines || []).map((l, i) => ({
|
||||
Sequence: i + 1,
|
||||
ParentSequence: l.parent_sequence,
|
||||
@@ -264,16 +252,28 @@ function mapRepairOrderCreate(job, bodyshopConfig) {
|
||||
: undefined
|
||||
})),
|
||||
|
||||
Totals: {
|
||||
// Totals
|
||||
Totals: hasAny({
|
||||
Currency: job.currency || "CAD",
|
||||
LaborTotal: num(job.totals?.labor),
|
||||
PartsTotal: num(job.totals?.parts),
|
||||
MiscTotal: num(job.totals?.misc),
|
||||
DiscountTotal: num(job.totals?.discount),
|
||||
TaxTotal: num(job.totals?.tax),
|
||||
GrandTotal: num(job.totals?.grand)
|
||||
},
|
||||
LaborTotal: job.totals?.labor,
|
||||
PartsTotal: job.totals?.parts,
|
||||
MiscTotal: job.totals?.misc,
|
||||
DiscountTotal: job.totals?.discount,
|
||||
TaxTotal: job.totals?.tax,
|
||||
GrandTotal: job.totals?.grand
|
||||
})
|
||||
? {
|
||||
Currency: job.currency || "CAD",
|
||||
LaborTotal: num(job.totals?.labor),
|
||||
PartsTotal: num(job.totals?.parts),
|
||||
MiscTotal: num(job.totals?.misc),
|
||||
DiscountTotal: num(job.totals?.discount),
|
||||
TaxTotal: num(job.totals?.tax),
|
||||
GrandTotal: num(job.totals?.grand)
|
||||
}
|
||||
: undefined,
|
||||
|
||||
// Payments
|
||||
Payments: job.payments?.length
|
||||
? {
|
||||
Items: job.payments.map((p) => ({
|
||||
@@ -287,6 +287,7 @@ function mapRepairOrderCreate(job, bodyshopConfig) {
|
||||
}
|
||||
: undefined,
|
||||
|
||||
// Insurance
|
||||
Insurance: job.insurance
|
||||
? {
|
||||
CompanyName: job.insurance.company,
|
||||
@@ -296,6 +297,7 @@ function mapRepairOrderCreate(job, bodyshopConfig) {
|
||||
}
|
||||
: undefined,
|
||||
|
||||
// Notes
|
||||
Notes: job.notes?.length ? { Items: job.notes.map((n) => n.text || n) } : undefined
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user