feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Refresh button inside VIN Enforced, add TOo Many OPen RO Handlers

This commit is contained in:
Dave
2025-11-12 12:56:34 -05:00
parent cbfda822c6
commit e3b4620d0c
2 changed files with 91 additions and 23 deletions

View File

@@ -58,12 +58,13 @@ function rrAddressToString(addr) {
return parts.join(", ");
}
export function DmsCustomerSelector({ bodyshop, jobid }) {
export function DmsCustomerSelector({ bodyshop, jobid, rrOpenRoLimit = false, onRrOpenRoFinished }) {
const { t } = useTranslation();
const [customerList, setcustomerList] = useState([]);
const [open, setOpen] = useState(false);
const [selectedCustomer, setSelectedCustomer] = useState(null);
const [dmsType, setDmsType] = useState("cdk");
const [refreshing, setRefreshing] = useState(false);
const {
treatments: { Fortellis }
@@ -95,6 +96,7 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
setcustomerList(normalized);
const firstOwner = normalized.find((r) => r.vinOwner)?.custNo;
setSelectedCustomer(firstOwner ? String(firstOwner) : null);
setRefreshing(false); // stop any in-flight refresh spinner
};
wsssocket.on("rr-select-customer", handleRrSelectCustomer);
@@ -183,7 +185,6 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
const generic = bodyshop.cdk_configuration?.generic_customer_number || null;
if (dmsType === "rr") {
// Not rendered in RR anymore
return;
} else if (Fortellis.treatment === "on") {
setOpen(false);
@@ -220,7 +221,30 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
setSelectedCustomer(null);
};
// ---------- Columns ----------
// NEW: trigger a re-run of the RR combined search
const refreshRrSearch = () => {
if (dmsType !== "rr") return;
setRefreshing(true);
// Safety timeout so the spinner can't hang forever
const to = setTimeout(() => {
setRefreshing(false);
}, 12000);
// Stop spinner on either outcome
const stop = () => {
clearTimeout(to);
setRefreshing(false);
wsssocket.off("export-failed", stop);
wsssocket.off("rr-select-customer", stop);
};
wsssocket.once("rr-select-customer", stop);
wsssocket.once("export-failed", stop);
// This re-runs the name+VIN multi-search and emits rr-select-customer
wsssocket.emit("rr-export-job", { jobId: jobid });
};
const fortellisColumns = [
{ title: t("jobs.fields.dms.id"), dataIndex: "customerId", key: "id" },
{
@@ -342,8 +366,30 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
<Table
title={() => (
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
{/* Open RO limit banner (from parent flag) */}
{dmsType === "rr" && rrOpenRoLimit && (
<Alert
type="error"
showIcon
message="Open RO limit reached in Reynolds"
description={
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<div>
Reynolds has reached the maximum number of open Repair Orders for this Customer. Close or finalize
an RO in Reynolds, then click <strong>Finished</strong> to continue.
</div>
<div>
<Button type="primary" danger onClick={onRrOpenRoFinished}>
Finished
</Button>
</div>
</div>
}
/>
)}
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button onClick={onUseSelected} disabled={!selectedCustomer}>
<Button onClick={onUseSelected} disabled={!selectedCustomer || (dmsType === "rr" && rrOpenRoLimit)}>
{t("jobs.actions.dms.useselected")}
</Button>
@@ -359,12 +405,24 @@ export function DmsCustomerSelector({ bodyshop, jobid }) {
</Button>
</div>
{/* NEW: VIN ownership enforced with Refresh */}
{dmsType === "rr" && rrHasVinOwner && (
<Alert
type="warning"
showIcon
message="VIN ownership enforced"
description="This VIN is already assigned in Reynolds. Only the VIN owner is selectable here. To use a different customer, please change the vehicle ownership in Reynolds first, then return to complete the export."
description={
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12 }}>
<div>
This VIN is already assigned in Reynolds. Only the VIN owner is selectable here. To use a
different customer, please change the vehicle ownership in Reynolds first, then return to complete
the export.
</div>
<Button onClick={refreshRrSearch} loading={refreshing}>
Refresh
</Button>
</div>
}
/>
)}
</div>