feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Checkpoint

This commit is contained in:
Dave
2025-11-04 15:18:03 -05:00
parent 5bbda89fb9
commit aa692d4d05

View File

@@ -1,5 +1,5 @@
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Button, Checkbox, Col, Form, Input, message, Modal, Table } from "antd";
import { Button, Checkbox, Col, message, Table } from "antd";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -17,7 +17,6 @@ const mapDispatchToProps = () => ({});
export default connect(mapStateToProps, mapDispatchToProps)(DmsCustomerSelector);
// ---------------- Helpers ----------------
function normalizeRrList(list) {
if (!Array.isArray(list)) return [];
return list
@@ -38,8 +37,6 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
const [open, setOpen] = useState(false);
const [selectedCustomer, setSelectedCustomer] = useState(null);
const [dmsType, setDmsType] = useState("cdk");
const [openCreate, setOpenCreate] = useState(false);
const [createForm] = Form.useForm();
const {
treatments: { Fortellis }
@@ -50,45 +47,21 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
});
const { socket: wsssocket } = useSocket();
const dms = useMemo(() => determineDmsType(bodyshop), [bodyshop]);
const bodyshopId = bodyshop?.id || bodyshop?.bodyshopid || bodyshop?.uuid;
useEffect(() => {
// RR takes precedence over Fortellis
// RR takes precedence
if (dms === "rr") {
const handleRrSelectCustomer = (list) => {
setOpen(true);
setDmsType("rr");
// Normalize to { custNo, name }
setcustomerList(normalizeRrList(list));
setSelectedCustomer(null);
};
const handleRrCreateRequired = () => {
setOpen(true);
setDmsType("rr");
setcustomerList([]);
setOpenCreate(true);
};
const handleRrCustomerCreated = ({ custNo }) => {
if (custNo) {
message.success(t("dms.messages.customerCreated"));
setSelectedCustomer(String(custNo));
setOpenCreate(false);
setOpen(false);
}
};
wsssocket.on("rr-select-customer", handleRrSelectCustomer);
wsssocket.on("rr-customer-create-required", handleRrCreateRequired);
wsssocket.on("rr-customer-created", handleRrCustomerCreated);
return () => {
wsssocket.off("rr-select-customer", handleRrSelectCustomer);
wsssocket.off("rr-customer-create-required", handleRrCreateRequired);
wsssocket.off("rr-customer-created", handleRrCustomerCreated);
};
}
@@ -132,14 +105,18 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
}
if (dmsType === "rr") {
// RR now behaves like others: use the selected row and close
wsssocket.emit("rr-selected-customer", { bodyshopId, custNo: String(selectedCustomer), jobId: jobid });
setOpen(false);
setSelectedCustomer(null);
// RR now mirrors others: send selection and close
wsssocket.emit("rr-selected-customer", { jobId: jobid, custNo: String(selectedCustomer) }, (ack) => {
if (ack?.ok) {
setOpen(false);
setSelectedCustomer(null);
} else if (ack?.error) {
message.error(ack.error);
}
});
return;
}
// Non-RR behavior unchanged:
setOpen(false);
if (Fortellis.treatment === "on") {
wsssocket.emit("fortellis-selected-customer", { selectedCustomerId: selectedCustomer, jobid });
@@ -150,28 +127,41 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
};
const onUseGeneric = () => {
setOpen(false);
const generic = bodyshop.cdk_configuration?.generic_customer_number || null;
if (dmsType === "rr") {
if (generic) {
wsssocket.emit("rr-selected-customer", { bodyshopId, custNo: String(generic), jobId: jobid });
wsssocket.emit("rr-selected-customer", { jobId: jobid, custNo: String(generic) }, (ack) => {
if (!ack?.ok && ack?.error) message.error(ack.error);
});
}
setOpen(false);
} else if (Fortellis.treatment === "on") {
setOpen(false);
wsssocket.emit("fortellis-selected-customer", { selectedCustomerId: generic, jobid });
} else {
setOpen(false);
socket.emit(`${dmsType}-selected-customer`, generic);
}
setSelectedCustomer(null);
};
const onCreateNew = () => {
// Exact parity with Fortellis: ask server to create immediately
if (dmsType === "rr") {
// RR: open inline creation modal (same as before)
setOpen(true);
setOpenCreate(true);
wsssocket.emit("rr-selected-customer", { jobId: jobid, create: true }, (ack) => {
if (ack?.ok) {
// Optionally preselect returned custNo
if (ack.custNo) setSelectedCustomer(String(ack.custNo));
setOpen(false);
message.success(t("dms.messages.customerCreated"));
} else if (ack?.error) {
message.error(ack.error);
}
});
return;
}
// Non-RR stays unchanged
// Non-RR unchanged
setOpen(false);
if (Fortellis.treatment === "on") {
wsssocket.emit("fortellis-selected-customer", { selectedCustomerId: null, jobid });
@@ -182,14 +172,13 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
};
// ---------- Columns ----------
const fortellisColumns = [
{ title: t("jobs.fields.dms.id"), dataIndex: "customerId", key: "id" },
{
title: t("jobs.fields.dms.vinowner"),
dataIndex: "vinOwner",
key: "vinOwner",
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />
render: (_t, r) => <Checkbox disabled checked={r.vinOwner} />
},
{
title: t("jobs.fields.dms.name1"),
@@ -221,7 +210,7 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
title: t("jobs.fields.dms.vinowner"),
dataIndex: "vinOwner",
key: "vinOwner",
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />
render: (_t, r) => <Checkbox disabled checked={r.vinOwner} />
},
{
title: t("jobs.fields.dms.name1"),
@@ -245,16 +234,15 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
title: t("jobs.fields.dms.name1"),
key: "name1",
sorter: (a, b) => alphaSort(a.LastName, b.LastName),
render: (text, record) => `${record.FirstName || ""} ${record.LastName || ""}`
render: (_t, r) => `${r.FirstName || ""} ${r.LastName || ""}`
},
{
title: t("jobs.fields.dms.address"),
key: "address",
render: (record) => `${record.Address}, ${record.City} ${record.State} ${record.ZipCode}`
render: (r) => `${r.Address}, ${r.City} ${r.State} ${r.ZipCode}`
}
];
// RR is normalized to { custNo, name }
const rrColumns = [
{ title: t("jobs.fields.dms.id"), dataIndex: "custNo", key: "custNo" },
{ title: t("jobs.fields.dms.name1"), dataIndex: "name", key: "name", sorter: (a, b) => alphaSort(a?.name, b?.name) }
@@ -310,67 +298,6 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
selectedRowKeys: selectedCustomer ? [selectedCustomer] : []
}}
/>
{/* RR inline creation modal (unchanged) */}
<Modal
open={openCreate}
title={t("jobs.actions.dms.createnewcustomer")}
onCancel={() => setOpenCreate(false)}
onOk={() => createForm.submit()}
destroyOnClose
>
<Form
form={createForm}
layout="vertical"
onFinish={(values) => {
const fields = {
FirstName: values.FirstName,
LastName: values.LastName,
CompanyName: values.CompanyName,
Phone: values.Phone,
AddressLine1: values.AddressLine1,
City: values.City,
StateProvince: values.StateProvince,
PostalCode: values.PostalCode
};
wsssocket.emit("rr-create-customer", { jobId: jobid, fields }, (ack) => {
if (ack?.ok) {
message.success(t("dms.messages.customerCreated"));
setSelectedCustomer(ack.custNo ? String(ack.custNo) : null);
setOpenCreate(false);
setOpen(false);
} else {
message.error(ack?.error || t("general.errors.unknown"));
}
});
}}
>
<Form.Item name="FirstName" label={t("jobs.fields.firstName")}>
<Input />
</Form.Item>
<Form.Item name="LastName" label={t("jobs.fields.lastName")} rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="CompanyName" label={t("jobs.fields.companyName")}>
<Input />
</Form.Item>
<Form.Item name="Phone" label={t("jobs.fields.phone")}>
<Input />
</Form.Item>
<Form.Item name="AddressLine1" label={t("jobs.fields.address")}>
<Input />
</Form.Item>
<Form.Item name="City" label={t("jobs.fields.city")}>
<Input />
</Form.Item>
<Form.Item name="StateProvince" label={t("jobs.fields.state")}>
<Input />
</Form.Item>
<Form.Item name="PostalCode" label={t("jobs.fields.postalCode")}>
<Input />
</Form.Item>
</Form>
</Modal>
</Col>
);
}