feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration / RRScratch2 / Math Adjustments / DMS State cleaning on Page load
This commit is contained in:
@@ -142,6 +142,41 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
|||||||
isConnected ? "Connected" : "Disconnected"
|
isConnected ? "Connected" : "Disconnected"
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
const resetKey = useMemo(() => `${mode || "none"}-${jobId || "none"}`, [mode, jobId]);
|
||||||
|
|
||||||
|
// 🔄 Hard reset of local + server-side DMS context when the page/job loads
|
||||||
|
useEffect(() => {
|
||||||
|
// Clear any local ephemeral state that might be stale
|
||||||
|
setLogs([]);
|
||||||
|
setRrOpenRoLimit(false);
|
||||||
|
setrrValidationPending(false);
|
||||||
|
|
||||||
|
if (!activeSocket) return;
|
||||||
|
|
||||||
|
const emitReset = () => {
|
||||||
|
// Generic reset; server can branch on `mode` if needed
|
||||||
|
activeSocket.emit("dms-reset-context", { jobId, mode });
|
||||||
|
};
|
||||||
|
|
||||||
|
if (activeSocket.connected) {
|
||||||
|
// WSS usually lands here
|
||||||
|
emitReset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy WS: wait for the connect before emitting reset
|
||||||
|
const handleConnectOnce = () => {
|
||||||
|
emitReset();
|
||||||
|
activeSocket.off("connect", handleConnectOnce);
|
||||||
|
};
|
||||||
|
|
||||||
|
activeSocket.on("connect", handleConnectOnce);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
activeSocket.off("connect", handleConnectOnce);
|
||||||
|
};
|
||||||
|
}, [jobId, mode, activeSocket]);
|
||||||
|
|
||||||
const handleExportFailed = (payload = {}) => {
|
const handleExportFailed = (payload = {}) => {
|
||||||
const { title, friendlyMessage, error: errText, severity, errorCode, vendorStatusCode } = payload;
|
const { title, friendlyMessage, error: errText, severity, errorCode, vendorStatusCode } = payload;
|
||||||
|
|
||||||
@@ -355,6 +390,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
|||||||
<Col md={24} lg={10}>
|
<Col md={24} lg={10}>
|
||||||
{!isRrMode ? (
|
{!isRrMode ? (
|
||||||
<DmsAllocationsSummary
|
<DmsAllocationsSummary
|
||||||
|
key={resetKey}
|
||||||
title={
|
title={
|
||||||
<span>
|
<span>
|
||||||
<Link
|
<Link
|
||||||
@@ -371,6 +407,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<RrAllocationsSummary
|
<RrAllocationsSummary
|
||||||
|
key={resetKey}
|
||||||
title={
|
title={
|
||||||
<span>
|
<span>
|
||||||
<Link to={`/manage/jobs/${data && data.jobs_by_pk.id}`}>
|
<Link to={`/manage/jobs/${data && data.jobs_by_pk.id}`}>
|
||||||
@@ -388,7 +425,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
|||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col md={24} lg={14}>
|
<Col md={24} lg={14}>
|
||||||
<DmsPostForm socket={activeSocket} job={data?.jobs_by_pk} logsRef={logsRef} mode={mode} />
|
<DmsPostForm key={resetKey} socket={activeSocket} job={data?.jobs_by_pk} logsRef={logsRef} mode={mode} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<DmsCustomerSelector
|
<DmsCustomerSelector
|
||||||
|
|||||||
@@ -584,19 +584,22 @@ function applyRomeProfileAdjustments({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Labor / materials adjustments
|
// Labor / materials adjustments (match CDK semantics: check `adjustment`, add `adjustments`)
|
||||||
Object.keys(rateMap).forEach((key) => {
|
Object.keys(rateMap).forEach((key) => {
|
||||||
const rate = rateMap[key];
|
const rate = rateMap[key];
|
||||||
if (!rate || !rate.adjustment) return;
|
if (!rate || !rate.adjustment) return;
|
||||||
|
|
||||||
const adjMoney = Dinero(rate.adjustment);
|
const checkMoney = Dinero(rate.adjustment);
|
||||||
if (adjMoney.isZero()) return;
|
if (checkMoney.isZero()) return;
|
||||||
|
|
||||||
const accountName = selectedDmsAllocationConfig.profits[key.toUpperCase()];
|
const accountName = selectedDmsAllocationConfig.profits[key.toUpperCase()];
|
||||||
const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName);
|
const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName);
|
||||||
|
|
||||||
if (otherAccount) {
|
if (otherAccount) {
|
||||||
const bucket = ensureCenterBucket(profitCenterHash, accountName);
|
const bucket = ensureCenterBucket(profitCenterHash, accountName);
|
||||||
|
|
||||||
|
// Note: we intentionally use `rate.adjustments` here to mirror CDK behaviour
|
||||||
|
const adjMoney = Dinero(rate.adjustments);
|
||||||
bucket.extrasSale = bucket.extrasSale.add(adjMoney);
|
bucket.extrasSale = bucket.extrasSale.add(adjMoney);
|
||||||
|
|
||||||
debugLog("Added rate adjustment", {
|
debugLog("Added rate adjustment", {
|
||||||
|
|||||||
@@ -67,6 +67,34 @@ const redisSocketEvents = ({ io, redisHelpers, ioHelpers, logger }) => {
|
|||||||
|
|
||||||
// Register Socket Events
|
// Register Socket Events
|
||||||
const registerSocketEvents = (socket) => {
|
const registerSocketEvents = (socket) => {
|
||||||
|
// DMS reset events (clear per-socket DMS transactional cache)
|
||||||
|
const registerDmsResetEvents = (socket) => {
|
||||||
|
socket.on("dms-reset-context", async ({ jobId, mode } = {}, ack) => {
|
||||||
|
try {
|
||||||
|
// This clears all transactional session data for this socket
|
||||||
|
// (RR txEnvelope/JobData/SelectedCustomer/PendingRO/etc, Fortellis, etc.)
|
||||||
|
await clearSessionTransactionData(socket.id);
|
||||||
|
|
||||||
|
createLogEvent(
|
||||||
|
socket,
|
||||||
|
"debug",
|
||||||
|
`DMS reset-context: cleared transactional session data` +
|
||||||
|
(jobId ? ` (jobId=${jobId})` : "") +
|
||||||
|
(mode ? ` (mode=${mode})` : "")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (typeof ack === "function") {
|
||||||
|
ack({ ok: true });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
createLogEvent(socket, "error", `DMS reset-context failed: ${error.message}`);
|
||||||
|
if (typeof ack === "function") {
|
||||||
|
ack({ ok: false, error: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Token Update Events
|
// Token Update Events
|
||||||
const registerUpdateEvents = (socket) => {
|
const registerUpdateEvents = (socket) => {
|
||||||
let latestTokenTimestamp = 0;
|
let latestTokenTimestamp = 0;
|
||||||
@@ -164,7 +192,9 @@ const redisSocketEvents = ({ io, redisHelpers, ioHelpers, logger }) => {
|
|||||||
// Optional: clear transactional session
|
// Optional: clear transactional session
|
||||||
try {
|
try {
|
||||||
await clearSessionTransactionData(socket.id);
|
await clearSessionTransactionData(socket.id);
|
||||||
} catch {}
|
} catch {
|
||||||
|
//
|
||||||
|
}
|
||||||
// Leave all rooms except the default room (socket.id)
|
// Leave all rooms except the default room (socket.id)
|
||||||
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
|
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
|
||||||
for (const room of rooms) {
|
for (const room of rooms) {
|
||||||
@@ -363,6 +393,7 @@ const redisSocketEvents = ({ io, redisHelpers, ioHelpers, logger }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Call Handlers
|
// Call Handlers
|
||||||
|
registerDmsResetEvents(socket);
|
||||||
registerRoomAndBroadcastEvents(socket);
|
registerRoomAndBroadcastEvents(socket);
|
||||||
registerUpdateEvents(socket);
|
registerUpdateEvents(socket);
|
||||||
registerMessagingEvents(socket);
|
registerMessagingEvents(socket);
|
||||||
|
|||||||
@@ -115,6 +115,33 @@ function SetLegacyWebsocketHandlers(io) {
|
|||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
createLogEvent(socket, "DEBUG", `User disconnected.`);
|
createLogEvent(socket, "DEBUG", `User disconnected.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// DMS reset for legacy WS (CDK / PBS)
|
||||||
|
socket.on("dms-reset-context", ({ jobId, mode } = {}, ack) => {
|
||||||
|
try {
|
||||||
|
// Clear any per-socket DMS state that can leak across jobs
|
||||||
|
socket.selectedCustomerId = null; // CDK / PBS AR
|
||||||
|
socket.txEnvelope = null; // PBS AP export
|
||||||
|
socket.apAllocations = null; // PBS AP allocations
|
||||||
|
|
||||||
|
createLogEvent(
|
||||||
|
socket,
|
||||||
|
"DEBUG",
|
||||||
|
`DMS reset-context (legacy WS): cleared per-socket state` +
|
||||||
|
(jobId ? ` (jobId=${jobId})` : "") +
|
||||||
|
(mode ? ` (mode=${mode})` : "")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (typeof ack === "function") {
|
||||||
|
ack({ ok: true });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
createLogEvent(socket, "ERROR", `DMS reset-context (legacy WS) failed: ${error.message}`);
|
||||||
|
if (typeof ack === "function") {
|
||||||
|
ack({ ok: false, error: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user