Merge branch 'master-AIO' into feature/IO-3092-imgproxy
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<babeledit_project version="1.2" be_version="2.7.1">
|
<babeledit_project be_version="2.7.1" version="1.2">
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
BabelEdit project file
|
BabelEdit project file
|
||||||
@@ -6453,6 +6453,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>mark_critical</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>operation</name>
|
<name>operation</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -6474,6 +6495,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>update_field</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>update_value</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>value</name>
|
<name>value</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -11943,6 +12006,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>shop_enabled_features</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>shopinfo</name>
|
<name>shopinfo</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -12312,6 +12396,37 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>tooltips</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>md_parts_scan</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>update_value_tooltip</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>validation</name>
|
<name>validation</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -19091,6 +19206,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>ok</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>previous</name>
|
<name>previous</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -19385,6 +19521,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>sharetoteams</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>submit</name>
|
<name>submit</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -43090,6 +43247,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>parts_returns</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>print</name>
|
<name>print</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -48557,6 +48735,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>unassigned</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>vertical</name>
|
<name>vertical</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -52732,6 +52931,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>purchases_by_date_excel</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>purchases_by_date_range_detail</name>
|
<name>purchases_by_date_range_detail</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -54483,6 +54703,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>view</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh
|
|||||||
const { data: unreadData } = useQuery(UNREAD_CONVERSATION_COUNT, {
|
const { data: unreadData } = useQuery(UNREAD_CONVERSATION_COUNT, {
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
nextFetchPolicy: "network-only",
|
nextFetchPolicy: "network-only",
|
||||||
skip: chatVisible, // Skip when chat is visible
|
pollInterval: 60 * 1000 // TODO: This is a fix for now, should be coming from sockets
|
||||||
...(pollInterval > 0 ? { pollInterval } : {})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Socket connection status
|
// Socket connection status
|
||||||
@@ -85,29 +84,25 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh
|
|||||||
|
|
||||||
// Get unread count from the cache
|
// Get unread count from the cache
|
||||||
const unreadCount = (() => {
|
const unreadCount = (() => {
|
||||||
if (chatVisible) {
|
try {
|
||||||
try {
|
const cachedData = client.readQuery({
|
||||||
const cachedData = client.readQuery({
|
query: CONVERSATION_LIST_QUERY,
|
||||||
query: CONVERSATION_LIST_QUERY,
|
variables: { offset: 0 }
|
||||||
variables: { offset: 0 }
|
});
|
||||||
});
|
|
||||||
|
|
||||||
if (!cachedData?.conversations) return 0;
|
if (!cachedData?.conversations) {
|
||||||
|
return unreadData?.messages_aggregate?.aggregate?.count;
|
||||||
// Aggregate unread message count
|
|
||||||
return cachedData.conversations.reduce((total, conversation) => {
|
|
||||||
const unread = conversation.messages_aggregate?.aggregate?.count || 0;
|
|
||||||
return total + unread;
|
|
||||||
}, 0);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Unread count not found in cache:", error);
|
|
||||||
return 0; // Fallback if not in cache
|
|
||||||
}
|
}
|
||||||
} else if (unreadData?.messages_aggregate?.aggregate?.count) {
|
|
||||||
// Use the unread count from the query result
|
// Aggregate unread message count
|
||||||
return unreadData.messages_aggregate.aggregate.count;
|
return cachedData.conversations.reduce((total, conversation) => {
|
||||||
|
const unread = conversation.messages_aggregate?.aggregate?.count || 0;
|
||||||
|
return total + unread;
|
||||||
|
}, 0);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Unread count not found in cache:", error);
|
||||||
|
return 0; // Fallback if not in cache
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import i18next from "i18next";
|
|
||||||
import React from "react";
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { setUserLanguage } from "../../redux/user/user.actions";
|
|
||||||
import HeaderComponent from "./header.component";
|
import HeaderComponent from "./header.component";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
// const mapDispatchToProps = (dispatch) => ({
|
||||||
setUserLanguage: (language) => dispatch(setUserLanguage(language))
|
// setUserLanguage: (language) => dispatch(setUserLanguage(language))
|
||||||
});
|
// });
|
||||||
|
|
||||||
export function HeaderContainer({ setUserLanguage }) {
|
// setUserLanguage was removed from signature because it is not used in the component, and it is throwing a deprecation warning
|
||||||
const handleMenuClick = (e) => {
|
export function HeaderContainer() {
|
||||||
|
// Commented out the handleMenuClick function because it is not used in the component, and it is throwing a deprecation warning
|
||||||
|
|
||||||
|
/* const handleMenuClick = (e) => {
|
||||||
if (e.item.props.actiontype === "lang-select") {
|
if (e.item.props.actiontype === "lang-select") {
|
||||||
i18next.changeLanguage(e.key, (err, t) => {
|
i18next.changeLanguage(e.key, (err, t) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -23,9 +22,10 @@ export function HeaderContainer({ setUserLanguage }) {
|
|||||||
setUserLanguage(e.key);
|
setUserLanguage(e.key);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};*/
|
||||||
|
// return <HeaderComponent handleMenuClick={handleMenuClick} />;
|
||||||
|
|
||||||
return <HeaderComponent handleMenuClick={handleMenuClick} />;
|
return <HeaderComponent />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(HeaderContainer);
|
export default connect(null, null)(HeaderContainer);
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ function JobLinesUpsertModalContainer({ jobLineEditModal, toggleModalVisible, bo
|
|||||||
refetchQueries: ["GET_LINE_TICKET_BY_PK"]
|
refetchQueries: ["GET_LINE_TICKET_BY_PK"]
|
||||||
});
|
});
|
||||||
if (!r.errors) {
|
if (!r.errors) {
|
||||||
|
if (CriticalPartsScanning.treatment === "on") {
|
||||||
|
await CriticalPartsScan(jobLineEditModal.context.jobid, notification);
|
||||||
|
}
|
||||||
await Axios.post("/job/totalsssu", {
|
await Axios.post("/job/totalsssu", {
|
||||||
id: jobLineEditModal.context.jobid
|
id: jobLineEditModal.context.jobid
|
||||||
});
|
});
|
||||||
@@ -107,7 +110,9 @@ function JobLinesUpsertModalContainer({ jobLineEditModal, toggleModalVisible, bo
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (CriticalPartsScanning.treatment === "on") {
|
||||||
|
await CriticalPartsScan(jobLineEditModal.context.jobid, notification);
|
||||||
|
}
|
||||||
if (jobLineEditModal.actions.submit) {
|
if (jobLineEditModal.actions.submit) {
|
||||||
jobLineEditModal.actions.submit();
|
jobLineEditModal.actions.submit();
|
||||||
} else {
|
} else {
|
||||||
@@ -115,9 +120,7 @@ function JobLinesUpsertModalContainer({ jobLineEditModal, toggleModalVisible, bo
|
|||||||
}
|
}
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
}
|
}
|
||||||
if (CriticalPartsScanning.treatment === "on") {
|
|
||||||
CriticalPartsScan(jobLineEditModal.context.jobid, notification);
|
|
||||||
}
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -172,13 +172,13 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
|
|||||||
job: newJob
|
job: newJob
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (CriticalPartsScanning.treatment === "on") {
|
||||||
|
await CriticalPartsScan(r.data.insert_jobs.returning[0].id, notification);
|
||||||
|
}
|
||||||
await Axios.post("/job/totalsssu", {
|
await Axios.post("/job/totalsssu", {
|
||||||
id: r.data.insert_jobs.returning[0].id
|
id: r.data.insert_jobs.returning[0].id
|
||||||
});
|
});
|
||||||
|
|
||||||
if (CriticalPartsScanning.treatment === "on") {
|
|
||||||
CriticalPartsScan(r.data.insert_jobs.returning[0].id, notification);
|
|
||||||
}
|
|
||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("jobs.successes.created"),
|
message: t("jobs.successes.created"),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@@ -281,6 +281,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
|
|||||||
if (CriticalPartsScanning.treatment === "on") {
|
if (CriticalPartsScanning.treatment === "on") {
|
||||||
CriticalPartsScan(updateResult.data.update_jobs.returning[0].id, notification);
|
CriticalPartsScan(updateResult.data.update_jobs.returning[0].id, notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateResult.errors) {
|
if (updateResult.errors) {
|
||||||
//error while inserting
|
//error while inserting
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
import {DeleteFilled} from "@ant-design/icons";
|
import { DeleteFilled } from "@ant-design/icons";
|
||||||
import {Button, Col, Form, Input, Row, Select, Space, Switch} from "antd";
|
import { Button, Col, Form, Input, Row, Select, Space, Switch } from "antd";
|
||||||
import React, {useMemo} from "react";
|
import { useMemo } from "react";
|
||||||
import {useTranslation} from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
import i18n from "i18next";
|
||||||
|
|
||||||
const predefinedPartTypes = [
|
const predefinedPartTypes = ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"];
|
||||||
"PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"
|
|
||||||
];
|
|
||||||
const predefinedModLbrTypes = [
|
const predefinedModLbrTypes = [
|
||||||
"LAA", "LAB", "LAD", "LAE", "LAF", "LAG", "LAM", "LAR", "LAS", "LAU",
|
"LAA",
|
||||||
"LA1", "LA2", "LA3", "LA4"
|
"LAB",
|
||||||
|
"LAD",
|
||||||
|
"LAE",
|
||||||
|
"LAF",
|
||||||
|
"LAG",
|
||||||
|
"LAM",
|
||||||
|
"LAR",
|
||||||
|
"LAS",
|
||||||
|
"LAU",
|
||||||
|
"LA1",
|
||||||
|
"LA2",
|
||||||
|
"LA3",
|
||||||
|
"LA4"
|
||||||
];
|
];
|
||||||
|
|
||||||
const getFieldType = (field) => {
|
const getFieldType = (field) => {
|
||||||
@@ -20,30 +31,46 @@ const getFieldType = (field) => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ShopInfoPartsScan({form}) {
|
const fieldSelectOptions = [
|
||||||
const {t} = useTranslation();
|
{ label: i18n.t("joblines.fields.line_desc"), value: "line_desc" },
|
||||||
|
{ label: i18n.t("joblines.fields.part_type"), value: "part_type" },
|
||||||
|
{ label: i18n.t("joblines.fields.act_price"), value: "act_price" },
|
||||||
|
{ label: i18n.t("joblines.fields.part_qty"), value: "part_qty" },
|
||||||
|
{ label: i18n.t("joblines.fields.mod_lbr_ty"), value: "mod_lbr_ty" },
|
||||||
|
|
||||||
|
{
|
||||||
|
label: `${i18n.t("joblines.fields.oem_partno")} / ${i18n.t("joblines.fields.alt_partno")}`,
|
||||||
|
value: "part_number"
|
||||||
|
},
|
||||||
|
{ label: i18n.t("joblines.fields.op_code_desc"), value: "op_code_desc" }
|
||||||
|
];
|
||||||
|
export default function ShopInfoPartsScan({ form }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const watchedFields = Form.useWatch("md_parts_scan", form);
|
const watchedFields = Form.useWatch("md_parts_scan", form);
|
||||||
|
|
||||||
const operationOptions = useMemo(() => ({
|
const operationOptions = useMemo(
|
||||||
string: [
|
() => ({
|
||||||
{label: t("bodyshop.operations.contains"), value: "contains"},
|
string: [
|
||||||
{label: t("bodyshop.operations.equals"), value: "equals"},
|
{ label: t("bodyshop.operations.contains"), value: "contains" },
|
||||||
{label: t("bodyshop.operations.starts_with"), value: "startsWith"},
|
{ label: t("bodyshop.operations.equals"), value: "equals" },
|
||||||
{label: t("bodyshop.operations.ends_with"), value: "endsWith"},
|
{ label: t("bodyshop.operations.starts_with"), value: "startsWith" },
|
||||||
],
|
{ label: t("bodyshop.operations.ends_with"), value: "endsWith" }
|
||||||
number: [
|
],
|
||||||
{label: t("bodyshop.operations.equals"), value: "="},
|
number: [
|
||||||
{label: t("bodyshop.operations.greater_than"), value: ">"},
|
{ label: t("bodyshop.operations.equals"), value: "=" },
|
||||||
{label: t("bodyshop.operations.less_than"), value: "<"},
|
{ label: t("bodyshop.operations.greater_than"), value: ">" },
|
||||||
],
|
{ label: t("bodyshop.operations.less_than"), value: "<" }
|
||||||
}), [t]);
|
]
|
||||||
|
}),
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<LayoutFormRow header={t("bodyshop.labels.md_parts_scan")}>
|
<LayoutFormRow header={t("bodyshop.labels.md_parts_scan")}>
|
||||||
<Form.List name={["md_parts_scan"]}>
|
<Form.List name={["md_parts_scan"]}>
|
||||||
{(fields, {add, remove, move}) => (
|
{(fields, { add, remove, move }) => (
|
||||||
<div>
|
<div>
|
||||||
{fields.map((field, index) => {
|
{fields.map((field, index) => {
|
||||||
const selectedField = watchedFields?.[index]?.field || "line_desc";
|
const selectedField = watchedFields?.[index]?.field || "line_desc";
|
||||||
@@ -61,28 +88,17 @@ export default function ShopInfoPartsScan({form}) {
|
|||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required", {
|
message: t("general.validation.required", {
|
||||||
label: t("bodyshop.fields.md_parts_scan.field"),
|
label: t("bodyshop.fields.md_parts_scan.field")
|
||||||
}),
|
})
|
||||||
},
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={fieldSelectOptions}
|
||||||
{label: t("joblines.fields.line_desc"), value: "line_desc"},
|
|
||||||
{label: t("joblines.fields.part_type"), value: "part_type"},
|
|
||||||
{label: t("joblines.fields.act_price"), value: "act_price"},
|
|
||||||
{label: t("joblines.fields.part_qty"), value: "part_qty"},
|
|
||||||
{label: t("joblines.fields.mod_lbr_ty"), value: "mod_lbr_ty"},
|
|
||||||
{label: t("joblines.fields.mod_lb_hrs"), value: "mod_lb_hrs"},
|
|
||||||
{
|
|
||||||
label: `${t("joblines.fields.oem_partno")} / ${t("joblines.fields.alt_partno")}`,
|
|
||||||
value: "part_number"
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
form.setFields([
|
form.setFields([
|
||||||
{name: ["md_parts_scan", index, "operation"], value: "contains"},
|
{ name: ["md_parts_scan", index, "operation"], value: "contains" },
|
||||||
{name: ["md_parts_scan", index, "value"], value: undefined},
|
{ name: ["md_parts_scan", index, "value"], value: undefined }
|
||||||
]);
|
]);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -99,12 +115,12 @@ export default function ShopInfoPartsScan({form}) {
|
|||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required", {
|
message: t("general.validation.required", {
|
||||||
label: t("bodyshop.fields.md_parts_scan.operation"),
|
label: t("bodyshop.fields.md_parts_scan.operation")
|
||||||
}),
|
})
|
||||||
},
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Select options={operationOptions[fieldType]}/>
|
<Select options={operationOptions[fieldType]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
@@ -119,9 +135,9 @@ export default function ShopInfoPartsScan({form}) {
|
|||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required", {
|
message: t("general.validation.required", {
|
||||||
label: t("bodyshop.fields.md_parts_scan.value"),
|
label: t("bodyshop.fields.md_parts_scan.value")
|
||||||
}),
|
})
|
||||||
},
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{fieldType === "predefined" ? (
|
{fieldType === "predefined" ? (
|
||||||
@@ -129,17 +145,17 @@ export default function ShopInfoPartsScan({form}) {
|
|||||||
options={
|
options={
|
||||||
selectedField === "part_type"
|
selectedField === "part_type"
|
||||||
? predefinedPartTypes.map((type) => ({
|
? predefinedPartTypes.map((type) => ({
|
||||||
label: type,
|
label: type,
|
||||||
value: type
|
value: type
|
||||||
}))
|
}))
|
||||||
: predefinedModLbrTypes.map((type) => ({
|
: predefinedModLbrTypes.map((type) => ({
|
||||||
label: type,
|
label: type,
|
||||||
value: type
|
value: type
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Input/>
|
<Input />
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
@@ -152,19 +168,70 @@ export default function ShopInfoPartsScan({form}) {
|
|||||||
label={t("bodyshop.fields.md_parts_scan.caseInsensitive")}
|
label={t("bodyshop.fields.md_parts_scan.caseInsensitive")}
|
||||||
name={[field.name, "caseInsensitive"]}
|
name={[field.name, "caseInsensitive"]}
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
labelCol={{span: 14}}
|
initialValue={true}
|
||||||
wrapperCol={{span: 10}}
|
labelCol={{ span: 14 }}
|
||||||
|
wrapperCol={{ span: 10 }}
|
||||||
>
|
>
|
||||||
<Switch defaultChecked={true}/>
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Mark Line as Critical */}
|
||||||
|
<Col span={4}>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.md_parts_scan.mark_critical")}
|
||||||
|
name={[field.name, "mark_critical"]}
|
||||||
|
valuePropName="checked"
|
||||||
|
initialValue={true}
|
||||||
|
labelCol={{ span: 14 }}
|
||||||
|
wrapperCol={{ span: 10 }}
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
{/* Update Field */}
|
||||||
|
<Col span={4}>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.md_parts_scan.update_field")}
|
||||||
|
name={[field.name, "update_field"]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={fieldSelectOptions}
|
||||||
|
allowClear
|
||||||
|
onClear={() =>
|
||||||
|
form.setFields([{ name: ["md_parts_scan", index, "update_field"], value: null }])
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
{/* Update Field */}
|
||||||
|
<Col span={4}>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.md_parts_scan.update_value")}
|
||||||
|
name={[field.name, "update_value"]}
|
||||||
|
dependencies={[["md_parts_scan", index, "update_field"]]}
|
||||||
|
tooltip={t("bodyshop.tooltips.md_parts_scan.update_value_tooltip")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: form.getFieldValue(["md_parts_scan", index, "update_field"]),
|
||||||
|
message: t("general.validation.required", {
|
||||||
|
label: t("bodyshop.fields.md_parts_scan.update_value")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<Col span={2}>
|
<Col span={2}>
|
||||||
<Space>
|
<Space>
|
||||||
<DeleteFilled onClick={() => remove(field.name)}/>
|
<DeleteFilled onClick={() => remove(field.name)} />
|
||||||
<FormListMoveArrows move={move} index={index} total={fields.length}/>
|
<FormListMoveArrows move={move} index={index} total={fields.length} />
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
@@ -175,8 +242,8 @@ export default function ShopInfoPartsScan({form}) {
|
|||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Button
|
<Button
|
||||||
type="dashed"
|
type="dashed"
|
||||||
onClick={() => add({field: "line_desc", operation: "contains"})}
|
onClick={() => add({ field: "line_desc", operation: "contains" })}
|
||||||
style={{width: "100%"}}
|
style={{ width: "100%" }}
|
||||||
>
|
>
|
||||||
{t("bodyshop.actions.addpartsrule")}
|
{t("bodyshop.actions.addpartsrule")}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -1890,6 +1890,7 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
|
|||||||
kmout
|
kmout
|
||||||
qb_multiple_payers
|
qb_multiple_payers
|
||||||
lbr_adjustments
|
lbr_adjustments
|
||||||
|
ownr_ea
|
||||||
payments {
|
payments {
|
||||||
amount
|
amount
|
||||||
created_at
|
created_at
|
||||||
|
|||||||
@@ -347,6 +347,9 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
|
|||||||
window.$zoho.salesiq.visitor.info({ "Shop Name": payload.shopname });
|
window.$zoho.salesiq.visitor.info({ "Shop Name": payload.shopname });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
payload.features?.allAccess === true
|
||||||
|
? window.$crisp.push(["set", "session:segments", [["allAccess"]]])
|
||||||
|
: window.$crisp.push(["set", "session:segments", [["basic"]]]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Couldnt find $crisp.");
|
console.error("Couldnt find $crisp.");
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -55,7 +55,7 @@ exports.default = async (req, res) => {
|
|||||||
const csv = converter.json2csv(shopList, { emptyFieldValue: "" });
|
const csv = converter.json2csv(shopList, { emptyFieldValue: "" });
|
||||||
emailer
|
emailer
|
||||||
.sendTaskEmail({
|
.sendTaskEmail({
|
||||||
to: ["patrick.fic@convenient-brands.com", "bradley.rhoades@convenient-brands.com"],
|
to: ["patrick.fic@convenient-brands.com", "bradley.rhoades@convenient-brands.com", "jrome@rometech.com"],
|
||||||
subject: `RO Usage Report - ${moment().format("MM/DD/YYYY")}`,
|
subject: `RO Usage Report - ${moment().format("MM/DD/YYYY")}`,
|
||||||
text: `
|
text: `
|
||||||
Usage Report for ${moment().format("MM/DD/YYYY")} for Rome Online Customers.
|
Usage Report for ${moment().format("MM/DD/YYYY")} for Rome Online Customers.
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const sendServerEmail = async ({ subject, text }) => {
|
|||||||
imex: `ImEX Online API - ${process.env.NODE_ENV} <noreply@imex.online>`,
|
imex: `ImEX Online API - ${process.env.NODE_ENV} <noreply@imex.online>`,
|
||||||
rome: `Rome Online API - ${process.env.NODE_ENV} <noreply@romeonline.io>`
|
rome: `Rome Online API - ${process.env.NODE_ENV} <noreply@romeonline.io>`
|
||||||
}),
|
}),
|
||||||
to: ["patrick@imexsystems.ca", "support@thinkimex.com"],
|
to: ["support@thinkimex.com"],
|
||||||
subject: subject,
|
subject: subject,
|
||||||
text: text,
|
text: text,
|
||||||
ses: {
|
ses: {
|
||||||
@@ -92,7 +92,7 @@ const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachmen
|
|||||||
},
|
},
|
||||||
(err, info) => {
|
(err, info) => {
|
||||||
// (message, type, user, record, meta
|
// (message, type, user, record, meta
|
||||||
logger.log("server-email", err ? "error" : "debug", null, null, { message: err || info });
|
logger.log("server-email", err ? "error" : "debug", null, null, { message: err ? err?.message : info });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -239,24 +239,24 @@ const emailBounce = async (req, res) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//If it's bounced, log it as bounced in audit log. Send an email to the user.
|
//If it's bounced, log it as bounced in audit log. Send an email to the user.
|
||||||
const result = await client.request(queries.UPDATE_EMAIL_AUDIT, {
|
await client.request(queries.UPDATE_EMAIL_AUDIT, {
|
||||||
sesid: messageId,
|
sesid: messageId,
|
||||||
status: "Bounced",
|
status: "Bounced",
|
||||||
context: message.bounce?.bouncedRecipients
|
context: message.bounce?.bouncedRecipients
|
||||||
});
|
});
|
||||||
mailer.sendMail(
|
mailer.sendMail(
|
||||||
{
|
{
|
||||||
from: InstanceMgr({
|
from: InstanceManager({
|
||||||
imex: `ImEX Online <noreply@imex.online>`,
|
imex: `ImEX Online <noreply@imex.online>`,
|
||||||
rome: `Rome Online <noreply@romeonline.io>`
|
rome: `Rome Online <noreply@romeonline.io>`
|
||||||
}),
|
}),
|
||||||
to: replyTo,
|
to: replyTo,
|
||||||
//bcc: "patrick@snapt.ca",
|
//bcc: "patrick@snapt.ca",
|
||||||
subject: `${InstanceMgr({
|
subject: `${InstanceManager({
|
||||||
imex: "ImEX Online",
|
imex: "ImEX Online",
|
||||||
rome: "Rome Online"
|
rome: "Rome Online"
|
||||||
})} Bounced Email - RE: ${subject}`,
|
})} Bounced Email - RE: ${subject}`,
|
||||||
text: `${InstanceMgr({
|
text: `${InstanceManager({
|
||||||
imex: "ImEX Online",
|
imex: "ImEX Online",
|
||||||
rome: "Rome Online"
|
rome: "Rome Online"
|
||||||
})} has tried to deliver an email with the subject: ${subject} to the intended recipients but encountered an error.
|
})} has tried to deliver an email with the subject: ${subject} to the intended recipients but encountered an error.
|
||||||
@@ -270,7 +270,7 @@ ${body.bounce?.bouncedRecipients.map(
|
|||||||
},
|
},
|
||||||
(err, info) => {
|
(err, info) => {
|
||||||
logger.log("sns-error", err ? "error" : "debug", "api", null, {
|
logger.log("sns-error", err ? "error" : "debug", "api", null, {
|
||||||
message: err ? JSON.stringify(error) : info
|
message: err ? err?.message : info
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2241,6 +2241,7 @@ exports.QUERY_PARTS_SCAN = `query QUERY_PARTS_SCAN ($id: uuid!) {
|
|||||||
mod_lb_hrs
|
mod_lb_hrs
|
||||||
oem_partno
|
oem_partno
|
||||||
alt_partno
|
alt_partno
|
||||||
|
op_code_desc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
@@ -2252,7 +2253,7 @@ exports.UPDATE_PARTS_CRITICAL = `mutation UPDATE_PARTS_CRITICAL ($IdsToMarkCriti
|
|||||||
notcritical: update_joblines(where: {id: {_nin: $IdsToMarkCritical}, jobid: {_eq: $jobid}}, _set: {critical: false}) {
|
notcritical: update_joblines(where: {id: {_nin: $IdsToMarkCritical}, jobid: {_eq: $jobid}}, _set: {critical: false}) {
|
||||||
affected_rows
|
affected_rows
|
||||||
}
|
}
|
||||||
}`;
|
}`;;
|
||||||
|
|
||||||
exports.ACTIVE_SHOP_BY_USER = `query ACTIVE_SHOP_BY_USER($user: String) {
|
exports.ACTIVE_SHOP_BY_USER = `query ACTIVE_SHOP_BY_USER($user: String) {
|
||||||
associations(where: {active: {_eq: true}, useremail: {_eq: $user}}) {
|
associations(where: {active: {_eq: true}, useremail: {_eq: $user}}) {
|
||||||
@@ -2690,6 +2691,23 @@ exports.STATUS_UPDATE = `query STATUS_UPDATE($period: timestamptz!, $today: time
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports.INSERT_AUDIT_TRAIL = `
|
||||||
|
mutation INSERT_AUDIT_TRAIL($auditObj: audit_trail_insert_input!) {
|
||||||
|
insert_audit_trail_one(object: $auditObj) {
|
||||||
|
id
|
||||||
|
jobid
|
||||||
|
billid
|
||||||
|
bodyshopid
|
||||||
|
created
|
||||||
|
operation
|
||||||
|
type
|
||||||
|
useremail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.GET_DOCUMENTS_BY_JOB = `
|
exports.GET_DOCUMENTS_BY_JOB = `
|
||||||
query GET_DOCUMENTS_BY_JOB($jobId: uuid!) {
|
query GET_DOCUMENTS_BY_JOB($jobId: uuid!) {
|
||||||
jobs_by_pk(id: $jobId) {
|
jobs_by_pk(id: $jobId) {
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ async function OpenSearchUpdateHandler(req, res) {
|
|||||||
break;
|
break;
|
||||||
case "payments":
|
case "payments":
|
||||||
//Query to get the job and RO number
|
//Query to get the job and RO number
|
||||||
|
|
||||||
const payment = await client.request(
|
const payment = await client.request(
|
||||||
`query ADMIN_GET_PAYMENT_BY_ID($paymentId: uuid!) {
|
`query ADMIN_GET_PAYMENT_BY_ID($paymentId: uuid!) {
|
||||||
payments_by_pk(id: $paymentId) {
|
payments_by_pk(id: $paymentId) {
|
||||||
@@ -147,11 +148,25 @@ async function OpenSearchUpdateHandler(req, res) {
|
|||||||
body: document
|
body: document
|
||||||
};
|
};
|
||||||
|
|
||||||
|
logger.log("os-handler", "DEBUG", null, null, {
|
||||||
|
id: req.body.event.data.new.id,
|
||||||
|
index: req.body.table.name,
|
||||||
|
bodyshopid: payload.body.bodyshopid
|
||||||
|
// body: document
|
||||||
|
});
|
||||||
|
|
||||||
const response = await osClient.index(payload);
|
const response = await osClient.index(payload);
|
||||||
//console.log(response.body);
|
//console.log(response.body);
|
||||||
res.status(200).json(response.body);
|
res.status(200).json(response.body);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
logger.log("os-handler-error", "ERROR", null, null, {
|
||||||
|
id: req.body.event.data.new.id,
|
||||||
|
index: req.body.table.name,
|
||||||
|
message: error.message,
|
||||||
|
stack: error.stack
|
||||||
|
// body: document
|
||||||
|
});
|
||||||
res.status(400).json(JSON.stringify(error));
|
res.status(400).json(JSON.stringify(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,7 +181,9 @@ async function OpenSearchSearchHandler(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.log("os-search", "DEBUG", req.user.email, null, {
|
logger.log("os-search", "DEBUG", req.user.email, null, {
|
||||||
search
|
search,
|
||||||
|
index,
|
||||||
|
bodyshopid
|
||||||
});
|
});
|
||||||
|
|
||||||
const BearerToken = req.BearerToken;
|
const BearerToken = req.BearerToken;
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
const queries = require("../graphql-client/queries");
|
const queries = require("../graphql-client/queries");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
|
|
||||||
const predefinedPartTypes = [
|
const predefinedPartTypes = ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"];
|
||||||
"PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG",
|
|
||||||
];
|
|
||||||
const predefinedModLbrTypes = [
|
const predefinedModLbrTypes = [
|
||||||
"LAA", "LAB", "LAD", "LAE", "LAF", "LAG", "LAM", "LAR", "LAS", "LAU",
|
"LAA",
|
||||||
"LA1", "LA2", "LA3", "LA4",
|
"LAB",
|
||||||
|
"LAD",
|
||||||
|
"LAE",
|
||||||
|
"LAF",
|
||||||
|
"LAG",
|
||||||
|
"LAM",
|
||||||
|
"LAR",
|
||||||
|
"LAS",
|
||||||
|
"LAU",
|
||||||
|
"LA1",
|
||||||
|
"LA2",
|
||||||
|
"LA3",
|
||||||
|
"LA4"
|
||||||
];
|
];
|
||||||
|
|
||||||
exports.partsScan = async function (req, res) {
|
exports.partsScan = async function (req, res) {
|
||||||
console.log('hello')
|
|
||||||
const { jobid } = req.body;
|
const { jobid } = req.body;
|
||||||
const BearerToken = req.BearerToken;
|
const BearerToken = req.BearerToken;
|
||||||
const client = req.userGraphQLClient;
|
const client = req.userGraphQLClient;
|
||||||
@@ -18,10 +27,9 @@ exports.partsScan = async function (req, res) {
|
|||||||
logger.log("job-parts-scan", "DEBUG", req.user?.email, jobid, null);
|
logger.log("job-parts-scan", "DEBUG", req.user?.email, jobid, null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await client.setHeaders({ Authorization: BearerToken }).request(
|
const data = await client
|
||||||
queries.QUERY_PARTS_SCAN,
|
.setHeaders({ Authorization: BearerToken })
|
||||||
{ id: jobid }
|
.request(queries.QUERY_PARTS_SCAN, { id: jobid });
|
||||||
);
|
|
||||||
|
|
||||||
const rules = data.jobs_by_pk.bodyshop.md_parts_scan || [];
|
const rules = data.jobs_by_pk.bodyshop.md_parts_scan || [];
|
||||||
if (!Array.isArray(rules)) {
|
if (!Array.isArray(rules)) {
|
||||||
@@ -36,21 +44,22 @@ exports.partsScan = async function (req, res) {
|
|||||||
? new RegExp(rule.value, "i")
|
? new RegExp(rule.value, "i")
|
||||||
: typeof rule.value === "string"
|
: typeof rule.value === "string"
|
||||||
? new RegExp(rule.value)
|
? new RegExp(rule.value)
|
||||||
: null,
|
: null
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const criticalIds = new Set();
|
const criticalIds = new Set();
|
||||||
|
|
||||||
for (const jobline of data.jobs_by_pk.joblines) {
|
for (const jobline of data.jobs_by_pk.joblines) {
|
||||||
for (const { field, regex, operation, value } of compiledRules) {
|
for (const { field, regex, operation, value, mark_critical, update_field, update_value } of compiledRules) {
|
||||||
if (criticalIds.has(jobline.id)) break; // Skip further evaluation if already critical
|
// IO-3077 - Remove skip as this is extended to include line updates.
|
||||||
|
// if (criticalIds.has(jobline.id)) break; // Skip further evaluation if already critical
|
||||||
|
|
||||||
let jobValue = jobline[field];
|
let jobValue = jobline[field];
|
||||||
let match = false;
|
let match = false;
|
||||||
|
|
||||||
if (field === "part_number") {
|
if (field === "part_number") {
|
||||||
match = regex
|
match = regex
|
||||||
? regex.test(jobline.oem_partno || '') || regex.test(jobline.alt_partno || '')
|
? regex.test(jobline.oem_partno || "") || regex.test(jobline.alt_partno || "")
|
||||||
: jobline.oem_partno === value || jobline.alt_partno === value;
|
: jobline.oem_partno === value || jobline.alt_partno === value;
|
||||||
} else if (field === "part_type") {
|
} else if (field === "part_type") {
|
||||||
match = predefinedPartTypes.includes(value) && value === jobValue;
|
match = predefinedPartTypes.includes(value) && value === jobValue;
|
||||||
@@ -68,22 +77,44 @@ exports.partsScan = async function (req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
criticalIds.add(jobline.id);
|
if (mark_critical) {
|
||||||
break; // No need to evaluate further rules for this jobline
|
//Could technically lead to duplicates, but they'd only be n positives, ultimately leading a positive.
|
||||||
|
criticalIds.add(jobline.id);
|
||||||
|
}
|
||||||
|
if (update_field && update_value) {
|
||||||
|
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB_LINE, {
|
||||||
|
lineId: jobline.id,
|
||||||
|
line: { [update_field]: update_value, manual_line: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
const auditResult = await client
|
||||||
|
.setHeaders({ Authorization: BearerToken })
|
||||||
|
.request(queries.INSERT_AUDIT_TRAIL, {
|
||||||
|
auditObj: {
|
||||||
|
bodyshopid: data.jobs_by_pk.bodyshop.id,
|
||||||
|
jobid,
|
||||||
|
operation: `Jobline (#${jobline.line_no} ${jobline.line_desc}/${jobline.id}) ${update_field} updated from ${jobline[update_field]} to ${update_value}. Lined marked as manual line.`,
|
||||||
|
type: "partscanupdate",
|
||||||
|
useremail: req.user.email
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//break; // No need to evaluate further rules for this jobline
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await client.setHeaders({ Authorization: BearerToken }).request(
|
const result = await client
|
||||||
queries.UPDATE_PARTS_CRITICAL,
|
.setHeaders({ Authorization: BearerToken })
|
||||||
{ IdsToMarkCritical: Array.from(criticalIds), jobid }
|
.request(queries.UPDATE_PARTS_CRITICAL, { IdsToMarkCritical: Array.from(criticalIds), jobid });
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).json(result);
|
res.status(200).json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.log("job-parts-scan-error", "ERROR", req.user?.email, jobid, {
|
logger.log("job-parts-scan-error", "ERROR", req.user?.email, jobid, {
|
||||||
jobid,
|
jobid,
|
||||||
error: error.message,
|
error: error.message,
|
||||||
|
stack: error.stack
|
||||||
});
|
});
|
||||||
res.status(400).json(JSON.stringify({ message: error?.message }));
|
res.status(400).json(JSON.stringify({ message: error?.message }));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user