IO-3077 Implement import rules engine.
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
|
||||
@@ -6453,6 +6453,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>operation</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -6474,6 +6495,48 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>value</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -11943,6 +12006,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>shopinfo</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -12312,6 +12396,37 @@
|
||||
</concept_node>
|
||||
</children>
|
||||
</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>
|
||||
<name>validation</name>
|
||||
<children>
|
||||
@@ -19091,6 +19206,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>previous</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -19385,6 +19521,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>submit</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -43090,6 +43247,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>print</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -48557,6 +48735,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>vertical</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -52732,6 +52931,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
<name>purchases_by_date_range_detail</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -54483,6 +54703,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</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>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
import {DeleteFilled} from "@ant-design/icons";
|
||||
import {Button, Col, Form, Input, Row, Select, Space, Switch} from "antd";
|
||||
import React, {useMemo} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import { DeleteFilled } from "@ant-design/icons";
|
||||
import { Button, Col, Form, Input, Row, Select, Space, Switch } from "antd";
|
||||
import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import i18n from "i18next";
|
||||
|
||||
const predefinedPartTypes = [
|
||||
"PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"
|
||||
];
|
||||
const predefinedPartTypes = ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"];
|
||||
const predefinedModLbrTypes = [
|
||||
"LAA", "LAB", "LAD", "LAE", "LAF", "LAG", "LAM", "LAR", "LAS", "LAU",
|
||||
"LA1", "LA2", "LA3", "LA4"
|
||||
"LAA",
|
||||
"LAB",
|
||||
"LAD",
|
||||
"LAE",
|
||||
"LAF",
|
||||
"LAG",
|
||||
"LAM",
|
||||
"LAR",
|
||||
"LAS",
|
||||
"LAU",
|
||||
"LA1",
|
||||
"LA2",
|
||||
"LA3",
|
||||
"LA4"
|
||||
];
|
||||
|
||||
const getFieldType = (field) => {
|
||||
@@ -20,30 +31,46 @@ const getFieldType = (field) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export default function ShopInfoPartsScan({form}) {
|
||||
const {t} = useTranslation();
|
||||
const fieldSelectOptions = [
|
||||
{ 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 operationOptions = useMemo(() => ({
|
||||
const operationOptions = useMemo(
|
||||
() => ({
|
||||
string: [
|
||||
{label: t("bodyshop.operations.contains"), value: "contains"},
|
||||
{label: t("bodyshop.operations.equals"), value: "equals"},
|
||||
{label: t("bodyshop.operations.starts_with"), value: "startsWith"},
|
||||
{label: t("bodyshop.operations.ends_with"), value: "endsWith"},
|
||||
{ label: t("bodyshop.operations.contains"), value: "contains" },
|
||||
{ label: t("bodyshop.operations.equals"), value: "equals" },
|
||||
{ label: t("bodyshop.operations.starts_with"), value: "startsWith" },
|
||||
{ label: t("bodyshop.operations.ends_with"), value: "endsWith" }
|
||||
],
|
||||
number: [
|
||||
{label: t("bodyshop.operations.equals"), value: "="},
|
||||
{label: t("bodyshop.operations.greater_than"), value: ">"},
|
||||
{label: t("bodyshop.operations.less_than"), value: "<"},
|
||||
],
|
||||
}), [t]);
|
||||
{ label: t("bodyshop.operations.equals"), value: "=" },
|
||||
{ label: t("bodyshop.operations.greater_than"), value: ">" },
|
||||
{ label: t("bodyshop.operations.less_than"), value: "<" }
|
||||
]
|
||||
}),
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<LayoutFormRow header={t("bodyshop.labels.md_parts_scan")}>
|
||||
<Form.List name={["md_parts_scan"]}>
|
||||
{(fields, {add, remove, move}) => (
|
||||
{(fields, { add, remove, move }) => (
|
||||
<div>
|
||||
{fields.map((field, index) => {
|
||||
const selectedField = watchedFields?.[index]?.field || "line_desc";
|
||||
@@ -61,28 +88,17 @@ export default function ShopInfoPartsScan({form}) {
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required", {
|
||||
label: t("bodyshop.fields.md_parts_scan.field"),
|
||||
}),
|
||||
},
|
||||
label: t("bodyshop.fields.md_parts_scan.field")
|
||||
})
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
options={[
|
||||
{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"
|
||||
},
|
||||
]}
|
||||
options={fieldSelectOptions}
|
||||
onChange={() => {
|
||||
form.setFields([
|
||||
{name: ["md_parts_scan", index, "operation"], value: "contains"},
|
||||
{name: ["md_parts_scan", index, "value"], value: undefined},
|
||||
{ name: ["md_parts_scan", index, "operation"], value: "contains" },
|
||||
{ name: ["md_parts_scan", index, "value"], value: undefined }
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
@@ -99,12 +115,12 @@ export default function ShopInfoPartsScan({form}) {
|
||||
{
|
||||
required: true,
|
||||
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>
|
||||
</Col>
|
||||
)}
|
||||
@@ -119,9 +135,9 @@ export default function ShopInfoPartsScan({form}) {
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required", {
|
||||
label: t("bodyshop.fields.md_parts_scan.value"),
|
||||
}),
|
||||
},
|
||||
label: t("bodyshop.fields.md_parts_scan.value")
|
||||
})
|
||||
}
|
||||
]}
|
||||
>
|
||||
{fieldType === "predefined" ? (
|
||||
@@ -139,7 +155,7 @@ export default function ShopInfoPartsScan({form}) {
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Input/>
|
||||
<Input />
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
@@ -152,19 +168,70 @@ export default function ShopInfoPartsScan({form}) {
|
||||
label={t("bodyshop.fields.md_parts_scan.caseInsensitive")}
|
||||
name={[field.name, "caseInsensitive"]}
|
||||
valuePropName="checked"
|
||||
labelCol={{span: 14}}
|
||||
wrapperCol={{span: 10}}
|
||||
initialValue={true}
|
||||
labelCol={{ span: 14 }}
|
||||
wrapperCol={{ span: 10 }}
|
||||
>
|
||||
<Switch defaultChecked={true}/>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</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 */}
|
||||
<Col span={2}>
|
||||
<Space>
|
||||
<DeleteFilled onClick={() => remove(field.name)}/>
|
||||
<FormListMoveArrows move={move} index={index} total={fields.length}/>
|
||||
<DeleteFilled onClick={() => remove(field.name)} />
|
||||
<FormListMoveArrows move={move} index={index} total={fields.length} />
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -175,8 +242,8 @@ export default function ShopInfoPartsScan({form}) {
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add({field: "line_desc", operation: "contains"})}
|
||||
style={{width: "100%"}}
|
||||
onClick={() => add({ field: "line_desc", operation: "contains" })}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{t("bodyshop.actions.addpartsrule")}
|
||||
</Button>
|
||||
|
||||
@@ -383,7 +383,10 @@
|
||||
"expression": "",
|
||||
"field": "Field",
|
||||
"flags": "",
|
||||
"mark_critical": "Mark Line as Critical?",
|
||||
"operation": "Operation",
|
||||
"update_field": "Field to Update",
|
||||
"update_value": "Update Value",
|
||||
"value": "Value"
|
||||
},
|
||||
"md_payment_types": "Payment Types",
|
||||
@@ -707,13 +710,13 @@
|
||||
"romepay": "Rome Pay",
|
||||
"scheduling": "SMART Scheduling",
|
||||
"scoreboardsetup": "Scoreboard Setup",
|
||||
"shop_enabled_features": "Shop Enabled Features",
|
||||
"shopinfo": "Shop Information",
|
||||
"speedprint": "Speed Print Configuration",
|
||||
"ssbuckets": "Job Size Definitions",
|
||||
"systemsettings": "System Settings",
|
||||
"task-presets": "Task Presets",
|
||||
"workingdays": "Working Days",
|
||||
"shop_enabled_features": "Shop Enabled Features"
|
||||
"workingdays": "Working Days"
|
||||
},
|
||||
"operations": {
|
||||
"contains": "Contains",
|
||||
@@ -730,6 +733,11 @@
|
||||
"save": "Shop configuration saved successfully. ",
|
||||
"unsavedchanges": "Unsaved changes will be lost. Are you sure you want to continue?"
|
||||
},
|
||||
"tooltips": {
|
||||
"md_parts_scan": {
|
||||
"update_value_tooltip": "Some fields require coded values in order to function properly (e.g. labor and part types). Please reach out to support if you have any questions."
|
||||
}
|
||||
},
|
||||
"validation": {
|
||||
"centermustexist": "The chosen responsibility center does not exist.",
|
||||
"larsplit": "Refinish hour split must add up to 1.",
|
||||
@@ -1177,6 +1185,7 @@
|
||||
"edit": "Edit",
|
||||
"login": "Login",
|
||||
"next": "Next",
|
||||
"ok": "Ok",
|
||||
"previous": "Previous",
|
||||
"print": "Print",
|
||||
"refresh": "Refresh",
|
||||
@@ -1191,12 +1200,11 @@
|
||||
"send": "Send",
|
||||
"sendbysms": "Send by SMS",
|
||||
"senderrortosupport": "Send Error to Support",
|
||||
"sharetoteams": "Share to Teams",
|
||||
"submit": "Submit",
|
||||
"tryagain": "Try Again",
|
||||
"view": "View",
|
||||
"viewreleasenotes": "See What's Changed",
|
||||
"sharetoteams": "Share to Teams",
|
||||
"ok": "Ok"
|
||||
"viewreleasenotes": "See What's Changed"
|
||||
},
|
||||
"errors": {
|
||||
"fcm": "You must allow notification permissions to have real time messaging. Click to try again.",
|
||||
@@ -2858,10 +2866,10 @@
|
||||
"tasks": "Tasks",
|
||||
"totalhours": "Total Hrs ",
|
||||
"touchtime": "T/T",
|
||||
"unassigned": "Unassigned",
|
||||
"vertical": "Vertical",
|
||||
"viewname": "View Name",
|
||||
"wide": "Wide",
|
||||
"unassigned": "Unassigned"
|
||||
"wide": "Wide"
|
||||
},
|
||||
"options": {
|
||||
"horizontal": "Horizontal",
|
||||
|
||||
@@ -383,7 +383,10 @@
|
||||
"expression": "",
|
||||
"field": "",
|
||||
"flags": "",
|
||||
"mark_critical": "",
|
||||
"operation": "",
|
||||
"update_field": "",
|
||||
"update_value": "",
|
||||
"value": ""
|
||||
},
|
||||
"md_payment_types": "",
|
||||
@@ -707,13 +710,13 @@
|
||||
"romepay": "",
|
||||
"scheduling": "",
|
||||
"scoreboardsetup": "",
|
||||
"shop_enabled_features": "",
|
||||
"shopinfo": "",
|
||||
"speedprint": "",
|
||||
"ssbuckets": "",
|
||||
"systemsettings": "",
|
||||
"task-presets": "",
|
||||
"workingdays": "",
|
||||
"shop_enabled_features": ""
|
||||
"workingdays": ""
|
||||
},
|
||||
"operations": {
|
||||
"contains": "",
|
||||
@@ -730,6 +733,11 @@
|
||||
"save": "",
|
||||
"unsavedchanges": ""
|
||||
},
|
||||
"tooltips": {
|
||||
"md_parts_scan": {
|
||||
"update_value_tooltip": ""
|
||||
}
|
||||
},
|
||||
"validation": {
|
||||
"centermustexist": "",
|
||||
"larsplit": "",
|
||||
@@ -1177,6 +1185,7 @@
|
||||
"edit": "Editar",
|
||||
"login": "",
|
||||
"next": "",
|
||||
"ok": "",
|
||||
"previous": "",
|
||||
"print": "",
|
||||
"refresh": "",
|
||||
@@ -1191,12 +1200,11 @@
|
||||
"send": "",
|
||||
"sendbysms": "",
|
||||
"senderrortosupport": "",
|
||||
"sharetoteams": "",
|
||||
"submit": "",
|
||||
"tryagain": "",
|
||||
"view": "",
|
||||
"viewreleasenotes": "",
|
||||
"sharetoteams": "",
|
||||
"ok": ""
|
||||
"viewreleasenotes": ""
|
||||
},
|
||||
"errors": {
|
||||
"fcm": "",
|
||||
@@ -2858,10 +2866,10 @@
|
||||
"tasks": "",
|
||||
"totalhours": "",
|
||||
"touchtime": "",
|
||||
"unassigned": "",
|
||||
"vertical": "",
|
||||
"viewname": "",
|
||||
"wide": "",
|
||||
"unassigned": ""
|
||||
"wide": ""
|
||||
},
|
||||
"options": {
|
||||
"horizontal": "",
|
||||
|
||||
@@ -383,7 +383,10 @@
|
||||
"expression": "",
|
||||
"field": "",
|
||||
"flags": "",
|
||||
"mark_critical": "",
|
||||
"operation": "",
|
||||
"update_field": "",
|
||||
"update_value": "",
|
||||
"value": ""
|
||||
},
|
||||
"md_payment_types": "",
|
||||
@@ -707,13 +710,13 @@
|
||||
"romepay": "",
|
||||
"scheduling": "",
|
||||
"scoreboardsetup": "",
|
||||
"shop_enabled_features": "",
|
||||
"shopinfo": "",
|
||||
"speedprint": "",
|
||||
"ssbuckets": "",
|
||||
"systemsettings": "",
|
||||
"task-presets": "",
|
||||
"workingdays": "",
|
||||
"shop_enabled_features": ""
|
||||
"workingdays": ""
|
||||
},
|
||||
"operations": {
|
||||
"contains": "",
|
||||
@@ -730,6 +733,11 @@
|
||||
"save": "",
|
||||
"unsavedchanges": ""
|
||||
},
|
||||
"tooltips": {
|
||||
"md_parts_scan": {
|
||||
"update_value_tooltip": ""
|
||||
}
|
||||
},
|
||||
"validation": {
|
||||
"centermustexist": "",
|
||||
"larsplit": "",
|
||||
@@ -1177,6 +1185,7 @@
|
||||
"edit": "modifier",
|
||||
"login": "",
|
||||
"next": "",
|
||||
"ok": "",
|
||||
"previous": "",
|
||||
"print": "",
|
||||
"refresh": "",
|
||||
@@ -1191,12 +1200,11 @@
|
||||
"send": "",
|
||||
"sendbysms": "",
|
||||
"senderrortosupport": "",
|
||||
"sharetoteams": "",
|
||||
"submit": "",
|
||||
"tryagain": "",
|
||||
"view": "",
|
||||
"viewreleasenotes": "",
|
||||
"sharetoteams": "",
|
||||
"ok": ""
|
||||
"viewreleasenotes": ""
|
||||
},
|
||||
"errors": {
|
||||
"fcm": "",
|
||||
@@ -2858,10 +2866,10 @@
|
||||
"tasks": "",
|
||||
"totalhours": "",
|
||||
"touchtime": "",
|
||||
"unassigned": "",
|
||||
"vertical": "",
|
||||
"viewname": "",
|
||||
"wide": "",
|
||||
"unassigned": ""
|
||||
"wide": ""
|
||||
},
|
||||
"options": {
|
||||
"horizontal": "",
|
||||
|
||||
@@ -2241,6 +2241,7 @@ exports.QUERY_PARTS_SCAN = `query QUERY_PARTS_SCAN ($id: uuid!) {
|
||||
mod_lb_hrs
|
||||
oem_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}) {
|
||||
affected_rows
|
||||
}
|
||||
}`
|
||||
}`;
|
||||
|
||||
exports.ACTIVE_SHOP_BY_USER = `query ACTIVE_SHOP_BY_USER($user: String) {
|
||||
associations(where: {active: {_eq: true}, useremail: {_eq: $user}}) {
|
||||
@@ -2618,7 +2619,6 @@ exports.CREATE_CONVERSATION = `mutation CREATE_CONVERSATION($conversation: [conv
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
exports.STATUS_UPDATE = `query STATUS_UPDATE($period: timestamptz!, $today: timestamptz!) {
|
||||
bodyshops(where: { created_at: { _gte: $period } }) {
|
||||
shopname
|
||||
@@ -2689,4 +2689,19 @@ 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
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
const queries = require("../graphql-client/queries");
|
||||
const logger = require("../utils/logger");
|
||||
|
||||
const predefinedPartTypes = [
|
||||
"PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG",
|
||||
];
|
||||
const predefinedPartTypes = ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"];
|
||||
const predefinedModLbrTypes = [
|
||||
"LAA", "LAB", "LAD", "LAE", "LAF", "LAG", "LAM", "LAR", "LAS", "LAU",
|
||||
"LA1", "LA2", "LA3", "LA4",
|
||||
"LAA",
|
||||
"LAB",
|
||||
"LAD",
|
||||
"LAE",
|
||||
"LAF",
|
||||
"LAG",
|
||||
"LAM",
|
||||
"LAR",
|
||||
"LAS",
|
||||
"LAU",
|
||||
"LA1",
|
||||
"LA2",
|
||||
"LA3",
|
||||
"LA4"
|
||||
];
|
||||
|
||||
exports.partsScan = async function (req, res) {
|
||||
console.log('hello')
|
||||
const { jobid } = req.body;
|
||||
const BearerToken = req.BearerToken;
|
||||
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);
|
||||
|
||||
try {
|
||||
const data = await client.setHeaders({ Authorization: BearerToken }).request(
|
||||
queries.QUERY_PARTS_SCAN,
|
||||
{ id: jobid }
|
||||
);
|
||||
const data = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.QUERY_PARTS_SCAN, { id: jobid });
|
||||
|
||||
const rules = data.jobs_by_pk.bodyshop.md_parts_scan || [];
|
||||
if (!Array.isArray(rules)) {
|
||||
@@ -36,21 +44,22 @@ exports.partsScan = async function (req, res) {
|
||||
? new RegExp(rule.value, "i")
|
||||
: typeof rule.value === "string"
|
||||
? new RegExp(rule.value)
|
||||
: null,
|
||||
: null
|
||||
}));
|
||||
|
||||
const criticalIds = new Set();
|
||||
|
||||
for (const jobline of data.jobs_by_pk.joblines) {
|
||||
for (const { field, regex, operation, value } of compiledRules) {
|
||||
if (criticalIds.has(jobline.id)) break; // Skip further evaluation if already critical
|
||||
for (const { field, regex, operation, value, mark_critical, update_field, update_value } of compiledRules) {
|
||||
// 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 match = false;
|
||||
|
||||
if (field === "part_number") {
|
||||
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;
|
||||
} else if (field === "part_type") {
|
||||
match = predefinedPartTypes.includes(value) && value === jobValue;
|
||||
@@ -68,22 +77,44 @@ exports.partsScan = async function (req, res) {
|
||||
}
|
||||
|
||||
if (match) {
|
||||
if (mark_critical) {
|
||||
//Could technically lead to duplicates, but they'd only be n positives, ultimately leading a positive.
|
||||
criticalIds.add(jobline.id);
|
||||
break; // No need to evaluate further rules for this jobline
|
||||
}
|
||||
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_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(
|
||||
queries.UPDATE_PARTS_CRITICAL,
|
||||
{ IdsToMarkCritical: Array.from(criticalIds), jobid }
|
||||
);
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.UPDATE_PARTS_CRITICAL, { IdsToMarkCritical: Array.from(criticalIds), jobid });
|
||||
|
||||
res.status(200).json(result);
|
||||
} catch (error) {
|
||||
logger.log("job-parts-scan-error", "ERROR", req.user?.email, jobid, {
|
||||
jobid,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
res.status(400).json(JSON.stringify({ message: error?.message }));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user