feature/IO-2742-redis - Checkpoint, Redis fully implemented.
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -214,7 +214,9 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline
|
||||
path="/tech/*"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute isAuthorized={currentUser.authorized} />
|
||||
<SocketProvider bodyshop={bodyshop}>
|
||||
<PrivateRoute isAuthorized={currentUser.authorized} />
|
||||
</SocketProvider>
|
||||
</ErrorBoundary>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,62 +1,77 @@
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import { Button, Card, Form, Input, Table } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect, useState, useContext } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { pageLimit } from "../../utils/config";
|
||||
import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; // Import SocketContext
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(mapStateToProps)(DmsAllocationsSummaryAp);
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DmsAllocationsSummaryAp);
|
||||
|
||||
export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
|
||||
export function DmsAllocationsSummaryAp({ bodyshop, billids, title }) {
|
||||
const { t } = useTranslation();
|
||||
const [allocationsSummary, setAllocationsSummary] = useState([]);
|
||||
const { socket } = useContext(SocketContext);
|
||||
|
||||
useEffect(() => {
|
||||
socket.on("ap-export-success", (billid) => {
|
||||
if (!socket) return;
|
||||
|
||||
const handleSuccess = async (billid) => {
|
||||
setAllocationsSummary((allocationsSummary) =>
|
||||
allocationsSummary.map((a) => {
|
||||
if (a.billid !== billid) return a;
|
||||
return { ...a, status: "Successful" };
|
||||
})
|
||||
);
|
||||
});
|
||||
socket.on("ap-export-failure", ({ billid, error }) => {
|
||||
allocationsSummary.map((a) => {
|
||||
if (a.billid !== billid) return a;
|
||||
return { ...a, status: error };
|
||||
});
|
||||
});
|
||||
|
||||
if (socket.disconnected) socket.connect();
|
||||
return () => {
|
||||
socket.removeListener("ap-export-success");
|
||||
socket.removeListener("ap-export-failure");
|
||||
//socket.disconnect();
|
||||
try {
|
||||
await new Promise((resolve, reject) => {
|
||||
socket.emit("clear-dms-session", (response) => {
|
||||
if (response && response.status === "ok") {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error("Failed to clear DMS session"));
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to clear DMS session", error);
|
||||
}
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const handleFailure = ({ billid, error }) => {
|
||||
setAllocationsSummary((allocationsSummary) =>
|
||||
allocationsSummary.map((a) => {
|
||||
if (a.billid !== billid) return a;
|
||||
return { ...a, status: error };
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
socket.on("ap-export-success", handleSuccess);
|
||||
socket.on("ap-export-failure", handleFailure);
|
||||
|
||||
return () => {
|
||||
socket.off("ap-export-success", handleSuccess);
|
||||
socket.off("ap-export-failure", handleFailure);
|
||||
};
|
||||
}, [socket]);
|
||||
|
||||
useEffect(() => {
|
||||
if (socket.connected) {
|
||||
if (socket && socket.connected) {
|
||||
socket.emit("pbs-calculate-allocations-ap", billids, (ack) => {
|
||||
setAllocationsSummary(ack);
|
||||
|
||||
socket.allocationsSummary = ack;
|
||||
});
|
||||
}
|
||||
}, [socket, socket.connected, billids]);
|
||||
console.log(allocationsSummary);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: t("general.labels.status"),
|
||||
@@ -68,35 +83,40 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
|
||||
dataIndex: ["Posting", "Reference"],
|
||||
key: "reference"
|
||||
},
|
||||
|
||||
{
|
||||
title: t("jobs.fields.dms.lines"),
|
||||
dataIndex: "Lines",
|
||||
key: "Lines",
|
||||
render: (text, record) => (
|
||||
<table style={{ tableLayout: "auto", width: "100%" }}>
|
||||
<tr>
|
||||
<th>{t("bills.fields.invoice_number")}</th>
|
||||
<th>{t("bodyshop.fields.dms.dms_acctnumber")}</th>
|
||||
<th>{t("jobs.fields.dms.amount")}</th>
|
||||
</tr>
|
||||
{record.Posting.Lines.map((l, idx) => (
|
||||
<tr key={idx}>
|
||||
<td>{l.InvoiceNumber}</td>
|
||||
<td>{l.Account}</td>
|
||||
<td>{l.Amount}</td>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t("bills.fields.invoice_number")}</th>
|
||||
<th>{t("bodyshop.fields.dms.dms_acctnumber")}</th>
|
||||
<th>{t("jobs.fields.dms.amount")}</th>
|
||||
</tr>
|
||||
))}
|
||||
</thead>
|
||||
<tbody>
|
||||
{record.Posting.Lines.map((l, idx) => (
|
||||
<tr key={idx}>
|
||||
<td>{l.InvoiceNumber}</td>
|
||||
<td>{l.Account}</td>
|
||||
<td>{l.Amount}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
socket.emit(`pbs-export-ap`, {
|
||||
billids,
|
||||
txEnvelope: values
|
||||
});
|
||||
if (socket) {
|
||||
socket.emit("pbs-export-ap", {
|
||||
billids,
|
||||
txEnvelope: values
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -105,7 +125,9 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
|
||||
extra={
|
||||
<Button
|
||||
onClick={() => {
|
||||
socket.emit("pbs-calculate-allocations-ap", billids, (ack) => setAllocationsSummary(ack));
|
||||
if (socket) {
|
||||
socket.emit("pbs-calculate-allocations-ap", billids, (ack) => setAllocationsSummary(ack));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SyncOutlined />
|
||||
@@ -124,12 +146,7 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
|
||||
name="journal"
|
||||
label={t("jobs.fields.dms.journal")}
|
||||
initialValue={bodyshop.cdk_configuration && bodyshop.cdk_configuration.default_journal}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
@@ -4,11 +4,8 @@ import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||
@@ -17,7 +14,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DmsLogEvents);
|
||||
|
||||
export function DmsLogEvents({ socket, logs, bodyshop }) {
|
||||
export function DmsLogEvents({ logs }) {
|
||||
return (
|
||||
<Timeline
|
||||
pending
|
||||
|
||||
@@ -37,6 +37,7 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser }) {
|
||||
onError: (error) => console.error(`Error fetching Kanban settings: ${error.message}`)
|
||||
});
|
||||
|
||||
// This provides us the current version of the Lanes from the Redux store
|
||||
// const currentReducerData = useSelector((state) => (state.trello.lanes ? state.trello : {}));
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button, Card, Col, notification, Row, Select, Space } from "antd";
|
||||
import React, { useEffect, useRef, useState, useContext } from "react";
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
@@ -7,13 +7,10 @@ import { createStructuredSelector } from "reselect";
|
||||
import DmsAllocationsSummaryApComponent from "../../components/dms-allocations-summary-ap/dms-allocations-summary-ap.component";
|
||||
import DmsLogEvents from "../../components/dms-log-events/dms-log-events.component";
|
||||
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import SocketContext from "../../contexts/SocketIO/socketContext";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||
@@ -22,7 +19,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DmsContainer);
|
||||
|
||||
export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
export function DmsContainer({ setBreadcrumbs, setSelectedHeader }) {
|
||||
const { t } = useTranslation();
|
||||
const { socket } = useContext(SocketContext);
|
||||
const [logLevel, setLogLevel] = useState("DEBUG");
|
||||
@@ -124,29 +121,23 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
<Select.Option key="ERROR">ERROR</Select.Option>
|
||||
</Select>
|
||||
<Button onClick={() => setLogs([])}>Clear Logs</Button>
|
||||
{/*<Button*/}
|
||||
{/* onClick={() => {*/}
|
||||
{/* setLogs([]);*/}
|
||||
{/* socket.disconnect();*/}
|
||||
{/* socket.connect();*/}
|
||||
{/* }}*/}
|
||||
{/*>*/}
|
||||
{/* Reconnect*/}
|
||||
{/*</Button>*/}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setLogs([]);
|
||||
if (socket) {
|
||||
socket.emit("clear-dms-session");
|
||||
}
|
||||
}}
|
||||
>
|
||||
Clear Session
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<DmsLogEvents socket={socket} logs={logs} />
|
||||
<DmsLogEvents logs={logs} />
|
||||
</Card>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
export const determineDmsType = (bodyshop) => {
|
||||
if (bodyshop.cdk_dealerid) return "cdk";
|
||||
else {
|
||||
return "pbs";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
||||
setLogs((logs) => [...logs, payload]);
|
||||
};
|
||||
|
||||
const handleExportSuccess = (payload) => {
|
||||
const handleExportSuccess = async (payload) => {
|
||||
notification.success({
|
||||
message: t("jobs.successes.exported")
|
||||
});
|
||||
@@ -113,6 +113,21 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
||||
operation: AuditTrailMapping.jobexported(),
|
||||
type: "jobexported"
|
||||
});
|
||||
|
||||
try {
|
||||
await new Promise((resolve, reject) => {
|
||||
socket.emit("clear-dms-session", (response) => {
|
||||
if (response && response.status === "ok") {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error("Failed to clear DMS session"));
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to clear DMS session", error);
|
||||
}
|
||||
|
||||
history("/manage/accounting/receivables");
|
||||
};
|
||||
|
||||
@@ -186,20 +201,21 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
||||
<Select.Option key="WARNING">WARNING</Select.Option>
|
||||
<Select.Option key="ERROR">ERROR</Select.Option>
|
||||
</Select>
|
||||
<Button onClick={() => setLogs([])}>Clear Logs</Button>
|
||||
{/*<Button*/}
|
||||
{/* onClick={() => {*/}
|
||||
{/* setLogs([]);*/}
|
||||
{/* socket.disconnect();*/}
|
||||
{/* socket.connect();*/}
|
||||
{/* }}*/}
|
||||
{/*>*/}
|
||||
{/* Reconnect*/}
|
||||
{/*</Button>*/}
|
||||
4<Button onClick={() => setLogs([])}>Clear Logs</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setLogs([]);
|
||||
if (socket) {
|
||||
socket.emit("clear-dms-session");
|
||||
}
|
||||
}}
|
||||
>
|
||||
Clear Session
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<DmsLogEvents socket={socket} logs={logs} />
|
||||
<DmsLogEvents logs={logs} />
|
||||
</Card>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
30
server.js
30
server.js
@@ -141,6 +141,36 @@ const main = async () => {
|
||||
|
||||
exports.redisClient = pubClient;
|
||||
|
||||
// Store session data in Redis
|
||||
exports.setSessionData = async (socketId, key, value) => {
|
||||
await pubClient.hSet(`socket:${socketId}`, key, JSON.stringify(value)); // Use Redis pubClient
|
||||
};
|
||||
|
||||
// Retrieve session data from Redis
|
||||
exports.getSessionData = async (socketId, key) => {
|
||||
const data = await pubClient.hGet(`socket:${socketId}`, key);
|
||||
return data ? JSON.parse(data) : null;
|
||||
};
|
||||
|
||||
// Clear session data from Redis
|
||||
exports.clearSessionData = async (socketId) => {
|
||||
await pubClient.del(`socket:${socketId}`);
|
||||
};
|
||||
|
||||
// TODO: Remove, just a demo of hGet and hSet
|
||||
// async function demoSessionData() {
|
||||
// // Store session data using setSessionData
|
||||
// await exports.setSessionData("testSocketId", "field1", "Hello, Redis Hash!");
|
||||
//
|
||||
// // Retrieve session data using getSessionData
|
||||
// const value = await exports.getSessionData("testSocketId", "field1");
|
||||
//
|
||||
// // Output the retrieved value
|
||||
// console.log(value);
|
||||
// }
|
||||
// demoSessionData().catch(console.error);
|
||||
// TODO: End of demo
|
||||
|
||||
require("./server/web-sockets/web-socket");
|
||||
|
||||
applyMiddleware(app);
|
||||
|
||||
@@ -12,67 +12,90 @@ const AxiosLib = require("axios").default;
|
||||
const axios = AxiosLib.create();
|
||||
const { PBS_ENDPOINTS, PBS_CREDENTIALS } = require("./pbs-constants");
|
||||
const { CheckForErrors } = require("./pbs-job-export");
|
||||
const { getSessionData, setSessionData } = require("../../../server");
|
||||
const uuid = require("uuid").v4;
|
||||
axios.interceptors.request.use((x) => {
|
||||
const socket = x.socket;
|
||||
|
||||
const headers = {
|
||||
...x.headers.common,
|
||||
...x.headers[x.method],
|
||||
...x.headers
|
||||
};
|
||||
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
|
||||
x.url
|
||||
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
|
||||
console.log(printable);
|
||||
axios.interceptors.request.use(
|
||||
async (x) => {
|
||||
const socket = x.socket;
|
||||
|
||||
CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data);
|
||||
const headers = {
|
||||
...x.headers.common,
|
||||
...x.headers[x.method],
|
||||
...x.headers
|
||||
};
|
||||
|
||||
return x;
|
||||
});
|
||||
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
|
||||
x.url
|
||||
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
|
||||
|
||||
axios.interceptors.response.use((x) => {
|
||||
const socket = x.config.socket;
|
||||
console.log(printable);
|
||||
|
||||
const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`;
|
||||
console.log(printable);
|
||||
CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data);
|
||||
// Use await properly here for the async operation
|
||||
await CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data);
|
||||
|
||||
return x;
|
||||
});
|
||||
return x; // Return the modified request
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error); // Proper error handling
|
||||
}
|
||||
);
|
||||
|
||||
axios.interceptors.response.use(
|
||||
async (x) => {
|
||||
const socket = x.config.socket;
|
||||
|
||||
const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`;
|
||||
|
||||
console.log(printable);
|
||||
|
||||
// Use await properly here for the async operation
|
||||
await CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data);
|
||||
|
||||
return x; // Return the modified response
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error); // Proper error handling
|
||||
}
|
||||
);
|
||||
|
||||
async function PbsCalculateAllocationsAp(socket, billids) {
|
||||
try {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Received request to calculate allocations for ${billids}`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Received request to calculate allocations for ${billids}`);
|
||||
|
||||
const { bills, bodyshops } = await QueryBillData(socket, billids);
|
||||
const bodyshop = bodyshops[0];
|
||||
socket.bodyshop = bodyshop;
|
||||
socket.bills = bills;
|
||||
|
||||
await setSessionData(socket.id, "bills", bills);
|
||||
await setSessionData(socket.id, "bodyshop", bodyshop);
|
||||
|
||||
const txEnvelope = await getSessionData(socket.id, "txEnvelope");
|
||||
|
||||
//Each bill will enter it's own top level transaction.
|
||||
|
||||
const transactionlist = [];
|
||||
if (bills.length === 0) {
|
||||
CdkBase.createLogEvent(
|
||||
await CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`No bills found for export. Ensure they have not already been exported and try again.`
|
||||
);
|
||||
}
|
||||
|
||||
bills.forEach((bill) => {
|
||||
//Keep the allocations at the bill level.
|
||||
|
||||
const transactionObject = {
|
||||
SerialNumber: socket.bodyshop.pbs_serialnumber,
|
||||
SerialNumber: bodyshop.pbs_serialnumber,
|
||||
billid: bill.id,
|
||||
Posting: {
|
||||
Reference: bill.invoice_number,
|
||||
JournalCode: socket.txEnvelope ? socket.txEnvelope.journal : null,
|
||||
TransactionDate: moment().tz(socket.bodyshop.timezone).toISOString(), //"0001-01-01T00:00:00.0000000Z",
|
||||
//Description: "Bulk AP posting.",
|
||||
//AdditionalInfo: "String",
|
||||
Source: "ImEX Online", //TODO:AIO Resolve this for rome online.
|
||||
Lines: [] //socket.apAllocations,
|
||||
Reference: bill.invoice_number,
|
||||
JournalCode: txEnvelope?.journal,
|
||||
TransactionDate: moment().tz(bodyshop.timezone).toISOString(),
|
||||
Source: "ImEX Online", // TODO: Resolve this for Rome Online.
|
||||
Lines: [] // Will be populated with allocation data,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,13 +140,13 @@ async function PbsCalculateAllocationsAp(socket, billids) {
|
||||
};
|
||||
}
|
||||
|
||||
//Add the line amount.
|
||||
// Add the line amount.
|
||||
billHash[cc.name] = {
|
||||
...billHash[cc.name],
|
||||
Amount: billHash[cc.name].Amount.add(lineDinero)
|
||||
};
|
||||
|
||||
//Does the line have taxes?
|
||||
// Does the line have taxes?
|
||||
if (bl.applicable_taxes.federal) {
|
||||
billHash[bodyshop.md_responsibility_centers.taxes.federal_itc.name] = {
|
||||
...billHash[bodyshop.md_responsibility_centers.taxes.federal_itc.name],
|
||||
@@ -145,7 +168,7 @@ async function PbsCalculateAllocationsAp(socket, billids) {
|
||||
|
||||
let APAmount = Dinero();
|
||||
Object.keys(billHash).map((key) => {
|
||||
if (billHash[key].Amount.getAmount() > 0 || billHash[key].Amount.getAmount() < 0) {
|
||||
if (billHash[key].Amount.getAmount() !== 0) {
|
||||
transactionObject.Posting.Lines.push({
|
||||
...billHash[key],
|
||||
Amount: billHash[key].Amount.toFormat("0.00")
|
||||
@@ -169,19 +192,19 @@ async function PbsCalculateAllocationsAp(socket, billids) {
|
||||
|
||||
return transactionlist;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error encountered in PbsCalculateAllocationsAp. ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error encountered in PbsCalculateAllocationsAp. ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
exports.PbsCalculateAllocationsAp = PbsCalculateAllocationsAp;
|
||||
|
||||
async function QueryBillData(socket, billids) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Querying bill data for id(s) ${billids}`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Querying bill data for id(s) ${billids}`);
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.GET_PBS_AP_ALLOCATIONS, { billids: billids });
|
||||
CdkBase.createLogEvent(socket, "TRACE", `Bill data query result ${JSON.stringify(result, null, 2)}`);
|
||||
await CdkBase.createLogEvent(socket, "TRACE", `Bill data query result ${JSON.stringify(result, null, 2)}`);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -196,40 +219,50 @@ function getCostAccount(billline, respcenters) {
|
||||
}
|
||||
|
||||
exports.PbsExportAp = async function (socket, { billids, txEnvelope }) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Exporting selected AP.`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Exporting selected AP.`);
|
||||
|
||||
//apAllocations has the same shap as the lines key for the accounting posting to PBS.
|
||||
socket.apAllocations = await PbsCalculateAllocationsAp(socket, billids);
|
||||
socket.txEnvelope = txEnvelope;
|
||||
for (const allocation of socket.apAllocations) {
|
||||
//apAllocations has the same shape as the lines key for the accounting posting to PBS.
|
||||
const apAllocations = await PbsCalculateAllocationsAp(socket, billids);
|
||||
await setSessionData(socket.id, "apAllocations", apAllocations);
|
||||
|
||||
// Store txEnvelope in session
|
||||
await setSessionData(socket.id, "txEnvelope", txEnvelope);
|
||||
|
||||
for (const allocation of apAllocations) {
|
||||
const { billid, ...restAllocation } = allocation;
|
||||
const { data: AccountPostingChange } = await axios.post(PBS_ENDPOINTS.AccountingPostingChange, restAllocation, {
|
||||
auth: PBS_CREDENTIALS,
|
||||
socket
|
||||
});
|
||||
|
||||
CheckForErrors(socket, AccountPostingChange);
|
||||
CheckForErrors(socket, AccountPostingChange).catch((err) =>
|
||||
console.error(`Error running CheckingForErrors in pbs-ap-allocations`)
|
||||
);
|
||||
|
||||
if (AccountPostingChange.WasSuccessful) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Marking bill as exported.`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Marking bill as exported.`);
|
||||
await MarkApExported(socket, [billid]);
|
||||
|
||||
socket.emit("ap-export-success", billid);
|
||||
} else {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Export was not succesful.`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Export was not successful.`);
|
||||
socket.emit("ap-export-failure", {
|
||||
billid,
|
||||
error: AccountPostingChange.Message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
socket.emit("ap-export-complete");
|
||||
};
|
||||
|
||||
async function MarkApExported(socket, billids) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Marking bills as exported for id ${billids}`);
|
||||
const bills = await getSessionData(socket.id, "bills");
|
||||
const bodyshop = await getSessionData(socket.id, "bodyshop");
|
||||
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Marking bills as exported for id ${billids}`);
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
return await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.MARK_BILLS_EXPORTED, {
|
||||
billids,
|
||||
@@ -237,13 +270,11 @@ async function MarkApExported(socket, billids) {
|
||||
exported: true,
|
||||
exported_at: new Date()
|
||||
},
|
||||
logs: socket.bills.map((bill) => ({
|
||||
bodyshopid: socket.bodyshop.id,
|
||||
logs: bills.map((bill) => ({
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: bill.id,
|
||||
successful: true,
|
||||
useremail: socket.user.email
|
||||
}))
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -12,136 +12,168 @@ const CalculateAllocations = require("../../cdk/cdk-calculate-allocations").defa
|
||||
const CdkBase = require("../../web-sockets/web-socket");
|
||||
const moment = require("moment-timezone");
|
||||
const Dinero = require("dinero.js");
|
||||
const { setSessionData, getSessionData } = require("../../../server");
|
||||
const InstanceManager = require("../../utils/instanceMgr").default;
|
||||
const axios = AxiosLib.create();
|
||||
|
||||
axios.interceptors.request.use((x) => {
|
||||
const socket = x.socket;
|
||||
axios.interceptors.request.use(
|
||||
async (x) => {
|
||||
const socket = x.socket;
|
||||
|
||||
const headers = {
|
||||
...x.headers.common,
|
||||
...x.headers[x.method],
|
||||
...x.headers
|
||||
};
|
||||
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
|
||||
x.url
|
||||
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
|
||||
console.log(printable);
|
||||
const headers = {
|
||||
...x.headers.common,
|
||||
...x.headers[x.method],
|
||||
...x.headers
|
||||
};
|
||||
|
||||
CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data);
|
||||
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
|
||||
x.url
|
||||
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
|
||||
|
||||
return x;
|
||||
});
|
||||
console.log(printable);
|
||||
|
||||
axios.interceptors.response.use((x) => {
|
||||
const socket = x.config.socket;
|
||||
await CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data);
|
||||
|
||||
const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`;
|
||||
console.log(printable);
|
||||
CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data);
|
||||
return x; // Make sure to return the request object
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
return x;
|
||||
});
|
||||
axios.interceptors.response.use(
|
||||
async (x) => {
|
||||
const socket = x.config.socket;
|
||||
|
||||
const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`;
|
||||
|
||||
console.log(printable);
|
||||
|
||||
await CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data);
|
||||
|
||||
return x; // Make sure to return the response object
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
exports.default = async function (socket, { txEnvelope, jobid }) {
|
||||
socket.logEvents = [];
|
||||
socket.recordid = jobid;
|
||||
socket.txEnvelope = txEnvelope;
|
||||
try {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Received Job export request for id ${jobid}`);
|
||||
await setSessionData(socket.id, "logEvents", []);
|
||||
await setSessionData(socket.id, "recordid", jobid);
|
||||
await setSessionData(socket.id, "txEnvelope", txEnvelope);
|
||||
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Received Job export request for id ${jobid}`);
|
||||
|
||||
const JobData = await QueryJobData(socket, jobid);
|
||||
socket.JobData = JobData;
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Querying the DMS for the Vehicle Record.`);
|
||||
//Query for the Vehicle record to get the associated customer.
|
||||
socket.DmsVeh = await QueryVehicleFromDms(socket);
|
||||
await setSessionData(socket.id, "JobData", JobData);
|
||||
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Querying the DMS for the Vehicle Record.`);
|
||||
|
||||
// Query for the Vehicle record to get the associated customer
|
||||
const DmsVeh = await QueryVehicleFromDms(socket);
|
||||
await setSessionData(socket.id, "DmsVeh", DmsVeh);
|
||||
|
||||
let DMSVehCustomer;
|
||||
|
||||
//Todo: Need to validate the lines and methods below.
|
||||
if (socket.DmsVeh && socket.DmsVeh.CustomerRef) {
|
||||
//Get the associated customer from the Vehicle Record.
|
||||
socket.DMSVehCustomer = await QueryCustomerBycodeFromDms(socket, socket.DmsVeh.CustomerRef);
|
||||
if (DmsVeh?.CustomerRef) {
|
||||
// Get the associated customer from the Vehicle Record
|
||||
DMSVehCustomer = await QueryCustomerBycodeFromDms(socket, DmsVeh.CustomerRef);
|
||||
await setSessionData(socket.id, "DMSVehCustomer", DMSVehCustomer);
|
||||
}
|
||||
socket.DMSCustList = await QueryCustomersFromDms(socket);
|
||||
|
||||
const DMSCustList = await QueryCustomersFromDms(socket);
|
||||
await setSessionData(socket.id, "DMSCustList", DMSCustList);
|
||||
|
||||
socket.emit("pbs-select-customer", [
|
||||
...(socket.DMSVehCustomer ? [{ ...socket.DMSVehCustomer, vinOwner: true }] : []),
|
||||
...socket.DMSCustList
|
||||
...(DMSVehCustomer ? [{ ...DMSVehCustomer, vinOwner: true }] : []),
|
||||
...DMSCustList
|
||||
]);
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error encountered in PbsJobExport. ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error encountered in PbsJobExport. ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
exports.PbsSelectedCustomer = async function PbsSelectedCustomer(socket, selectedCustomerId) {
|
||||
try {
|
||||
if (socket.JobData.bodyshop.pbs_configuration.disablecontactvehicle === false) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `User selected customer ${selectedCustomerId || "NEW"}`);
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
|
||||
//Upsert the contact information as per Wafaa's Email.
|
||||
CdkBase.createLogEvent(
|
||||
if (JobData.bodyshop.pbs_configuration.disablecontactvehicle === false) {
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `User selected customer ${selectedCustomerId || "NEW"}`);
|
||||
|
||||
// Upsert the contact information as per Wafaa's Email
|
||||
await CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`Upserting contact information to DMS for ${
|
||||
socket.JobData.ownr_fn || ""
|
||||
} ${socket.JobData.ownr_ln || ""} ${socket.JobData.ownr_co_nm || ""}`
|
||||
JobData.ownr_fn || ""
|
||||
} ${JobData.ownr_ln || ""} ${JobData.ownr_co_nm || ""}`
|
||||
);
|
||||
|
||||
const ownerRef = await UpsertContactData(socket, selectedCustomerId);
|
||||
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Upserting vehicle information to DMS for ${socket.JobData.v_vin}`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Upserting vehicle information to DMS for ${JobData.v_vin}`);
|
||||
await UpsertVehicleData(socket, ownerRef.ReferenceId);
|
||||
} else {
|
||||
CdkBase.createLogEvent(
|
||||
await CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`Contact and Vehicle updates disabled. Skipping to accounting data insert.`
|
||||
);
|
||||
}
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Inserting account data.`);
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Inserting accounting posting data..`);
|
||||
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Inserting account data.`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Inserting accounting posting data..`);
|
||||
const insertResponse = await InsertAccountPostingData(socket);
|
||||
|
||||
// TODO: Insert Clear session
|
||||
if (insertResponse.WasSuccessful) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported.`);
|
||||
await MarkJobExported(socket, socket.JobData.id);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported.`);
|
||||
await MarkJobExported(socket, JobData.id);
|
||||
|
||||
socket.emit("export-success", socket.JobData.id);
|
||||
socket.emit("export-success", JobData.id);
|
||||
} else {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Export was not succesful.`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Export was not successful.`);
|
||||
}
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkSelectedCustomer. ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error encountered in PbsSelectedCustomer. ${error}`);
|
||||
await InsertFailedExportLog(socket, error);
|
||||
}
|
||||
};
|
||||
|
||||
async function CheckForErrors(socket, response) {
|
||||
if (response.WasSuccessful === undefined || response.WasSuccessful === true) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Successful response from DMS. ${response.Message || ""}`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Successful response from DMS. ${response.Message || ""}`);
|
||||
} else {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error received from DMS: ${response.Message}`);
|
||||
CdkBase.createLogEvent(socket, "TRACE", `Error received from DMS: ${JSON.stringify(response)}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error received from DMS: ${response.Message}`);
|
||||
await CdkBase.createLogEvent(socket, "TRACE", `Error received from DMS: ${JSON.stringify(response)}`);
|
||||
}
|
||||
}
|
||||
|
||||
exports.CheckForErrors = CheckForErrors;
|
||||
|
||||
async function QueryJobData(socket, jobid) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`);
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.QUERY_JOBS_FOR_PBS_EXPORT, { id: jobid });
|
||||
CdkBase.createLogEvent(socket, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`);
|
||||
await CdkBase.createLogEvent(socket, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`);
|
||||
return result.jobs_by_pk;
|
||||
}
|
||||
|
||||
async function QueryVehicleFromDms(socket) {
|
||||
try {
|
||||
if (!socket.JobData.v_vin) return null;
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
|
||||
if (!JobData.v_vin) return null;
|
||||
|
||||
const { data: VehicleGetResponse, request } = await axios.post(
|
||||
PBS_ENDPOINTS.VehicleGet,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
SerialNumber: JobData.bodyshop.pbs_serialnumber,
|
||||
// VehicleId: "00000000000000000000000000000000",
|
||||
// Year: "String",
|
||||
// Make: "String",
|
||||
@@ -149,7 +181,7 @@ async function QueryVehicleFromDms(socket) {
|
||||
// Trim: "String",
|
||||
// ModelNumber: "String",
|
||||
// StockNumber: "String",
|
||||
VIN: socket.JobData.v_vin
|
||||
VIN: JobData.v_vin
|
||||
// LicenseNumber: "String",
|
||||
// Lot: "String",
|
||||
// Status: "String",
|
||||
@@ -166,26 +198,31 @@ async function QueryVehicleFromDms(socket) {
|
||||
{ auth: PBS_CREDENTIALS, socket }
|
||||
);
|
||||
|
||||
CheckForErrors(socket, VehicleGetResponse);
|
||||
await CheckForErrors(socket, VehicleGetResponse);
|
||||
|
||||
return VehicleGetResponse;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error in QueryVehicleFromDms - ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error in QueryVehicleFromDms - ${error}`);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function QueryCustomersFromDms(socket) {
|
||||
try {
|
||||
// Retrieve JobData from session storage
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
|
||||
// Make an API call to PBS to query customer details
|
||||
const { data: CustomerGetResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.ContactGet,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
SerialNumber: JobData.bodyshop.pbs_serialnumber,
|
||||
//ContactId: "00000000000000000000000000000000",
|
||||
// ContactCode: socket.JobData.owner.accountingid,
|
||||
FirstName: socket.JobData.ownr_fn,
|
||||
LastName: socket.JobData.ownr_co_nm ? socket.JobData.ownr_co_nm : socket.JobData.ownr_ln,
|
||||
PhoneNumber: socket.JobData.ownr_ph1,
|
||||
EmailAddress: socket.JobData.ownr_ea
|
||||
// ContactCode: JobData.owner.accountingid,
|
||||
FirstName: JobData.ownr_fn,
|
||||
LastName: JobData.ownr_co_nm ? JobData.ownr_co_nm : JobData.ownr_ln,
|
||||
PhoneNumber: JobData.ownr_ph1,
|
||||
EmailAddress: JobData.ownr_ea
|
||||
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||
// ContactIdList: ["00000000000000000000000000000000"],
|
||||
@@ -197,27 +234,36 @@ async function QueryCustomersFromDms(socket) {
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS, socket }
|
||||
);
|
||||
CheckForErrors(socket, CustomerGetResponse);
|
||||
|
||||
// Check for errors in the PBS response
|
||||
await CheckForErrors(socket, CustomerGetResponse);
|
||||
|
||||
// Return the list of contacts from the PBS response
|
||||
return CustomerGetResponse && CustomerGetResponse.Contacts;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error in QueryCustomersFromDms - ${error}`);
|
||||
// Log any errors encountered during the API call
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error in QueryCustomersFromDms - ${error}`);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function QueryCustomerBycodeFromDms(socket, CustomerRef) {
|
||||
try {
|
||||
// Retrieve JobData from session storage
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
|
||||
// Make an API call to PBS to query customer by ContactId
|
||||
const { data: CustomerGetResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.ContactGet,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
SerialNumber: JobData.bodyshop.pbs_serialnumber,
|
||||
ContactId: CustomerRef
|
||||
//ContactCode: socket.JobData.owner.accountingid,
|
||||
//FirstName: socket.JobData.ownr_co_nm
|
||||
// ? socket.JobData.ownr_co_nm
|
||||
// : socket.JobData.ownr_fn,
|
||||
//LastName: socket.JobData.ownr_ln,
|
||||
//PhoneNumber: socket.JobData.ownr_ph1,
|
||||
//ContactCode: JobData.owner.accountingid,
|
||||
//FirstName: JobData.ownr_co_nm
|
||||
// ? JobData.ownr_co_nm
|
||||
// : JobData.ownr_fn,
|
||||
//LastName: JobData.ownr_ln,
|
||||
//PhoneNumber: JobData.ownr_ph1,
|
||||
// EmailAddress: "String",
|
||||
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||
@@ -230,33 +276,42 @@ async function QueryCustomerBycodeFromDms(socket, CustomerRef) {
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS, socket }
|
||||
);
|
||||
CheckForErrors(socket, CustomerGetResponse);
|
||||
|
||||
// Check for errors in the PBS response
|
||||
await CheckForErrors(socket, CustomerGetResponse);
|
||||
|
||||
// Return the list of contacts from the PBS response
|
||||
return CustomerGetResponse && CustomerGetResponse.Contacts;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error in QueryCustomersFromDms - ${error}`);
|
||||
// Log any errors encountered during the API call
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error in QueryCustomerBycodeFromDms - ${error}`);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function UpsertContactData(socket, selectedCustomerId) {
|
||||
try {
|
||||
// Retrieve JobData from session storage
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
|
||||
// Make an API call to PBS to upsert contact data
|
||||
const { data: ContactChangeResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.ContactChange,
|
||||
{
|
||||
ContactInfo: {
|
||||
// Id: socket.JobData.owner.id,
|
||||
// Id: JobData.owner.id,
|
||||
...(selectedCustomerId ? { ContactId: selectedCustomerId } : {}),
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
Code: socket.JobData.owner.accountingid,
|
||||
...(socket.JobData.ownr_co_nm
|
||||
SerialNumber: JobData.bodyshop.pbs_serialnumber,
|
||||
Code: JobData.owner.accountingid,
|
||||
...(JobData.ownr_co_nm
|
||||
? {
|
||||
//LastName: socket.JobData.ownr_ln,
|
||||
FirstName: socket.JobData.ownr_co_nm,
|
||||
//LastName: JobData.ownr_ln,
|
||||
FirstName: JobData.ownr_co_nm,
|
||||
IsBusiness: true
|
||||
}
|
||||
: {
|
||||
LastName: socket.JobData.ownr_ln,
|
||||
FirstName: socket.JobData.ownr_fn,
|
||||
LastName: JobData.ownr_ln,
|
||||
FirstName: JobData.ownr_fn,
|
||||
IsBusiness: false
|
||||
}),
|
||||
|
||||
@@ -266,20 +321,20 @@ async function UpsertContactData(socket, selectedCustomerId) {
|
||||
IsInactive: false,
|
||||
|
||||
//ApartmentNumber: "String",
|
||||
Address: socket.JobData.ownr_addr1,
|
||||
City: socket.JobData.ownr_city,
|
||||
//County: socket.JobData.ownr_addr1,
|
||||
State: socket.JobData.ownr_st,
|
||||
ZipCode: socket.JobData.ownr_zip,
|
||||
Address: JobData.ownr_addr1,
|
||||
City: JobData.ownr_city,
|
||||
//County: JobData.ownr_addr1,
|
||||
State: JobData.ownr_st,
|
||||
ZipCode: JobData.ownr_zip,
|
||||
//BusinessPhone: "String",
|
||||
//BusinessPhoneExt: "String",
|
||||
HomePhone: socket.JobData.ownr_ph2,
|
||||
CellPhone: socket.JobData.ownr_ph1,
|
||||
HomePhone: JobData.ownr_ph2,
|
||||
CellPhone: JobData.ownr_ph1,
|
||||
//BusinessPhoneRawReverse: "String",
|
||||
//HomePhoneRawReverse: "String",
|
||||
//CellPhoneRawReverse: "String",
|
||||
//FaxNumber: "String",
|
||||
EmailAddress: socket.JobData.ownr_ea
|
||||
EmailAddress: JobData.ownr_ea
|
||||
//Notes: "String",
|
||||
//CriticalMemo: "String",
|
||||
//BirthDate: "0001-01-01T00:00:00.0000000Z",
|
||||
@@ -312,39 +367,43 @@ async function UpsertContactData(socket, selectedCustomerId) {
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS, socket }
|
||||
);
|
||||
CheckForErrors(socket, ContactChangeResponse);
|
||||
|
||||
await CheckForErrors(socket, ContactChangeResponse);
|
||||
|
||||
return ContactChangeResponse;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error in UpsertContactData - ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error in UpsertContactData - ${error}`);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function UpsertVehicleData(socket, ownerRef) {
|
||||
try {
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
|
||||
const { data: VehicleChangeResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.VehicleChange,
|
||||
{
|
||||
VehicleInfo: {
|
||||
//Id: "string/00000000-0000-0000-0000-000000000000",
|
||||
//VehicleId: "00000000000000000000000000000000",
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
SerialNumber: JobData.bodyshop.pbs_serialnumber,
|
||||
//StockNumber: "String",
|
||||
VIN: socket.JobData.v_vin,
|
||||
LicenseNumber: socket.JobData.plate_no,
|
||||
VIN: JobData.v_vin,
|
||||
LicenseNumber: JobData.plate_no,
|
||||
//FleetNumber: "String",
|
||||
//Status: "String",
|
||||
OwnerRef: ownerRef, // "00000000000000000000000000000000",
|
||||
ModelNumber: socket.JobData.vehicle && socket.JobData.vehicle.v_makecode,
|
||||
Make: socket.JobData.v_make_desc,
|
||||
Model: socket.JobData.v_model_desc,
|
||||
Trim: socket.JobData.vehicle && socket.JobData.vehicle.v_trimcode,
|
||||
ModelNumber: JobData.vehicle && JobData.vehicle.v_makecode,
|
||||
Make: JobData.v_make_desc,
|
||||
Model: JobData.v_model_desc,
|
||||
Trim: JobData.vehicle && JobData.vehicle.v_trimcode,
|
||||
//VehicleType: "String",
|
||||
Year: socket.JobData.v_model_yr,
|
||||
Odometer: socket.JobData.kmout,
|
||||
Year: JobData.v_model_yr,
|
||||
Odometer: JobData.kmout,
|
||||
ExteriorColor: {
|
||||
Code: socket.JobData.v_color,
|
||||
Description: socket.JobData.v_color
|
||||
Code: JobData.v_color,
|
||||
Description: JobData.v_color
|
||||
}
|
||||
// InteriorColor: { Code: "String", Description: "String" },
|
||||
//Engine: "String",
|
||||
@@ -465,100 +524,113 @@ async function UpsertVehicleData(socket, ownerRef) {
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS, socket }
|
||||
);
|
||||
CheckForErrors(socket, VehicleChangeResponse);
|
||||
|
||||
await CheckForErrors(socket, VehicleChangeResponse);
|
||||
|
||||
return VehicleChangeResponse;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error in UpsertVehicleData - ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error in UpsertVehicleData - ${error}`);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function InsertAccountPostingData(socket) {
|
||||
try {
|
||||
const allocations = await CalculateAllocations(socket, socket.JobData.id);
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
const txEnvelope = await getSessionData(socket.id, "txEnvelope");
|
||||
|
||||
const allocations = await CalculateAllocations(socket, JobData.id);
|
||||
|
||||
const wips = [];
|
||||
|
||||
allocations.forEach((alloc) => {
|
||||
//Add the sale item from each allocation.
|
||||
// Add the sale item from each allocation if the amount is greater than 0 and not a tax
|
||||
if (alloc.sale.getAmount() > 0 && !alloc.tax) {
|
||||
const item = {
|
||||
Account: alloc.profitCenter.dms_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
ControlNumber: JobData.ro_number,
|
||||
Amount: alloc.sale.multiply(-1).toFormat("0.00"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).tz(socket.JobData.bodyshop.timezone).toISOString()
|
||||
// Comment: "String",
|
||||
// AdditionalInfo: "String",
|
||||
InvoiceNumber: JobData.ro_number,
|
||||
InvoiceDate: moment(JobData.date_invoiced).tz(JobData.bodyshop.timezone).toISOString()
|
||||
};
|
||||
wips.push(item);
|
||||
}
|
||||
|
||||
//Add the cost Item.
|
||||
// Add the cost item if the cost amount is greater than 0 and not a tax
|
||||
if (alloc.cost.getAmount() > 0 && !alloc.tax) {
|
||||
const item = {
|
||||
Account: alloc.costCenter.dms_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
ControlNumber: JobData.ro_number,
|
||||
Amount: alloc.cost.toFormat("0.00"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).tz(socket.JobData.bodyshop.timezone).toISOString()
|
||||
// Comment: "String",
|
||||
// AdditionalInfo: "String",
|
||||
InvoiceNumber: JobData.ro_number,
|
||||
InvoiceDate: moment(JobData.date_invoiced).tz(JobData.bodyshop.timezone).toISOString()
|
||||
};
|
||||
|
||||
wips.push(item);
|
||||
|
||||
const itemWip = {
|
||||
Account: alloc.costCenter.dms_wip_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
ControlNumber: JobData.ro_number,
|
||||
Amount: alloc.cost.multiply(-1).toFormat("0.00"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).tz(socket.JobData.bodyshop.timezone).toISOString()
|
||||
// Comment: "String",
|
||||
// AdditionalInfo: "String",
|
||||
InvoiceNumber: JobData.ro_number,
|
||||
InvoiceDate: moment(JobData.date_invoiced).tz(JobData.bodyshop.timezone).toISOString()
|
||||
};
|
||||
|
||||
wips.push(itemWip);
|
||||
//Add to the WIP account.
|
||||
// Add to the WIP account.
|
||||
}
|
||||
|
||||
// Add tax-related entries if applicable
|
||||
if (alloc.tax) {
|
||||
if (alloc.sale.getAmount() > 0) {
|
||||
const item2 = {
|
||||
Account: alloc.profitCenter.dms_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
ControlNumber: JobData.ro_number,
|
||||
Amount: alloc.sale.multiply(-1).toFormat("0.00"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).tz(socket.JobData.bodyshop.timezone).toISOString()
|
||||
// Comment: "String",
|
||||
// AdditionalInfo: "String",
|
||||
InvoiceNumber: JobData.ro_number,
|
||||
InvoiceDate: moment(JobData.date_invoiced).tz(JobData.bodyshop.timezone).toISOString()
|
||||
};
|
||||
|
||||
wips.push(item2);
|
||||
}
|
||||
}
|
||||
});
|
||||
socket.txEnvelope.payers.forEach((payer) => {
|
||||
|
||||
// Add payer information
|
||||
txEnvelope.payers.forEach((payer) => {
|
||||
const item = {
|
||||
Account: payer.dms_acctnumber,
|
||||
ControlNumber: payer.controlnumber,
|
||||
Amount: Dinero({ amount: Math.round(payer.amount * 100) }).toFormat("0.0"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).tz(socket.JobData.bodyshop.timezone).toISOString()
|
||||
// Comment: "String",
|
||||
// AdditionalInfo: "String",
|
||||
InvoiceNumber: JobData.ro_number,
|
||||
InvoiceDate: moment(JobData.date_invoiced).tz(JobData.bodyshop.timezone).toISOString()
|
||||
};
|
||||
|
||||
wips.push(item);
|
||||
});
|
||||
socket.transWips = wips;
|
||||
|
||||
await setSessionData(socket.id, "transWips", wips);
|
||||
|
||||
const { data: AccountPostingChange } = await axios.post(
|
||||
PBS_ENDPOINTS.AccountingPostingChange,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
SerialNumber: JobData.bodyshop.pbs_serialnumber,
|
||||
Posting: {
|
||||
Reference: socket.JobData.ro_number,
|
||||
JournalCode: socket.txEnvelope.journal,
|
||||
TransactionDate: moment(socket.JobData.date_invoiced).tz(socket.JobData.bodyshop.timezone).toISOString(), //"0001-01-01T00:00:00.0000000Z",
|
||||
Description: socket.txEnvelope.story,
|
||||
//AdditionalInfo: "String",
|
||||
Reference: JobData.ro_number,
|
||||
JournalCode: txEnvelope.journal,
|
||||
TransactionDate: moment(JobData.date_invoiced).tz(JobData.bodyshop.timezone).toISOString(), // "0001-01-01T00:00:00.0000000Z",
|
||||
Description: txEnvelope.story,
|
||||
// AdditionalInfo: "String",
|
||||
Source: InstanceManager({ imex: "ImEX Online", rome: "Rome Online" }),
|
||||
Lines: wips
|
||||
}
|
||||
@@ -566,54 +638,55 @@ async function InsertAccountPostingData(socket) {
|
||||
{ auth: PBS_CREDENTIALS, socket }
|
||||
);
|
||||
|
||||
CheckForErrors(socket, AccountPostingChange);
|
||||
await CheckForErrors(socket, AccountPostingChange);
|
||||
|
||||
return AccountPostingChange;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error in InsertAccountPostingData - ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error in InsertAccountPostingData - ${error}`);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function MarkJobExported(socket, jobid) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported for id ${jobid}`);
|
||||
await CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported for id ${jobid}`);
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
const transWips = await getSessionData(socket.id, "transWips");
|
||||
return await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.MARK_JOB_EXPORTED, {
|
||||
jobId: jobid,
|
||||
job: {
|
||||
status: socket.JobData.bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||
status: JobData.bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||
date_exported: new Date()
|
||||
},
|
||||
log: {
|
||||
bodyshopid: socket.JobData.bodyshop.id,
|
||||
bodyshopid: JobData.bodyshop.id,
|
||||
jobid: jobid,
|
||||
successful: true,
|
||||
useremail: socket.user.email,
|
||||
metadata: socket.transWips
|
||||
metadata: transWips
|
||||
},
|
||||
bill: {
|
||||
exported: true,
|
||||
exported_at: new Date()
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function InsertFailedExportLog(socket, error) {
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
const JobData = await getSessionData(socket.id, "JobData");
|
||||
|
||||
return await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.INSERT_EXPORT_LOG, {
|
||||
log: {
|
||||
bodyshopid: socket.JobData.bodyshop.id,
|
||||
jobid: socket.JobData.id,
|
||||
bodyshopid: JobData.bodyshop.id,
|
||||
jobid: JobData.id,
|
||||
successful: false,
|
||||
message: [error],
|
||||
useremail: socket.user.email
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ const { DiscountNotAlreadyCounted } = InstanceManager({
|
||||
|
||||
exports.defaultRoute = async function (req, res) {
|
||||
try {
|
||||
CdkBase.createLogEvent(req, "DEBUG", `Received request to calculate allocations for ${req.body.jobid}`);
|
||||
await CdkBase.createLogEvent(req, "DEBUG", `Received request to calculate allocations for ${req.body.jobid}`);
|
||||
const jobData = await QueryJobData(req, req.BearerToken, req.body.jobid);
|
||||
return res.status(200).json({ data: calculateAllocations(req, jobData) });
|
||||
return res.status(200).json({ data: await calculateAllocations(req, jobData) });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
CdkBase.createLogEvent(req, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`);
|
||||
await CdkBase.createLogEvent(req, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`);
|
||||
res.status(500).json({ error: `Error encountered in CdkCalculateAllocations. ${error}` });
|
||||
}
|
||||
};
|
||||
@@ -31,22 +31,22 @@ exports.defaultRoute = async function (req, res) {
|
||||
exports.default = async function (socket, jobid) {
|
||||
try {
|
||||
const jobData = await QueryJobData(socket, "Bearer " + socket.handshake.auth.token, jobid);
|
||||
return calculateAllocations(socket, jobData);
|
||||
return await calculateAllocations(socket, jobData);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`);
|
||||
await CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
async function QueryJobData(connectionData, token, jobid) {
|
||||
CdkBase.createLogEvent(connectionData, "DEBUG", `Querying job data for id ${jobid}`);
|
||||
await CdkBase.createLogEvent(connectionData, "DEBUG", `Querying job data for id ${jobid}`);
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client.setHeaders({ Authorization: token }).request(queries.GET_CDK_ALLOCATIONS, { id: jobid });
|
||||
CdkBase.createLogEvent(connectionData, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`);
|
||||
await CdkBase.createLogEvent(connectionData, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`);
|
||||
return result.jobs_by_pk;
|
||||
}
|
||||
|
||||
function calculateAllocations(connectionData, job) {
|
||||
async function calculateAllocations(connectionData, job) {
|
||||
const { bodyshop } = job;
|
||||
|
||||
const taxAllocations = InstanceManager({
|
||||
@@ -171,7 +171,7 @@ function calculateAllocations(connectionData, job) {
|
||||
const selectedDmsAllocationConfig = bodyshop.md_responsibility_centers.dms_defaults.find(
|
||||
(d) => d.name === job.dms_allocation
|
||||
);
|
||||
CdkBase.createLogEvent(
|
||||
await CdkBase.createLogEvent(
|
||||
connectionData,
|
||||
"DEBUG",
|
||||
`Using DMS Allocation ${selectedDmsAllocationConfig && selectedDmsAllocationConfig.name} for cost export.`
|
||||
@@ -361,9 +361,10 @@ function calculateAllocations(connectionData, job) {
|
||||
}
|
||||
if (InstanceManager({ rome: true })) {
|
||||
//profile level adjustments for parts
|
||||
Object.keys(job.job_totals.parts.adjustments).forEach((key) => {
|
||||
for (const key of Object.keys(job.job_totals.parts.adjustments)) {
|
||||
const accountName = selectedDmsAllocationConfig.profits[key];
|
||||
const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName);
|
||||
|
||||
if (otherAccount) {
|
||||
if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero();
|
||||
|
||||
@@ -371,31 +372,41 @@ function calculateAllocations(connectionData, job) {
|
||||
Dinero(job.job_totals.parts.adjustments[key])
|
||||
);
|
||||
} else {
|
||||
CdkBase.createLogEvent(
|
||||
// Use await correctly here
|
||||
await CdkBase.createLogEvent(
|
||||
connectionData,
|
||||
"ERROR",
|
||||
`Error encountered in CdkCalculateAllocations. Unable to find adjustment account. ${error}`
|
||||
`Error encountered in CdkCalculateAllocations. Unable to find adjustment account for key ${key}.`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//profile level adjustments for labor and materials
|
||||
Object.keys(job.job_totals.rates).forEach((key) => {
|
||||
if (job.job_totals.rates[key] && job.job_totals.rates[key].adjustment && Dinero(job.job_totals.rates[key].adjustment).isZero() === false) {
|
||||
for (const key of Object.keys(job.job_totals.rates)) {
|
||||
if (
|
||||
job.job_totals.rates[key] &&
|
||||
job.job_totals.rates[key].adjustment &&
|
||||
Dinero(job.job_totals.rates[key].adjustment).isZero() === false
|
||||
) {
|
||||
const accountName = selectedDmsAllocationConfig.profits[key.toUpperCase()];
|
||||
const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName);
|
||||
|
||||
if (otherAccount) {
|
||||
if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero();
|
||||
|
||||
profitCenterHash[accountName] = profitCenterHash[accountName].add(Dinero(job.job_totals.rates[key].adjustments));
|
||||
profitCenterHash[accountName] = profitCenterHash[accountName].add(
|
||||
Dinero(job.job_totals.rates[key].adjustments)
|
||||
);
|
||||
} else {
|
||||
CdkBase.createLogEvent(
|
||||
// Await the log event creation here
|
||||
await CdkBase.createLogEvent(
|
||||
connectionData,
|
||||
"ERROR",
|
||||
`Error encountered in CdkCalculateAllocations. Unable to find adjustment account. ${error}`
|
||||
`Error encountered in CdkCalculateAllocations. Unable to find adjustment account for key ${key}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const jobAllocations = _.union(Object.keys(profitCenterHash), Object.keys(costCenterHash)).map((key) => {
|
||||
|
||||
@@ -86,7 +86,7 @@ async function GetCdkMakes(req, cdk_dealerid) {
|
||||
{}
|
||||
);
|
||||
|
||||
CheckCdkResponseForError(null, soapResponseVehicleSearch);
|
||||
await CheckCdkResponseForError(null, soapResponseVehicleSearch);
|
||||
const [result, rawResponse, , rawRequest] = soapResponseVehicleSearch;
|
||||
logger.log("cdk-replace-makes-models-request", "ERROR", req.user.email, null, {
|
||||
cdk_dealerid,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,10 +15,10 @@ exports.CDK_CREDENTIALS = CDK_CREDENTIALS;
|
||||
const cdkDomain =
|
||||
process.env.NODE_ENV === "production" ? "https://3pa.dmotorworks.com" : "https://uat-3pa.dmotorworks.com";
|
||||
|
||||
function CheckCdkResponseForError(socket, soapResponse) {
|
||||
async function CheckCdkResponseForError(socket, soapResponse) {
|
||||
if (!soapResponse[0]) {
|
||||
//The response was null, this might be ok, it might not.
|
||||
CdkBase.createLogEvent(
|
||||
await CdkBase.createLogEvent(
|
||||
socket,
|
||||
"WARNING",
|
||||
`Warning detected in CDK Response - it appears to be null. Stack: ${new Error().stack}`
|
||||
@@ -31,23 +31,22 @@ function CheckCdkResponseForError(socket, soapResponse) {
|
||||
if (Array.isArray(ResultToCheck)) {
|
||||
ResultToCheck.forEach((result) => checkIndividualResult(socket, result));
|
||||
} else {
|
||||
checkIndividualResult(socket, ResultToCheck);
|
||||
await checkIndividualResult(socket, ResultToCheck);
|
||||
}
|
||||
}
|
||||
|
||||
exports.CheckCdkResponseForError = CheckCdkResponseForError;
|
||||
|
||||
function checkIndividualResult(socket, ResultToCheck) {
|
||||
async function checkIndividualResult(socket, ResultToCheck) {
|
||||
if (
|
||||
ResultToCheck.errorLevel === 0 ||
|
||||
ResultToCheck.errorLevel === "0" ||
|
||||
ResultToCheck.code === "success" ||
|
||||
(!ResultToCheck.code && !ResultToCheck.errorLevel)
|
||||
)
|
||||
) {
|
||||
//TODO: Verify that this is the best way to detect errors.
|
||||
return;
|
||||
else {
|
||||
CdkBase.createLogEvent(
|
||||
} else {
|
||||
await CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error detected in CDK Response - ${JSON.stringify(ResultToCheck, null, 2)}`
|
||||
|
||||
@@ -3,9 +3,8 @@ require("dotenv").config({
|
||||
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
|
||||
});
|
||||
|
||||
const { io } = require("../../server");
|
||||
const { io, setSessionData, clearSessionData, getSessionData } = require("../../server");
|
||||
const { admin } = require("../firebase/firebase-handler");
|
||||
const { isArray } = require("lodash");
|
||||
const logger = require("../utils/logger");
|
||||
const { default: CdkJobExport, CdkSelectedCustomer } = require("../cdk/cdk-job-export");
|
||||
const CdkGetMakes = require("../cdk/cdk-get-makes").default;
|
||||
@@ -32,9 +31,9 @@ function socketAuthMiddleware(socket, next) {
|
||||
}
|
||||
|
||||
// Register all socket events for a given socket connection
|
||||
function registerSocketEvents(socket) {
|
||||
socket.log_level = "TRACE";
|
||||
createLogEvent(socket, "DEBUG", `Connected and Authenticated.`);
|
||||
async function registerSocketEvents(socket) {
|
||||
await setSessionData(socket.id, "log_level", "TRACE");
|
||||
await createLogEvent(socket, "DEBUG", `Connected and Authenticated.`);
|
||||
|
||||
// Register CDK-related socket events
|
||||
registerCdkEvents(socket);
|
||||
@@ -48,18 +47,24 @@ function registerSocketEvents(socket) {
|
||||
// Register room and broadcasting events
|
||||
registerRoomAndBroadcastEvents(socket);
|
||||
|
||||
// Register event to clear DMS session
|
||||
registerDmsClearSessionEvent(socket);
|
||||
|
||||
// Handle socket disconnection
|
||||
socket.on("disconnect", () => {
|
||||
createLogEvent(socket, "DEBUG", `User disconnected.`);
|
||||
socket.on("disconnect", async () => {
|
||||
await createLogEvent(socket, "DEBUG", `User disconnected.`);
|
||||
});
|
||||
}
|
||||
|
||||
// CDK-specific socket events
|
||||
function registerCdkEvents(socket) {
|
||||
socket.on("cdk-export-job", (jobid) => CdkJobExport(socket, jobid));
|
||||
socket.on("cdk-selected-customer", (selectedCustomerId) => {
|
||||
createLogEvent(socket, "DEBUG", `User selected customer ID ${selectedCustomerId}`);
|
||||
CdkSelectedCustomer(socket, selectedCustomerId);
|
||||
socket.on("cdk-selected-customer", async (selectedCustomerId) => {
|
||||
await createLogEvent(socket, "DEBUG", `User selected customer ID ${selectedCustomerId}`);
|
||||
CdkSelectedCustomer(socket, selectedCustomerId).catch((err) =>
|
||||
console.error(`Error in cdk-selected-customer: ${err}`)
|
||||
);
|
||||
await setSessionData(socket.id, "selectedCustomer", selectedCustomerId);
|
||||
});
|
||||
|
||||
socket.on("cdk-get-makes", async (cdk_dealerid, callback) => {
|
||||
@@ -67,15 +72,16 @@ function registerCdkEvents(socket) {
|
||||
const makes = await CdkGetMakes(socket, cdk_dealerid);
|
||||
callback(makes);
|
||||
} catch (error) {
|
||||
createLogEvent(socket, "ERROR", `Error in cdk-get-makes WS call. ${JSON.stringify(error)}`);
|
||||
await createLogEvent(socket, "ERROR", `Error in cdk-get-makes WS call. ${JSON.stringify(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("cdk-calculate-allocations", async (jobid, callback) => {
|
||||
const allocations = await CdkCalculateAllocations(socket, jobid);
|
||||
createLogEvent(socket, "DEBUG", `Allocations calculated.`);
|
||||
createLogEvent(socket, "TRACE", `Allocations details: ${JSON.stringify(allocations)}`);
|
||||
await createLogEvent(socket, "DEBUG", `Allocations calculated.`);
|
||||
await createLogEvent(socket, "TRACE", `Allocations details: ${JSON.stringify(allocations)}`);
|
||||
callback(allocations);
|
||||
await setSessionData(socket.id, "cdk_allocations", allocations);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -83,15 +89,19 @@ function registerCdkEvents(socket) {
|
||||
function registerPbsArEvents(socket) {
|
||||
socket.on("pbs-calculate-allocations", async (jobid, callback) => {
|
||||
const allocations = await CdkCalculateAllocations(socket, jobid);
|
||||
createLogEvent(socket, "DEBUG", `PBS AR allocations calculated.`);
|
||||
createLogEvent(socket, "TRACE", `Allocations details: ${JSON.stringify(allocations)}`);
|
||||
await createLogEvent(socket, "DEBUG", `PBS AR allocations calculated.`);
|
||||
await createLogEvent(socket, "TRACE", `Allocations details: ${JSON.stringify(allocations)}`);
|
||||
callback(allocations);
|
||||
await setSessionData(socket.id, "pbs_allocations", allocations);
|
||||
});
|
||||
|
||||
socket.on("pbs-export-job", (jobid) => PbsExportJob(socket, jobid));
|
||||
socket.on("pbs-selected-customer", (selectedCustomerId) => {
|
||||
createLogEvent(socket, "DEBUG", `PBS AR selected customer ID ${selectedCustomerId}`);
|
||||
PbsSelectedCustomer(socket, selectedCustomerId);
|
||||
socket.on("pbs-selected-customer", async (selectedCustomerId) => {
|
||||
await createLogEvent(socket, "DEBUG", `PBS AR selected customer ID ${selectedCustomerId}`);
|
||||
PbsSelectedCustomer(socket, selectedCustomerId).catch((err) =>
|
||||
console.error(`Error in pbs-selected-customer: ${err}`)
|
||||
);
|
||||
await setSessionData(socket.id, "selectedCustomer", selectedCustomerId);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -99,62 +109,92 @@ function registerPbsArEvents(socket) {
|
||||
function registerPbsApEvents(socket) {
|
||||
socket.on("pbs-calculate-allocations-ap", async (billids, callback) => {
|
||||
const allocations = await PbsCalculateAllocationsAp(socket, billids);
|
||||
createLogEvent(socket, "DEBUG", `PBS AP allocations calculated.`);
|
||||
createLogEvent(socket, "TRACE", `Allocations details: ${JSON.stringify(allocations)}`);
|
||||
socket.apAllocations = allocations;
|
||||
await createLogEvent(socket, "DEBUG", `PBS AP allocations calculated.`);
|
||||
await createLogEvent(socket, "TRACE", `Allocations details: ${JSON.stringify(allocations)}`);
|
||||
callback(allocations);
|
||||
await setSessionData(socket.id, "pbs_ap_allocations", allocations);
|
||||
});
|
||||
|
||||
socket.on("pbs-export-ap", ({ billids, txEnvelope }) => {
|
||||
socket.txEnvelope = txEnvelope;
|
||||
PbsExportAp(socket, { billids, txEnvelope });
|
||||
socket.on("pbs-export-ap", async ({ billids, txEnvelope }) => {
|
||||
await setSessionData(socket.id, "pbs_txEnvelope", txEnvelope);
|
||||
PbsExportAp(socket, { billids, txEnvelope }).catch((err) => console.error(`Error in pbs-export-ap: ${err}`));
|
||||
});
|
||||
}
|
||||
|
||||
// Room management and broadcasting events
|
||||
function registerRoomAndBroadcastEvents(socket) {
|
||||
socket.on("join-bodyshop-room", (bodyshopUUID) => {
|
||||
socket.on("join-bodyshop-room", async (bodyshopUUID) => {
|
||||
socket.join(bodyshopUUID);
|
||||
createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${bodyshopUUID}`);
|
||||
await createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${bodyshopUUID}`);
|
||||
});
|
||||
|
||||
socket.on("leave-bodyshop-room", (bodyshopUUID) => {
|
||||
socket.on("leave-bodyshop-room", async (bodyshopUUID) => {
|
||||
socket.leave(bodyshopUUID);
|
||||
createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${bodyshopUUID}`);
|
||||
await createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${bodyshopUUID}`);
|
||||
});
|
||||
|
||||
socket.on("broadcast-to-bodyshop", (bodyshopUUID, message) => {
|
||||
socket.on("broadcast-to-bodyshop", async (bodyshopUUID, message) => {
|
||||
io.to(bodyshopUUID).emit("bodyshop-message", message);
|
||||
createLogEvent(socket, "INFO", `Broadcasted message to bodyshop ${bodyshopUUID}`);
|
||||
await createLogEvent(socket, "INFO", `Broadcast message to bodyshop ${bodyshopUUID}`);
|
||||
});
|
||||
}
|
||||
|
||||
// DMS session clearing event
|
||||
function registerDmsClearSessionEvent(socket) {
|
||||
socket.on("clear-dms-session", async () => {
|
||||
await clearSessionData(socket.id); // Clear all session data in Redis
|
||||
await createLogEvent(socket, "INFO", `DMS session data cleared for socket ${socket.id}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Logging helper functions
|
||||
function createLogEvent(socket, level, message) {
|
||||
if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
|
||||
async function createLogEvent(socket, level, message) {
|
||||
const logLevel = await getSessionData(socket.id, "log_level");
|
||||
const recordid = await getSessionData(socket.id, "recordid");
|
||||
const logEvents = await getSessionData(socket.id, "logEvents");
|
||||
|
||||
if (LogLevelHierarchy(logLevel) >= LogLevelHierarchy(level)) {
|
||||
console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`);
|
||||
socket.emit("log-event", { timestamp: new Date(), level, message });
|
||||
logger.log("ws-log-event", level, socket.user.email, socket.recordid, { wsmessage: message });
|
||||
logger.log("ws-log-event", level, socket.user.email, recordid, { wsmessage: message });
|
||||
|
||||
if (socket.logEvents && isArray(socket.logEvents)) {
|
||||
socket.logEvents.push({ timestamp: new Date(), level, message });
|
||||
if (logEvents && Array.isArray(logEvents)) {
|
||||
logEvents.push({ timestamp: new Date(), level, message });
|
||||
setSessionData(socket.id, "logEvents", logEvents).catch((err) =>
|
||||
console.error(`Error setting logEvents in Redis: ${err}`)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createJsonEvent(socket, level, message, json) {
|
||||
if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
|
||||
async function createJsonEvent(socket, level, message, json) {
|
||||
const logEvents = await getSessionData(socket.id, "logEvents");
|
||||
const logLevel = await getSessionData(socket.id, "log_level");
|
||||
const recordid = await getSessionData(socket.id, "recordid");
|
||||
|
||||
if (LogLevelHierarchy(logLevel) >= LogLevelHierarchy(level)) {
|
||||
socket.emit("log-event", { timestamp: new Date(), level, message });
|
||||
}
|
||||
logger.log("ws-log-event-json", level, socket.user.email, socket.recordid, { wsmessage: message, json });
|
||||
|
||||
if (socket.logEvents && isArray(socket.logEvents)) {
|
||||
socket.logEvents.push({ timestamp: new Date(), level, message });
|
||||
logger.log("ws-log-event-json", level, socket.user.email, recordid, {
|
||||
wsmessage: message,
|
||||
json
|
||||
});
|
||||
|
||||
if (logEvents && Array.isArray(logEvents)) {
|
||||
logEvents.push({ timestamp: new Date(), level, message });
|
||||
setSessionData(socket.id, "logEvents", logEvents).catch((err) =>
|
||||
console.error(`Error setting logEvents in Redis: ${err}`)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function createXmlEvent(socket, xml, message, isError = false) {
|
||||
if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy("TRACE")) {
|
||||
async function createXmlEvent(socket, xml, message, isError = false) {
|
||||
const logLevel = await getSessionData(socket.id, "log_level");
|
||||
const recordid = await getSessionData(socket.id, "recordid");
|
||||
const logEvents = await getSessionData(socket.id, "logEvents");
|
||||
|
||||
if (LogLevelHierarchy(logLevel) >= LogLevelHierarchy("TRACE")) {
|
||||
socket.emit("log-event", {
|
||||
timestamp: new Date(),
|
||||
level: isError ? "ERROR" : "TRACE",
|
||||
@@ -166,12 +206,19 @@ function createXmlEvent(socket, xml, message, isError = false) {
|
||||
isError ? "ws-log-event-xml-error" : "ws-log-event-xml",
|
||||
isError ? "ERROR" : "TRACE",
|
||||
socket.user.email,
|
||||
socket.recordid,
|
||||
recordid,
|
||||
{ wsmessage: message, xml }
|
||||
);
|
||||
|
||||
if (socket.logEvents && isArray(socket.logEvents)) {
|
||||
socket.logEvents.push({ timestamp: new Date(), level: isError ? "ERROR" : "TRACE", message, xml });
|
||||
if (logEvents && Array.isArray(logEvents)) {
|
||||
logEvents.push({
|
||||
timestamp: new Date(),
|
||||
level: isError ? "ERROR" : "TRACE",
|
||||
message,
|
||||
xml
|
||||
});
|
||||
|
||||
await setSessionData(socket.id, "logEvents", logEvents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user