Merged in release/2021-11-12 (pull request #264)
release/2021-11-12 Approved-by: Patrick Fic
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
|
||||||
@@ -8103,6 +8103,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>filehandlers</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>insurancecos</name>
|
<name>insurancecos</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -8664,6 +8685,27 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>validation</name>
|
<name>validation</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>centermustexist</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>larsplit</name>
|
<name>larsplit</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -17491,6 +17533,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>changefilehandler</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>changelaborrate</name>
|
<name>changelaborrate</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -19737,6 +19800,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>date_next_contact</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>date_open</name>
|
<name>date_open</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -29272,6 +29356,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>noattachedjobs</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>
|
||||||
@@ -29424,6 +29529,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>recentonly</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>selectmedia</name>
|
<name>selectmedia</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -30627,6 +30753,27 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>errors</name>
|
<name>errors</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>associatedbills</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>backordering</name>
|
<name>backordering</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -32874,6 +33021,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>ab_proof_of_loss</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>appointment_confirmation</name>
|
<name>appointment_confirmation</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -36465,6 +36633,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>open_orders_status</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>parts_backorder</name>
|
<name>parts_backorder</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -2,40 +2,40 @@
|
|||||||
"name": "bodyshop",
|
"name": "bodyshop",
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:5000",
|
"proxy": "http://localhost:4000",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.4.16",
|
"@apollo/client": "^3.4.16",
|
||||||
"@craco/craco": "^6.4.0",
|
"@craco/craco": "^6.4.0",
|
||||||
"@fingerprintjs/fingerprintjs": "^3.3.0",
|
"@fingerprintjs/fingerprintjs": "^3.3.0",
|
||||||
"@lourenci/react-kanban": "^2.1.0",
|
"@lourenci/react-kanban": "^2.1.0",
|
||||||
"@openreplay/tracker": "^3.4.4",
|
"@openreplay/tracker": "^3.4.6",
|
||||||
"@openreplay/tracker-assist": "^3.4.4",
|
"@openreplay/tracker-assist": "^3.4.4",
|
||||||
"@openreplay/tracker-graphql": "^3.0.0",
|
"@openreplay/tracker-graphql": "^3.0.0",
|
||||||
"@openreplay/tracker-redux": "^3.0.0",
|
"@openreplay/tracker-redux": "^3.0.0",
|
||||||
"@sentry/react": "^6.13.3",
|
"@sentry/react": "^6.14.1",
|
||||||
"@sentry/tracing": "^6.13.3",
|
"@sentry/tracing": "^6.14.1",
|
||||||
"@splitsoftware/splitio-react": "^1.3.0",
|
"@splitsoftware/splitio-react": "^1.3.0",
|
||||||
"@stripe/react-stripe-js": "^1.6.0",
|
"@stripe/react-stripe-js": "^1.6.0",
|
||||||
"@stripe/stripe-js": "^1.20.2",
|
"@stripe/stripe-js": "^1.21.1",
|
||||||
"@tanem/react-nprogress": "^3.0.81",
|
"@tanem/react-nprogress": "^3.0.82",
|
||||||
"antd": "^4.16.13",
|
"antd": "^4.16.13",
|
||||||
"apollo-link-logger": "^2.0.0",
|
"apollo-link-logger": "^2.0.0",
|
||||||
"axios": "^0.23.0",
|
"axios": "^0.24.0",
|
||||||
"craco-less": "^1.20.0",
|
"craco-less": "^1.20.0",
|
||||||
"dinero.js": "^1.9.1",
|
"dinero.js": "^1.9.1",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"enquire-js": "^0.2.1",
|
"enquire-js": "^0.2.1",
|
||||||
"env-cmd": "^10.1.0",
|
"env-cmd": "^10.1.0",
|
||||||
"exifr": "^7.1.3",
|
"exifr": "^7.1.3",
|
||||||
"firebase": "^9.1.3",
|
"firebase": "^9.3.0",
|
||||||
"graphql": "^15.6.1",
|
"graphql": "^16.0.1",
|
||||||
"i18next": "^21.3.3",
|
"i18next": "^21.4.1",
|
||||||
"i18next-browser-languagedetector": "^6.1.2",
|
"i18next-browser-languagedetector": "^6.1.2",
|
||||||
"jsoneditor": "^9.5.6",
|
"jsoneditor": "^9.5.7",
|
||||||
"jsreport-browser-client-dist": "^1.3.0",
|
"jsreport-browser-client-dist": "^1.3.0",
|
||||||
"libphonenumber-js": "^1.9.38",
|
"libphonenumber-js": "^1.9.42",
|
||||||
"logrocket": "^2.1.1",
|
"logrocket": "^2.1.1",
|
||||||
"markerjs2": "^2.15.0",
|
"markerjs2": "^2.16.2",
|
||||||
"moment-business-days": "^1.2.0",
|
"moment-business-days": "^1.2.0",
|
||||||
"phone": "^3.1.8",
|
"phone": "^3.1.8",
|
||||||
"preval.macro": "^5.0.0",
|
"preval.macro": "^5.0.0",
|
||||||
@@ -51,25 +51,25 @@
|
|||||||
"react-drag-listview": "^0.1.8",
|
"react-drag-listview": "^0.1.8",
|
||||||
"react-grid-gallery": "^0.5.5",
|
"react-grid-gallery": "^0.5.5",
|
||||||
"react-grid-layout": "^1.3.0",
|
"react-grid-layout": "^1.3.0",
|
||||||
"react-i18next": "^11.12.0",
|
"react-i18next": "^11.13.0",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"react-number-format": "^4.7.3",
|
"react-number-format": "^4.7.3",
|
||||||
"react-redux": "^7.2.5",
|
"react-redux": "^7.2.6",
|
||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.4",
|
||||||
"react-router-dom": "^5.3.0",
|
"react-router-dom": "^5.3.0",
|
||||||
"react-scripts": "^4.0.3",
|
"react-scripts": "^4.0.3",
|
||||||
"react-sublime-video": "^0.2.5",
|
"react-sublime-video": "^0.2.5",
|
||||||
"react-virtualized": "^9.22.3",
|
"react-virtualized": "^9.22.3",
|
||||||
"recharts": "^2.1.5",
|
"recharts": "^2.1.6",
|
||||||
"redux": "^4.1.1",
|
"redux": "^4.1.2",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"redux-saga": "^1.1.3",
|
"redux-saga": "^1.1.3",
|
||||||
"redux-state-sync": "^3.1.2",
|
"redux-state-sync": "^3.1.2",
|
||||||
"reselect": "^4.0.0",
|
"reselect": "^4.1.2",
|
||||||
"sass": "^1.43.3",
|
"sass": "^1.43.4",
|
||||||
"socket.io-client": "^4.3.2",
|
"socket.io-client": "^4.3.2",
|
||||||
"styled-components": "^5.3.3",
|
"styled-components": "^5.3.3",
|
||||||
"subscriptions-transport-ws": "^0.9.18",
|
"subscriptions-transport-ws": "^0.11.0",
|
||||||
"web-vitals": "^2.1.2",
|
"web-vitals": "^2.1.2",
|
||||||
"workbox-background-sync": "^6.3.0",
|
"workbox-background-sync": "^6.3.0",
|
||||||
"workbox-broadcast-update": "^6.3.0",
|
"workbox-broadcast-update": "^6.3.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ShrinkOutlined } from "@ant-design/icons";
|
import { ShrinkOutlined, InfoCircleOutlined } from "@ant-design/icons";
|
||||||
import { Col, Row, Typography } from "antd";
|
import { Col, Row, Tooltip, Typography } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -31,6 +31,9 @@ export function ChatPopupComponent({
|
|||||||
{t("messaging.labels.messaging")}
|
{t("messaging.labels.messaging")}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
<ChatNewConversation />
|
<ChatNewConversation />
|
||||||
|
<Tooltip title={t("messaging.labels.recentonly")}>
|
||||||
|
<InfoCircleOutlined />
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
<ShrinkOutlined
|
<ShrinkOutlined
|
||||||
onClick={() => toggleChatVisible()}
|
onClick={() => toggleChatVisible()}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Button, Table, Col , Checkbox} from "antd";
|
import { Button, Table, Col, Checkbox } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -23,15 +23,26 @@ export function DmsCustomerSelector({ bodyshop }) {
|
|||||||
const [customerList, setcustomerList] = useState([]);
|
const [customerList, setcustomerList] = useState([]);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [selectedCustomer, setSelectedCustomer] = useState(null);
|
const [selectedCustomer, setSelectedCustomer] = useState(null);
|
||||||
|
const [dmsType, setDmsType] = useState("cdk");
|
||||||
|
|
||||||
socket.on("cdk-select-customer", (customerList, callback) => {
|
socket.on("cdk-select-customer", (customerList, callback) => {
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
setDmsType("cdk");
|
||||||
setcustomerList(customerList);
|
setcustomerList(customerList);
|
||||||
});
|
});
|
||||||
|
socket.on("pbs-select-customer", (customerList, callback) => {
|
||||||
|
setVisible(true);
|
||||||
|
setDmsType("pbs");
|
||||||
|
setcustomerList(customerList);
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: dms-customer-selector.component.jsx ~ line 37 ~ socket.on ~ customerList",
|
||||||
|
customerList
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const onUseSelected = () => {
|
const onUseSelected = () => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
socket.emit("cdk-selected-customer", selectedCustomer);
|
socket.emit(`${dmsType}-selected-customer`, selectedCustomer);
|
||||||
setSelectedCustomer(null);
|
setSelectedCustomer(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,7 +61,7 @@ export function DmsCustomerSelector({ bodyshop }) {
|
|||||||
setSelectedCustomer(null);
|
setSelectedCustomer(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = [
|
const cdkColumns = [
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.dms.id"),
|
title: t("jobs.fields.dms.id"),
|
||||||
dataIndex: ["id", "value"],
|
dataIndex: ["id", "value"],
|
||||||
@@ -60,13 +71,14 @@ export function DmsCustomerSelector({ bodyshop }) {
|
|||||||
title: t("jobs.fields.dms.vinowner"),
|
title: t("jobs.fields.dms.vinowner"),
|
||||||
dataIndex: "vinOwner",
|
dataIndex: "vinOwner",
|
||||||
key: "vinOwner",
|
key: "vinOwner",
|
||||||
render: (text, record) => <Checkbox disabled checked={record.vinOwner}/>
|
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.dms.name1"),
|
title: t("jobs.fields.dms.name1"),
|
||||||
dataIndex: ["name1", "fullName"],
|
dataIndex: ["name1", "fullName"],
|
||||||
key: "name1",
|
key: "name1",
|
||||||
sorter: (a, b) => alphaSort(a.name1?.fullName, b.name1?.fullName),
|
sorter: (a, b) =>
|
||||||
|
alphaSort(a.name1 && a.name1.fullName, b.name1 && b.name1.fullName),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -74,11 +86,43 @@ export function DmsCustomerSelector({ bodyshop }) {
|
|||||||
//dataIndex: ["name2", "fullName"],
|
//dataIndex: ["name2", "fullName"],
|
||||||
key: "address",
|
key: "address",
|
||||||
render: (record, value) =>
|
render: (record, value) =>
|
||||||
`${record?.address?.addressLine[0]}, ${record.address?.city} ${record.address?.stateOrProvince} ${record.address?.postalCode}`,
|
`${record.address && record.address.addressLine[0]}, ${
|
||||||
|
record.address && record.address.city
|
||||||
|
} ${record.address && record.address.stateOrProvince} ${
|
||||||
|
record.address && record.address.postalCode
|
||||||
|
}`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!visible) return <></>;
|
const pbsColumns = [
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.dms.id"),
|
||||||
|
dataIndex: "ContactId",
|
||||||
|
key: "ContactId",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.dms.vinowner"),
|
||||||
|
dataIndex: "vinOwner",
|
||||||
|
key: "vinOwner",
|
||||||
|
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.dms.name1"),
|
||||||
|
key: "name1",
|
||||||
|
sorter: (a, b) => alphaSort(a.LastName, b.LastName),
|
||||||
|
render: (text, record) =>
|
||||||
|
`${record.FirstName || ""} ${record.LastName || ""}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.dms.address"),
|
||||||
|
key: "address",
|
||||||
|
render: (record, value) =>
|
||||||
|
`${record.Address}, ${record.City} ${record.State} ${record.ZipCode}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!visible) return null;
|
||||||
return (
|
return (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Table
|
<Table
|
||||||
@@ -104,13 +148,17 @@ export function DmsCustomerSelector({ bodyshop }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
pagination={{ position: "top" }}
|
pagination={{ position: "top" }}
|
||||||
columns={columns}
|
columns={dmsType === "cdk" ? cdkColumns : pbsColumns}
|
||||||
rowKey={(record) => record.id.value}
|
rowKey={(record) =>
|
||||||
|
dmsType === "cdk" ? record.id.value : record.ContactId
|
||||||
|
}
|
||||||
dataSource={customerList}
|
dataSource={customerList}
|
||||||
//onChange={handleTableChange}
|
//onChange={handleTableChange}
|
||||||
rowSelection={{
|
rowSelection={{
|
||||||
onSelect: (props) => {
|
onSelect: (record) => {
|
||||||
setSelectedCustomer(props.id.value);
|
setSelectedCustomer(
|
||||||
|
dmsType === "cdk" ? record.id.value : record.ContactId
|
||||||
|
);
|
||||||
},
|
},
|
||||||
type: "radio",
|
type: "radio",
|
||||||
selectedRowKeys: [selectedCustomer],
|
selectedRowKeys: [selectedCustomer],
|
||||||
|
|||||||
@@ -119,33 +119,35 @@ export function DmsPostForm({ bodyshop, socket, job }) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
|
||||||
<LayoutFormRow style={{ justifyContent: "center" }} grow>
|
{bodyshop.cdk_dealerid && (
|
||||||
<Form.Item
|
<LayoutFormRow style={{ justifyContent: "center" }} grow>
|
||||||
name="dms_make"
|
<Form.Item
|
||||||
label={t("jobs.fields.dms.dms_make")}
|
name="dms_make"
|
||||||
rules={[
|
label={t("jobs.fields.dms.dms_make")}
|
||||||
{
|
rules={[
|
||||||
required: true,
|
{
|
||||||
},
|
required: true,
|
||||||
]}
|
},
|
||||||
>
|
]}
|
||||||
<Input disabled />
|
>
|
||||||
</Form.Item>
|
<Input disabled />
|
||||||
<Form.Item
|
</Form.Item>
|
||||||
name="dms_model"
|
<Form.Item
|
||||||
label={t("jobs.fields.dms.dms_model")}
|
name="dms_model"
|
||||||
rules={[
|
label={t("jobs.fields.dms.dms_model")}
|
||||||
{
|
rules={[
|
||||||
required: true,
|
{
|
||||||
},
|
required: true,
|
||||||
]}
|
},
|
||||||
>
|
]}
|
||||||
<Input disabled />
|
>
|
||||||
</Form.Item>
|
<Input disabled />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<DmsCdkMakes form={form} socket={socket} job={job} />
|
<DmsCdkMakes form={form} socket={socket} job={job} />
|
||||||
<DmsCdkMakesRefetch />
|
<DmsCdkMakesRefetch />
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
)}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="story"
|
name="story"
|
||||||
label={t("jobs.fields.dms.story")}
|
label={t("jobs.fields.dms.story")}
|
||||||
@@ -157,6 +159,7 @@ export function DmsPostForm({ bodyshop, socket, job }) {
|
|||||||
>
|
>
|
||||||
<Input.TextArea maxLength={240} />
|
<Input.TextArea maxLength={240} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<Form.List name={["payers"]}>
|
<Form.List name={["payers"]}>
|
||||||
{(fields, { add, remove }) => {
|
{(fields, { add, remove }) => {
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import { selectCurrentUser } from "../../redux/user/user.selectors";
|
|||||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||||
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
|
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
|
||||||
});
|
});
|
||||||
@@ -24,9 +26,20 @@ export function EmailTestComponent({ currentUser, setEmailOptions }) {
|
|||||||
{
|
{
|
||||||
name: values.key,
|
name: values.key,
|
||||||
variables: {
|
variables: {
|
||||||
|
...(values.start
|
||||||
|
? {
|
||||||
|
start: moment(values.start).startOf("day").format("YYYY-MM-DD"),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...(values.end
|
||||||
|
? { end: moment(values.end).endOf("day").format("YYYY-MM-DD") }
|
||||||
|
: {}),
|
||||||
|
...(values.start
|
||||||
|
? { starttz: moment(values.start).startOf("day") }
|
||||||
|
: {}),
|
||||||
|
...(values.end ? { endtz: moment(values.end).endOf("day") } : {}),
|
||||||
|
|
||||||
...(values.id ? { id: values.id } : {}),
|
...(values.id ? { id: values.id } : {}),
|
||||||
...(values.start ? { start: values.start } : {}),
|
|
||||||
...(values.end ? { end: values.end } : {}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,12 +46,16 @@ import {
|
|||||||
} from "../../redux/application/application.selectors";
|
} from "../../redux/application/application.selectors";
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
import { signOutStart } from "../../redux/user/user.actions";
|
import { signOutStart } from "../../redux/user/user.actions";
|
||||||
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
import {
|
||||||
|
selectBodyshop,
|
||||||
|
selectCurrentUser,
|
||||||
|
} from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
recentItems: selectRecentItems,
|
recentItems: selectRecentItems,
|
||||||
selectedHeader: selectSelectedHeader,
|
selectedHeader: selectSelectedHeader,
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@@ -69,6 +73,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
function Header({
|
function Header({
|
||||||
handleMenuClick,
|
handleMenuClick,
|
||||||
currentUser,
|
currentUser,
|
||||||
|
bodyshop,
|
||||||
selectedHeader,
|
selectedHeader,
|
||||||
signOutStart,
|
signOutStart,
|
||||||
setBillEnterContext,
|
setBillEnterContext,
|
||||||
@@ -237,16 +242,26 @@ function Header({
|
|||||||
{t("menus.header.accounting-receivables")}
|
{t("menus.header.accounting-receivables")}
|
||||||
</Link>
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="payables">
|
{!(
|
||||||
<Link to="/manage/accounting/payables">
|
(bodyshop && bodyshop.cdk_dealerid) ||
|
||||||
{t("menus.header.accounting-payables")}
|
(bodyshop && bodyshop.pbs_serialnumber)
|
||||||
</Link>
|
) && (
|
||||||
</Menu.Item>
|
<Menu.Item key="payables">
|
||||||
<Menu.Item key="payments">
|
<Link to="/manage/accounting/payables">
|
||||||
<Link to="/manage/accounting/payments">
|
{t("menus.header.accounting-payables")}
|
||||||
{t("menus.header.accounting-payments")}
|
</Link>
|
||||||
</Link>
|
</Menu.Item>
|
||||||
</Menu.Item>
|
)}
|
||||||
|
{!(
|
||||||
|
(bodyshop && bodyshop.cdk_dealerid) ||
|
||||||
|
(bodyshop && bodyshop.pbs_serialnumber)
|
||||||
|
) && (
|
||||||
|
<Menu.Item key="payments">
|
||||||
|
<Link to="/manage/accounting/payments">
|
||||||
|
{t("menus.header.accounting-payments")}
|
||||||
|
</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
<Menu.Item key="export-logs">
|
<Menu.Item key="export-logs">
|
||||||
<Link to="/manage/accounting/exportlogs">
|
<Link to="/manage/accounting/exportlogs">
|
||||||
{t("menus.header.export-logs")}
|
{t("menus.header.export-logs")}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const reconcileByPrice = (
|
|||||||
|
|
||||||
jobLines.forEach((jl) => {
|
jobLines.forEach((jl) => {
|
||||||
const matchingBillLineIds = billLines
|
const matchingBillLineIds = billLines
|
||||||
.filter((bl) => bl.actual_price === jl.act_price && !jl.removed)
|
.filter((bl) => bl.actual_price === jl.act_price && bl.quantity === jl.part_qty && !jl.removed)
|
||||||
.map((bl) => bl.id);
|
.map((bl) => bl.id);
|
||||||
|
|
||||||
if (matchingBillLineIds.length > 1) {
|
if (matchingBillLineIds.length > 1) {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const overlay = bodyshop.cdk_dealerid && (
|
const overlay = (bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||||
<Menu onClick={handleMenuClick}>
|
<Menu onClick={handleMenuClick}>
|
||||||
{bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => (
|
{bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => (
|
||||||
<Menu.Item key={mapping.name}>{mapping.name}</Menu.Item>
|
<Menu.Item key={mapping.name}>{mapping.name}</Menu.Item>
|
||||||
@@ -69,7 +69,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
|||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|
||||||
return bodyshop.cdk_dealerid ? (
|
return bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? (
|
||||||
<Dropdown overlay={overlay}>
|
<Dropdown overlay={overlay}>
|
||||||
<Button disabled={disabled}>{t("jobs.actions.dmsautoallocate")}</Button>
|
<Button disabled={disabled}>{t("jobs.actions.dmsautoallocate")}</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { DownOutlined } from "@ant-design/icons";
|
import { DownOutlined } from "@ant-design/icons";
|
||||||
import { Dropdown, Menu } from "antd";
|
import { Dropdown, Menu } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
@@ -11,8 +10,6 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) {
|
export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) {
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const handleClick = ({ item, key, keyPath }) => {
|
const handleClick = ({ item, key, keyPath }) => {
|
||||||
const est = item.props.value;
|
const est = item.props.value;
|
||||||
form.setFieldsValue(est);
|
form.setFieldsValue(est);
|
||||||
@@ -37,7 +34,7 @@ export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) {
|
|||||||
href=" #"
|
href=" #"
|
||||||
onClick={(e) => e.preventDefault()}
|
onClick={(e) => e.preventDefault()}
|
||||||
>
|
>
|
||||||
{t("jobs.actions.changestimator")} <DownOutlined />
|
<DownOutlined />
|
||||||
</a>
|
</a>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { DownOutlined } from "@ant-design/icons";
|
||||||
|
import { Dropdown, Menu } from "antd";
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function JobsDetailChangeFilehandler({ disabled, form, bodyshop }) {
|
||||||
|
const handleClick = ({ item, key, keyPath }) => {
|
||||||
|
const est = item.props.value;
|
||||||
|
form.setFieldsValue(est);
|
||||||
|
};
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<div>
|
||||||
|
<Menu onClick={handleClick}>
|
||||||
|
{bodyshop.md_filehandlers.map((est, idx) => (
|
||||||
|
<Menu.Item value={est} key={idx}>
|
||||||
|
{`${est.ins_ct_fn} ${est.ins_ct_ln}`}
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown overlay={menu} disabled={disabled}>
|
||||||
|
<a
|
||||||
|
className="ant-dropdown-link"
|
||||||
|
href=" #"
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
<DownOutlined />
|
||||||
|
</a>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, null)(JobsDetailChangeFilehandler);
|
||||||
@@ -75,6 +75,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<DateTimePicker />
|
<DateTimePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.date_next_contact")}
|
||||||
|
name="date_next_contact"
|
||||||
|
>
|
||||||
|
<DateTimePicker />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.scheduled_completion")}
|
label={t("jobs.fields.scheduled_completion")}
|
||||||
name="scheduled_completion"
|
name="scheduled_completion"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
InputNumber,
|
InputNumber,
|
||||||
Row,
|
Row,
|
||||||
Select,
|
Select,
|
||||||
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@@ -23,7 +24,7 @@ import FormItemPhone, {
|
|||||||
import Car from "../job-damage-visual/job-damage-visual.component";
|
import Car from "../job-damage-visual/job-damage-visual.component";
|
||||||
import JobsDetailChangeEstimator from "../jobs-detail-change-estimator/jobs-detail-change-estimator.component";
|
import JobsDetailChangeEstimator from "../jobs-detail-change-estimator/jobs-detail-change-estimator.component";
|
||||||
import FormRow from "../layout-form-row/layout-form-row.component";
|
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
import JobsDetailChangeFileHandler from "../jobs-detail-change-filehandler/jobs-detail-change-filehandler.component";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -85,7 +86,15 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
|||||||
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city">
|
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city">
|
||||||
<Input disabled={jobRO} />
|
<Input disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.ins_ct_ln")} name="ins_ct_ln">
|
<Form.Item
|
||||||
|
label={
|
||||||
|
<Space>
|
||||||
|
{t("jobs.fields.ins_ct_ln")}
|
||||||
|
<JobsDetailChangeFileHandler form={form} disabled={jobRO} />
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
name="ins_ct_ln"
|
||||||
|
>
|
||||||
<Input disabled={jobRO} />
|
<Input disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn">
|
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn">
|
||||||
@@ -135,7 +144,7 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
|||||||
label={t("jobs.fields.referral_source_extra")}
|
label={t("jobs.fields.referral_source_extra")}
|
||||||
name="referral_source_extra"
|
name="referral_source_extra"
|
||||||
>
|
>
|
||||||
<Input disabled={jobRO}/>
|
<Input disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.alt_transport")} name="alt_transport">
|
<Form.Item label={t("jobs.fields.alt_transport")} name="alt_transport">
|
||||||
<Select disabled={jobRO} allowClear>
|
<Select disabled={jobRO} allowClear>
|
||||||
@@ -219,12 +228,19 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
|||||||
{t("jobs.forms.appraiserinfo")}
|
{t("jobs.forms.appraiserinfo")}
|
||||||
</Divider>
|
</Divider>
|
||||||
|
|
||||||
<JobsDetailChangeEstimator form={form} disabled={jobRO} />
|
|
||||||
<FormRow noDivider>
|
<FormRow noDivider>
|
||||||
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
|
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
|
||||||
<Input disabled={jobRO} />
|
<Input disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.est_ct_fn")} name="est_ct_fn">
|
<Form.Item
|
||||||
|
label={
|
||||||
|
<Space>
|
||||||
|
{t("jobs.fields.est_ct_fn")}
|
||||||
|
<JobsDetailChangeEstimator form={form} disabled={jobRO} />
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
name="est_ct_fn"
|
||||||
|
>
|
||||||
<Input disabled={jobRO} />
|
<Input disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln">
|
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln">
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ export function PartsOrderListTableComponent({
|
|||||||
</Button>
|
</Button>
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title={t("parts_orders.labels.confirmdelete")}
|
title={t("parts_orders.labels.confirmdelete")}
|
||||||
disabled={jobRO || !record.return}
|
disabled={jobRO}
|
||||||
onConfirm={async () => {
|
onConfirm={async () => {
|
||||||
//Delete the parts return.!
|
//Delete the parts return.!
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ export function PartsOrderListTableComponent({
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button disabled={jobRO || !record.return}>
|
<Button disabled={jobRO}>
|
||||||
<DeleteFilled />
|
<DeleteFilled />
|
||||||
</Button>
|
</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Input, PageHeader, Space, Spin } from "antd";
|
import { Input, Space, Spin } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -26,8 +26,7 @@ export function ProductionBoardFilters({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageHeader
|
|
||||||
extra={
|
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
{loading && <Spin />}
|
{loading && <Spin />}
|
||||||
<Input.Search
|
<Input.Search
|
||||||
@@ -46,7 +45,6 @@ export function ProductionBoardFilters({
|
|||||||
allowClear
|
allowClear
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
}
|
|
||||||
></PageHeader>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
||||||
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
|
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
|
||||||
|
|
||||||
export default function ProductionBoardCard(technician, card) {
|
export default function ProductionBoardCard(technician, card, bodyshop) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const menu = (
|
const menu = (
|
||||||
<div>
|
<div>
|
||||||
@@ -19,6 +19,21 @@ export default function ProductionBoardCard(technician, card) {
|
|||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
let employee_body, employee_prep, employee_refinish, employee_csr;
|
||||||
|
if (card.employee_body) {
|
||||||
|
employee_body = bodyshop.employees.find((e) => e.id === card.employee_body);
|
||||||
|
}
|
||||||
|
if (card.employee_prep) {
|
||||||
|
employee_prep = bodyshop.employees.find((e) => e.id === card.employee_prep);
|
||||||
|
}
|
||||||
|
if (card.employee_refinish) {
|
||||||
|
employee_refinish = bodyshop.employees.find(
|
||||||
|
(e) => e.id === card.employee_refinish
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (card.employee_csr) {
|
||||||
|
employee_csr = bodyshop.employees.find((e) => e.id === card.employee_csr);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown overlay={menu} trigger={["contextMenu"]}>
|
<Dropdown overlay={menu} trigger={["contextMenu"]}>
|
||||||
@@ -53,23 +68,23 @@ export default function ProductionBoardCard(technician, card) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mex-flex-row__margin">
|
<div className="mex-flex-row__margin">
|
||||||
<div>{`B: ${
|
<div>{`B: ${
|
||||||
card.employee_body_rel
|
employee_body
|
||||||
? `${card.employee_body_rel.first_name} ${card.employee_body_rel.last_name}`
|
? `${employee_body.first_name} ${employee_body.last_name}`
|
||||||
: ""
|
: ""
|
||||||
}`}</div>
|
}`}</div>
|
||||||
<div>{`P: ${
|
<div>{`P: ${
|
||||||
card.employee_prep_rel
|
employee_prep
|
||||||
? `${card.employee_prep_rel.first_name} ${card.employee_prep_rel.last_name}`
|
? `${employee_prep.first_name} ${employee_prep.last_name}`
|
||||||
: ""
|
: ""
|
||||||
}`}</div>
|
}`}</div>
|
||||||
<div>{`R: ${
|
<div>{`R: ${
|
||||||
card.employee_refinish_rel
|
employee_refinish
|
||||||
? `${card.employee_refinish_rel.first_name} ${card.employee_refinish_rel.last_name}`
|
? `${employee_refinish.first_name} ${employee_refinish.last_name}`
|
||||||
: ""
|
: ""
|
||||||
}`}</div>
|
}`}</div>
|
||||||
<div>{`CSR: ${
|
<div>{`CSR: ${
|
||||||
card.employee_csr_rel
|
employee_csr
|
||||||
? `${card.employee_csr_rel.first_name} ${card.employee_csr_rel.last_name}`
|
? `${employee_csr.first_name} ${employee_csr.last_name}`
|
||||||
: ""
|
: ""
|
||||||
}`}</div>
|
}`}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useApolloClient } from "@apollo/client";
|
import { useApolloClient } from "@apollo/client";
|
||||||
import Board, { moveCard } from "@lourenci/react-kanban";
|
import Board, { moveCard } from "@lourenci/react-kanban";
|
||||||
import "@lourenci/react-kanban/dist/styles.css";
|
import "@lourenci/react-kanban/dist/styles.css";
|
||||||
import { notification } from "antd";
|
import { notification, PageHeader, Space, Statistic } from "antd";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -130,19 +130,44 @@ export function ProductionBoardKanbanComponent({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const totalHrs = data
|
||||||
|
.reduce(
|
||||||
|
(acc, val) =>
|
||||||
|
acc +
|
||||||
|
(val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) +
|
||||||
|
(val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
.toFixed(1);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<IndefiniteLoading loading={isMoving} />
|
<IndefiniteLoading loading={isMoving} />
|
||||||
<ProductionBoardFilters
|
<PageHeader
|
||||||
filter={filter}
|
title={
|
||||||
setFilter={setFilter}
|
<Space>
|
||||||
loading={isMoving}
|
<Statistic
|
||||||
|
title={t("dashboard.titles.productionhours")}
|
||||||
|
value={totalHrs}
|
||||||
|
/>
|
||||||
|
<Statistic
|
||||||
|
title={t("appointments.labels.inproduction")}
|
||||||
|
value={data && data.length}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
extra={
|
||||||
|
<ProductionBoardFilters
|
||||||
|
filter={filter}
|
||||||
|
setFilter={setFilter}
|
||||||
|
loading={isMoving}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Board
|
<Board
|
||||||
children={boardLanes}
|
children={boardLanes}
|
||||||
disableCardDrag={isMoving}
|
disableCardDrag={isMoving}
|
||||||
renderCard={(card) => ProductionBoardCard(technician, card)}
|
renderCard={(card) => ProductionBoardCard(technician, card, bodyshop)}
|
||||||
onCardDragEnd={handleDragEnd}
|
onCardDragEnd={handleDragEnd}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
|
import moment from "moment";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
@@ -11,11 +12,11 @@ import ProductionListColumnBodyPriority from "./production-list-columns.bodyprio
|
|||||||
import ProductionListDate from "./production-list-columns.date.component";
|
import ProductionListDate from "./production-list-columns.date.component";
|
||||||
import ProductionListColumnDetailPriority from "./production-list-columns.detailpriority.component";
|
import ProductionListColumnDetailPriority from "./production-list-columns.detailpriority.component";
|
||||||
import ProductionListEmployeeAssignment from "./production-list-columns.empassignment.component";
|
import ProductionListEmployeeAssignment from "./production-list-columns.empassignment.component";
|
||||||
|
import ProductionListLastContacted from "./production-list-columns.lastcontacted.component";
|
||||||
import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component";
|
import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component";
|
||||||
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
|
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
|
||||||
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
||||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||||
import ProductionListLastContacted from "./production-list-columns.lastcontacted.component";
|
|
||||||
|
|
||||||
const r = ({ technician, state, activeStatuses }) => {
|
const r = ({ technician, state, activeStatuses }) => {
|
||||||
return [
|
return [
|
||||||
@@ -109,6 +110,29 @@ const r = ({ technician, state, activeStatuses }) => {
|
|||||||
state.sortedInfo.order,
|
state.sortedInfo.order,
|
||||||
render: (text, record) => <ProductionListLastContacted record={record} />,
|
render: (text, record) => <ProductionListLastContacted record={record} />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18n.t("jobs.fields.date_next_contact"),
|
||||||
|
dataIndex: "date_next_contact",
|
||||||
|
key: "date_next_contact",
|
||||||
|
ellipsis: true,
|
||||||
|
sorter: (a, b) => dateSort(a.date_next_contact, b.date_next_contact),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "date_next_contact" &&
|
||||||
|
state.sortedInfo.order,
|
||||||
|
render: (text, record) => (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color:
|
||||||
|
record.date_next_contact &&
|
||||||
|
moment(record.date_next_contact).isBefore(moment())
|
||||||
|
? "red"
|
||||||
|
: "",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProductionListDate record={record} field="date_next_contact" time />
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18n.t("jobs.fields.scheduled_delivery"),
|
title: i18n.t("jobs.fields.scheduled_delivery"),
|
||||||
dataIndex: "scheduled_delivery",
|
dataIndex: "scheduled_delivery",
|
||||||
@@ -332,7 +356,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListEmployeeAssignment
|
<ProductionListEmployeeAssignment
|
||||||
record={record}
|
record={record}
|
||||||
type="employee_body_rel"
|
type="employee_body"
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -343,7 +367,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListEmployeeAssignment
|
<ProductionListEmployeeAssignment
|
||||||
record={record}
|
record={record}
|
||||||
type="employee_prep_rel"
|
type="employee_prep"
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -352,10 +376,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
|||||||
dataIndex: "employee_csr",
|
dataIndex: "employee_csr",
|
||||||
key: "employee_csr",
|
key: "employee_csr",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListEmployeeAssignment
|
<ProductionListEmployeeAssignment record={record} type="employee_csr" />
|
||||||
record={record}
|
|
||||||
type="employee_csr_rel"
|
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -365,7 +386,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListEmployeeAssignment
|
<ProductionListEmployeeAssignment
|
||||||
record={record}
|
record={record}
|
||||||
type="employee_refinish_rel"
|
type="employee_refinish"
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export function ProductionListEmpAssignment({
|
|||||||
const result = await updateJob({
|
const result = await updateJob({
|
||||||
variables: { jobId: record.id, job: { [empAssignment]: employeeid } },
|
variables: { jobId: record.id, job: { [empAssignment]: employeeid } },
|
||||||
|
|
||||||
awaitRefetchQueries: true,
|
// awaitRefetchQueries: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
insertAuditTrail({
|
insertAuditTrail({
|
||||||
@@ -145,13 +145,18 @@ export function ProductionListEmpAssignment({
|
|||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let theEmployee;
|
||||||
|
|
||||||
|
if (record[type])
|
||||||
|
theEmployee = bodyshop.employees.find((e) => e.id === record[type]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover destroyTooltipOnHide content={popContent} visible={visibility}>
|
<Popover destroyTooltipOnHide content={popContent} visible={visibility}>
|
||||||
<Spin spinning={loading}>
|
<Spin spinning={loading}>
|
||||||
{record[type] ? (
|
{record[type] ? (
|
||||||
<div>
|
<div>
|
||||||
<span>{`${record[type].first_name || ""} ${
|
<span>{`${theEmployee.first_name || ""} ${
|
||||||
record[type].last_name || ""
|
theEmployee.last_name || ""
|
||||||
}`}</span>
|
}`}</span>
|
||||||
<DeleteFilled
|
<DeleteFilled
|
||||||
style={iconStyle}
|
style={iconStyle}
|
||||||
@@ -174,13 +179,13 @@ export function ProductionListEmpAssignment({
|
|||||||
|
|
||||||
const determineFieldName = (operation) => {
|
const determineFieldName = (operation) => {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case "employee_body_rel":
|
case "employee_body":
|
||||||
return "employee_body";
|
return "employee_body";
|
||||||
case "employee_prep_rel":
|
case "employee_prep":
|
||||||
return "employee_prep";
|
return "employee_prep";
|
||||||
case "employee_refinish_rel":
|
case "employee_refinish":
|
||||||
return "employee_refinish";
|
return "employee_refinish";
|
||||||
case "employee_csr_rel":
|
case "employee_csr":
|
||||||
return "employee_csr";
|
return "employee_csr";
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ export function ProductionLastContacted({ currentUser, record }) {
|
|||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const handleFinish = async ({ date_last_contacted, note }) => {
|
const handleFinish = async ({
|
||||||
|
date_last_contacted,
|
||||||
|
date_next_contact,
|
||||||
|
note,
|
||||||
|
}) => {
|
||||||
logImEXEvent("production_last_contacted");
|
logImEXEvent("production_last_contacted");
|
||||||
|
|
||||||
//e.stopPropagation();
|
//e.stopPropagation();
|
||||||
@@ -38,6 +42,7 @@ export function ProductionLastContacted({ currentUser, record }) {
|
|||||||
jobId: record.id,
|
jobId: record.id,
|
||||||
job: {
|
job: {
|
||||||
date_last_contacted,
|
date_last_contacted,
|
||||||
|
...(date_next_contact ? { date_next_contact } : {}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -98,7 +103,16 @@ export function ProductionLastContacted({ currentUser, record }) {
|
|||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<Form form={form} onFinish={handleFinish} layout="vertical">
|
<Form form={form} onFinish={handleFinish} layout="vertical">
|
||||||
<Form.Item name="date_last_contacted">
|
<Form.Item
|
||||||
|
name="date_last_contacted"
|
||||||
|
label={t("jobs.fields.date_last_contacted")}
|
||||||
|
>
|
||||||
|
<FormDateTimePickerComponent />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="date_next_contact"
|
||||||
|
label={t("jobs.fields.date_next_contact")}
|
||||||
|
>
|
||||||
<FormDateTimePickerComponent />
|
<FormDateTimePickerComponent />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("notes.labels.notetoadd")} name="note">
|
<Form.Item label={t("notes.labels.notetoadd")} name="note">
|
||||||
|
|||||||
@@ -182,10 +182,16 @@ export function ProductionListTable({
|
|||||||
<div>
|
<div>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={
|
title={
|
||||||
<Statistic
|
<Space>
|
||||||
title={t("dashboard.titles.productionhours")}
|
<Statistic
|
||||||
value={totalHrs}
|
title={t("dashboard.titles.productionhours")}
|
||||||
/>
|
value={totalHrs}
|
||||||
|
/>
|
||||||
|
<Statistic
|
||||||
|
title={t("appointments.labels.inproduction")}
|
||||||
|
value={dataSource && dataSource.length}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
}
|
}
|
||||||
extra={
|
extra={
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
|
|||||||
@@ -848,6 +848,88 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
}}
|
}}
|
||||||
</Form.List>
|
</Form.List>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
<LayoutFormRow grow header={t("bodyshop.labels.filehandlers")}>
|
||||||
|
<Form.List name={["md_filehandlers"]}>
|
||||||
|
{(fields, { add, remove, move }) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{fields.map((field, index) => (
|
||||||
|
<Form.Item key={field.key}>
|
||||||
|
<LayoutFormRow noDivider>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.ins_ct_fn")}
|
||||||
|
key={`${index}ins_ct_fn`}
|
||||||
|
name={[field.name, "ins_ct_fn"]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.ins_ct_ln")}
|
||||||
|
key={`${index}ins_ct_ln`}
|
||||||
|
name={[field.name, "ins_ct_ln"]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.ins_ph1")}
|
||||||
|
key={`${index}ins_ph1`}
|
||||||
|
name={[field.name, "ins_ph1"]}
|
||||||
|
rules={[
|
||||||
|
({ getFieldValue }) =>
|
||||||
|
PhoneItemFormatterValidation(getFieldValue, [
|
||||||
|
field.name,
|
||||||
|
"ins_ph",
|
||||||
|
]),
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.ins_ea")}
|
||||||
|
key={`${index}ins_ea`}
|
||||||
|
name={[field.name, "ins_ea"]}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
type: "email",
|
||||||
|
message: "This is not a valid email address.",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<FormItemEmail
|
||||||
|
email={form.getFieldValue([field.name, "ins_ea"])}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Space>
|
||||||
|
<DeleteFilled
|
||||||
|
onClick={() => {
|
||||||
|
remove(field.name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FormListMoveArrows
|
||||||
|
move={move}
|
||||||
|
index={index}
|
||||||
|
total={fields.length}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</LayoutFormRow>
|
||||||
|
</Form.Item>
|
||||||
|
))}
|
||||||
|
<Form.Item>
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
onClick={() => {
|
||||||
|
add();
|
||||||
|
}}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
>
|
||||||
|
{t("general.actions.add")}
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Form.List>
|
||||||
|
</LayoutFormRow>
|
||||||
<LayoutFormRow grow header={t("bodyshop.fields.md_ccc_rates")}>
|
<LayoutFormRow grow header={t("bodyshop.fields.md_ccc_rates")}>
|
||||||
<Form.List name={["md_ccc_rates"]}>
|
<Form.List name={["md_ccc_rates"]}>
|
||||||
{(fields, { add, remove, move }) => {
|
{(fields, { add, remove, move }) => {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -98,6 +98,7 @@ export const QUERY_BODYSHOP = gql`
|
|||||||
md_ded_notes
|
md_ded_notes
|
||||||
pbs_configuration
|
pbs_configuration
|
||||||
pbs_serialnumber
|
pbs_serialnumber
|
||||||
|
md_filehandlers
|
||||||
employees {
|
employees {
|
||||||
id
|
id
|
||||||
active
|
active
|
||||||
@@ -192,6 +193,7 @@ export const UPDATE_SHOP = gql`
|
|||||||
md_ded_notes
|
md_ded_notes
|
||||||
pbs_configuration
|
pbs_configuration
|
||||||
pbs_serialnumber
|
pbs_serialnumber
|
||||||
|
md_filehandlers
|
||||||
employees {
|
employees {
|
||||||
id
|
id
|
||||||
first_name
|
first_name
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { gql } from "@apollo/client";
|
|||||||
|
|
||||||
export const QUERY_EMPLOYEES = gql`
|
export const QUERY_EMPLOYEES = gql`
|
||||||
query QUERY_EMPLOYEES {
|
query QUERY_EMPLOYEES {
|
||||||
employees {
|
employees(order_by: { employee_number: asc }) {
|
||||||
last_name
|
last_name
|
||||||
id
|
id
|
||||||
first_name
|
first_name
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
|||||||
scheduled_completion
|
scheduled_completion
|
||||||
scheduled_delivery
|
scheduled_delivery
|
||||||
date_last_contacted
|
date_last_contacted
|
||||||
|
date_next_contact
|
||||||
ins_co_nm
|
ins_co_nm
|
||||||
clm_total
|
clm_total
|
||||||
ownr_ph1
|
ownr_ph1
|
||||||
@@ -134,39 +135,10 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
|||||||
production_vars
|
production_vars
|
||||||
kanbanparent
|
kanbanparent
|
||||||
alt_transport
|
alt_transport
|
||||||
joblines_status {
|
|
||||||
part_type
|
|
||||||
count
|
|
||||||
status
|
|
||||||
}
|
|
||||||
employee_body
|
employee_body
|
||||||
employee_body_rel {
|
|
||||||
id
|
|
||||||
first_name
|
|
||||||
last_name
|
|
||||||
}
|
|
||||||
employee_refinish
|
employee_refinish
|
||||||
employee_refinish_rel {
|
|
||||||
id
|
|
||||||
first_name
|
|
||||||
last_name
|
|
||||||
}
|
|
||||||
employee_prep
|
employee_prep
|
||||||
employee_prep_rel {
|
employee_csr
|
||||||
id
|
|
||||||
first_name
|
|
||||||
last_name
|
|
||||||
}
|
|
||||||
employee_csr_rel {
|
|
||||||
id
|
|
||||||
first_name
|
|
||||||
last_name
|
|
||||||
}
|
|
||||||
partcount: joblines_aggregate(where: { removed: { _eq: false } }) {
|
|
||||||
nodes {
|
|
||||||
status
|
|
||||||
}
|
|
||||||
}
|
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: {
|
where: {
|
||||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
@@ -519,6 +491,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
date_scheduled
|
date_scheduled
|
||||||
date_invoiced
|
date_invoiced
|
||||||
date_last_contacted
|
date_last_contacted
|
||||||
|
date_next_contact
|
||||||
date_exported
|
date_exported
|
||||||
status
|
status
|
||||||
owner_owing
|
owner_owing
|
||||||
@@ -762,6 +735,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
|
|||||||
scheduled_delivery
|
scheduled_delivery
|
||||||
date_invoiced
|
date_invoiced
|
||||||
date_last_contacted
|
date_last_contacted
|
||||||
|
date_next_contact
|
||||||
date_open
|
date_open
|
||||||
date_exported
|
date_exported
|
||||||
|
|
||||||
@@ -848,6 +822,7 @@ export const QUERY_TECH_JOB_DETAILS = gql`
|
|||||||
scheduled_delivery
|
scheduled_delivery
|
||||||
date_invoiced
|
date_invoiced
|
||||||
date_last_contacted
|
date_last_contacted
|
||||||
|
date_next_contact
|
||||||
date_open
|
date_open
|
||||||
date_exported
|
date_exported
|
||||||
voided
|
voided
|
||||||
|
|||||||
@@ -120,7 +120,11 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
|||||||
if (loading) return <LoadingSpinner />;
|
if (loading) return <LoadingSpinner />;
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
|
||||||
if (!jobId || !bodyshop.cdk_dealerid || !(data && data.jobs_by_pk))
|
if (
|
||||||
|
!jobId ||
|
||||||
|
!(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) ||
|
||||||
|
!(data && data.jobs_by_pk)
|
||||||
|
)
|
||||||
return <Result status="404" />;
|
return <Result status="404" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
>
|
>
|
||||||
<DateTimePicker disabled={jobRO} />
|
<DateTimePicker disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{bodyshop.cdk_dealerid && (
|
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.kmin")}
|
label={t("jobs.fields.kmin")}
|
||||||
name="kmin"
|
name="kmin"
|
||||||
@@ -221,7 +221,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
<InputNumber precision={0} disabled={jobRO} />
|
<InputNumber precision={0} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
{bodyshop.cdk_dealerid && (
|
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.kmout")}
|
label={t("jobs.fields.kmout")}
|
||||||
name="kmout"
|
name="kmout"
|
||||||
|
|||||||
@@ -503,6 +503,7 @@
|
|||||||
"emaillater": "Email Later",
|
"emaillater": "Email Later",
|
||||||
"employees": "Employees",
|
"employees": "Employees",
|
||||||
"estimators": "Estimators",
|
"estimators": "Estimators",
|
||||||
|
"filehandlers": "File Handlers",
|
||||||
"insurancecos": "Insurance Companies",
|
"insurancecos": "Insurance Companies",
|
||||||
"intakechecklist": "Intake Checklist",
|
"intakechecklist": "Intake Checklist",
|
||||||
"jobstatuses": "Job Statuses",
|
"jobstatuses": "Job Statuses",
|
||||||
@@ -535,6 +536,7 @@
|
|||||||
"save": "Shop configuration saved successfully. "
|
"save": "Shop configuration saved successfully. "
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"centermustexist": "The chosen responsibility center does not exist.",
|
||||||
"larsplit": "Refinish hour split must add up to 1.",
|
"larsplit": "Refinish hour split must add up to 1.",
|
||||||
"useremailmustexist": "This email is not a valid user."
|
"useremailmustexist": "This email is not a valid user."
|
||||||
}
|
}
|
||||||
@@ -1091,6 +1093,7 @@
|
|||||||
"addtoscoreboard": "Add to Scoreboard",
|
"addtoscoreboard": "Add to Scoreboard",
|
||||||
"allocate": "Allocate",
|
"allocate": "Allocate",
|
||||||
"autoallocate": "Auto Allocate",
|
"autoallocate": "Auto Allocate",
|
||||||
|
"changefilehandler": "Change File Handler",
|
||||||
"changelaborrate": "Change Labor Rate",
|
"changelaborrate": "Change Labor Rate",
|
||||||
"changestatus": "Change Status",
|
"changestatus": "Change Status",
|
||||||
"changestimator": "Change Estimator",
|
"changestimator": "Change Estimator",
|
||||||
@@ -1205,6 +1208,7 @@
|
|||||||
"date_exported": "Exported",
|
"date_exported": "Exported",
|
||||||
"date_invoiced": "Invoiced",
|
"date_invoiced": "Invoiced",
|
||||||
"date_last_contacted": "Last Contacted Date",
|
"date_last_contacted": "Last Contacted Date",
|
||||||
|
"date_next_contact": "Next Contact Date",
|
||||||
"date_open": "Open",
|
"date_open": "Open",
|
||||||
"date_scheduled": "Scheduled",
|
"date_scheduled": "Scheduled",
|
||||||
"ded_amt": "Deductible",
|
"ded_amt": "Deductible",
|
||||||
@@ -1725,7 +1729,8 @@
|
|||||||
"new": "New Conversation"
|
"new": "New Conversation"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalidphone": "The phone number is invalid. Unable to open conversation. "
|
"invalidphone": "The phone number is invalid. Unable to open conversation. ",
|
||||||
|
"noattachedjobs": "No jobs have been associated to this conversation. "
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"archive": "Archive",
|
"archive": "Archive",
|
||||||
@@ -1735,6 +1740,7 @@
|
|||||||
"nojobs": "Not associated to any job.",
|
"nojobs": "Not associated to any job.",
|
||||||
"phonenumber": "Phone #",
|
"phonenumber": "Phone #",
|
||||||
"presets": "Presets",
|
"presets": "Presets",
|
||||||
|
"recentonly": "Only your most recent 50 conversations will be shown here. If you are looking for an older conversation, find the related contact and click their phone number to view the conversation.",
|
||||||
"selectmedia": "Select Media",
|
"selectmedia": "Select Media",
|
||||||
"sentby": "Sent by {{by}} at {{time}}",
|
"sentby": "Sent by {{by}} at {{time}}",
|
||||||
"typeamessage": "Send a message...",
|
"typeamessage": "Send a message...",
|
||||||
@@ -1824,6 +1830,7 @@
|
|||||||
"receivebill": "Receive Bill"
|
"receivebill": "Receive Bill"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
|
"associatedbills": "This parts order cannot",
|
||||||
"backordering": "Error backordering part {{message}}.",
|
"backordering": "Error backordering part {{message}}.",
|
||||||
"creating": "Error encountered when creating parts order. "
|
"creating": "Error encountered when creating parts order. "
|
||||||
},
|
},
|
||||||
@@ -1849,7 +1856,7 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"allpartsto": "All Parts Location",
|
"allpartsto": "All Parts Location",
|
||||||
"confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. ",
|
"confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ",
|
||||||
"email": "Send by Email",
|
"email": "Send by Email",
|
||||||
"inthisorder": "Parts in this Order",
|
"inthisorder": "Parts in this Order",
|
||||||
"newpartsorder": "New Parts Order",
|
"newpartsorder": "New Parts Order",
|
||||||
@@ -1968,6 +1975,7 @@
|
|||||||
"zip": "Postal Code/Zip"
|
"zip": "Postal Code/Zip"
|
||||||
},
|
},
|
||||||
"3rdpartypayer": "Invoice to Third Party Payer",
|
"3rdpartypayer": "Invoice to Third Party Payer",
|
||||||
|
"ab_proof_of_loss": "AB - Proof of Loss",
|
||||||
"appointment_confirmation": "Appointment Confirmation",
|
"appointment_confirmation": "Appointment Confirmation",
|
||||||
"appointment_reminder": "Appointment Reminder",
|
"appointment_reminder": "Appointment Reminder",
|
||||||
"casl_authorization": "CASL Authorization",
|
"casl_authorization": "CASL Authorization",
|
||||||
@@ -2176,6 +2184,7 @@
|
|||||||
"open_orders_csr": "Open Orders by CSR",
|
"open_orders_csr": "Open Orders by CSR",
|
||||||
"open_orders_estimator": "Open Orders by Estimator",
|
"open_orders_estimator": "Open Orders by Estimator",
|
||||||
"open_orders_ins_co": "Open Orders by Insurance Company",
|
"open_orders_ins_co": "Open Orders by Insurance Company",
|
||||||
|
"open_orders_status": "Open Orders by Status",
|
||||||
"parts_backorder": "Backordered Parts",
|
"parts_backorder": "Backordered Parts",
|
||||||
"parts_not_recieved": "Parts Not Received",
|
"parts_not_recieved": "Parts Not Received",
|
||||||
"payments_by_date": "Payments by Date",
|
"payments_by_date": "Payments by Date",
|
||||||
|
|||||||
@@ -503,6 +503,7 @@
|
|||||||
"emaillater": "",
|
"emaillater": "",
|
||||||
"employees": "",
|
"employees": "",
|
||||||
"estimators": "",
|
"estimators": "",
|
||||||
|
"filehandlers": "",
|
||||||
"insurancecos": "",
|
"insurancecos": "",
|
||||||
"intakechecklist": "",
|
"intakechecklist": "",
|
||||||
"jobstatuses": "",
|
"jobstatuses": "",
|
||||||
@@ -535,6 +536,7 @@
|
|||||||
"save": ""
|
"save": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"centermustexist": "",
|
||||||
"larsplit": "",
|
"larsplit": "",
|
||||||
"useremailmustexist": ""
|
"useremailmustexist": ""
|
||||||
}
|
}
|
||||||
@@ -1091,6 +1093,7 @@
|
|||||||
"addtoscoreboard": "",
|
"addtoscoreboard": "",
|
||||||
"allocate": "",
|
"allocate": "",
|
||||||
"autoallocate": "",
|
"autoallocate": "",
|
||||||
|
"changefilehandler": "",
|
||||||
"changelaborrate": "",
|
"changelaborrate": "",
|
||||||
"changestatus": "Cambiar Estado",
|
"changestatus": "Cambiar Estado",
|
||||||
"changestimator": "",
|
"changestimator": "",
|
||||||
@@ -1205,6 +1208,7 @@
|
|||||||
"date_exported": "Exportado",
|
"date_exported": "Exportado",
|
||||||
"date_invoiced": "Facturado",
|
"date_invoiced": "Facturado",
|
||||||
"date_last_contacted": "",
|
"date_last_contacted": "",
|
||||||
|
"date_next_contact": "",
|
||||||
"date_open": "Abierto",
|
"date_open": "Abierto",
|
||||||
"date_scheduled": "Programado",
|
"date_scheduled": "Programado",
|
||||||
"ded_amt": "Deducible",
|
"ded_amt": "Deducible",
|
||||||
@@ -1725,7 +1729,8 @@
|
|||||||
"new": ""
|
"new": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalidphone": ""
|
"invalidphone": "",
|
||||||
|
"noattachedjobs": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"archive": "",
|
"archive": "",
|
||||||
@@ -1735,6 +1740,7 @@
|
|||||||
"nojobs": "",
|
"nojobs": "",
|
||||||
"phonenumber": "",
|
"phonenumber": "",
|
||||||
"presets": "",
|
"presets": "",
|
||||||
|
"recentonly": "",
|
||||||
"selectmedia": "",
|
"selectmedia": "",
|
||||||
"sentby": "",
|
"sentby": "",
|
||||||
"typeamessage": "Enviar un mensaje...",
|
"typeamessage": "Enviar un mensaje...",
|
||||||
@@ -1824,6 +1830,7 @@
|
|||||||
"receivebill": ""
|
"receivebill": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
|
"associatedbills": "",
|
||||||
"backordering": "",
|
"backordering": "",
|
||||||
"creating": "Se encontró un error al crear el pedido de piezas."
|
"creating": "Se encontró un error al crear el pedido de piezas."
|
||||||
},
|
},
|
||||||
@@ -1968,6 +1975,7 @@
|
|||||||
"zip": ""
|
"zip": ""
|
||||||
},
|
},
|
||||||
"3rdpartypayer": "",
|
"3rdpartypayer": "",
|
||||||
|
"ab_proof_of_loss": "",
|
||||||
"appointment_confirmation": "",
|
"appointment_confirmation": "",
|
||||||
"appointment_reminder": "",
|
"appointment_reminder": "",
|
||||||
"casl_authorization": "",
|
"casl_authorization": "",
|
||||||
@@ -2176,6 +2184,7 @@
|
|||||||
"open_orders_csr": "",
|
"open_orders_csr": "",
|
||||||
"open_orders_estimator": "",
|
"open_orders_estimator": "",
|
||||||
"open_orders_ins_co": "",
|
"open_orders_ins_co": "",
|
||||||
|
"open_orders_status": "",
|
||||||
"parts_backorder": "",
|
"parts_backorder": "",
|
||||||
"parts_not_recieved": "",
|
"parts_not_recieved": "",
|
||||||
"payments_by_date": "",
|
"payments_by_date": "",
|
||||||
|
|||||||
@@ -503,6 +503,7 @@
|
|||||||
"emaillater": "",
|
"emaillater": "",
|
||||||
"employees": "",
|
"employees": "",
|
||||||
"estimators": "",
|
"estimators": "",
|
||||||
|
"filehandlers": "",
|
||||||
"insurancecos": "",
|
"insurancecos": "",
|
||||||
"intakechecklist": "",
|
"intakechecklist": "",
|
||||||
"jobstatuses": "",
|
"jobstatuses": "",
|
||||||
@@ -535,6 +536,7 @@
|
|||||||
"save": ""
|
"save": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"centermustexist": "",
|
||||||
"larsplit": "",
|
"larsplit": "",
|
||||||
"useremailmustexist": ""
|
"useremailmustexist": ""
|
||||||
}
|
}
|
||||||
@@ -1091,6 +1093,7 @@
|
|||||||
"addtoscoreboard": "",
|
"addtoscoreboard": "",
|
||||||
"allocate": "",
|
"allocate": "",
|
||||||
"autoallocate": "",
|
"autoallocate": "",
|
||||||
|
"changefilehandler": "",
|
||||||
"changelaborrate": "",
|
"changelaborrate": "",
|
||||||
"changestatus": "Changer le statut",
|
"changestatus": "Changer le statut",
|
||||||
"changestimator": "",
|
"changestimator": "",
|
||||||
@@ -1205,6 +1208,7 @@
|
|||||||
"date_exported": "Exportés",
|
"date_exported": "Exportés",
|
||||||
"date_invoiced": "Facturé",
|
"date_invoiced": "Facturé",
|
||||||
"date_last_contacted": "",
|
"date_last_contacted": "",
|
||||||
|
"date_next_contact": "",
|
||||||
"date_open": "Ouvrir",
|
"date_open": "Ouvrir",
|
||||||
"date_scheduled": "Prévu",
|
"date_scheduled": "Prévu",
|
||||||
"ded_amt": "Déductible",
|
"ded_amt": "Déductible",
|
||||||
@@ -1725,7 +1729,8 @@
|
|||||||
"new": ""
|
"new": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalidphone": ""
|
"invalidphone": "",
|
||||||
|
"noattachedjobs": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"archive": "",
|
"archive": "",
|
||||||
@@ -1735,6 +1740,7 @@
|
|||||||
"nojobs": "",
|
"nojobs": "",
|
||||||
"phonenumber": "",
|
"phonenumber": "",
|
||||||
"presets": "",
|
"presets": "",
|
||||||
|
"recentonly": "",
|
||||||
"selectmedia": "",
|
"selectmedia": "",
|
||||||
"sentby": "",
|
"sentby": "",
|
||||||
"typeamessage": "Envoyer un message...",
|
"typeamessage": "Envoyer un message...",
|
||||||
@@ -1824,6 +1830,7 @@
|
|||||||
"receivebill": ""
|
"receivebill": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
|
"associatedbills": "",
|
||||||
"backordering": "",
|
"backordering": "",
|
||||||
"creating": "Erreur rencontrée lors de la création de la commande de pièces."
|
"creating": "Erreur rencontrée lors de la création de la commande de pièces."
|
||||||
},
|
},
|
||||||
@@ -1968,6 +1975,7 @@
|
|||||||
"zip": ""
|
"zip": ""
|
||||||
},
|
},
|
||||||
"3rdpartypayer": "",
|
"3rdpartypayer": "",
|
||||||
|
"ab_proof_of_loss": "",
|
||||||
"appointment_confirmation": "",
|
"appointment_confirmation": "",
|
||||||
"appointment_reminder": "",
|
"appointment_reminder": "",
|
||||||
"casl_authorization": "",
|
"casl_authorization": "",
|
||||||
@@ -2176,6 +2184,7 @@
|
|||||||
"open_orders_csr": "",
|
"open_orders_csr": "",
|
||||||
"open_orders_estimator": "",
|
"open_orders_estimator": "",
|
||||||
"open_orders_ins_co": "",
|
"open_orders_ins_co": "",
|
||||||
|
"open_orders_status": "",
|
||||||
"parts_backorder": "",
|
"parts_backorder": "",
|
||||||
"parts_not_recieved": "",
|
"parts_not_recieved": "",
|
||||||
"payments_by_date": "",
|
"payments_by_date": "",
|
||||||
|
|||||||
@@ -407,6 +407,17 @@ export const TemplateList = (type, context) => {
|
|||||||
CA_MB: true,
|
CA_MB: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ab_proof_of_loss: {
|
||||||
|
title: i18n.t("printcenter.jobs.ab_proof_of_loss"),
|
||||||
|
description: "Thank You Letter by RO",
|
||||||
|
key: "ab_proof_of_loss",
|
||||||
|
subject: i18n.t("printcenter.jobs.ab_proof_of_loss"),
|
||||||
|
disabled: false,
|
||||||
|
group: "pre",
|
||||||
|
regions: {
|
||||||
|
CA_AB: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
// parts_label_multi: {
|
// parts_label_multi: {
|
||||||
// title: i18n.t("printcenter.jobs.parts_label_multi"),
|
// title: i18n.t("printcenter.jobs.parts_label_multi"),
|
||||||
// description: "Thank You Letter by RO",
|
// description: "Thank You Letter by RO",
|
||||||
@@ -1181,6 +1192,19 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
group: "jobs",
|
group: "jobs",
|
||||||
},
|
},
|
||||||
|
open_orders_status: {
|
||||||
|
title: i18n.t("reportcenter.templates.open_orders_status"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.open_orders_status"),
|
||||||
|
key: "open_orders_status",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
|
},
|
||||||
|
group: "jobs",
|
||||||
|
},
|
||||||
open_orders_csr: {
|
open_orders_csr: {
|
||||||
title: i18n.t("reportcenter.templates.open_orders_csr"),
|
title: i18n.t("reportcenter.templates.open_orders_csr"),
|
||||||
description: "",
|
description: "",
|
||||||
|
|||||||
2098
client/yarn.lock
2098
client/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -828,6 +828,7 @@
|
|||||||
- md_classes
|
- md_classes
|
||||||
- md_ded_notes
|
- md_ded_notes
|
||||||
- md_estimators
|
- md_estimators
|
||||||
|
- md_filehandlers
|
||||||
- md_hour_split
|
- md_hour_split
|
||||||
- md_ins_cos
|
- md_ins_cos
|
||||||
- md_jobline_presets
|
- md_jobline_presets
|
||||||
@@ -906,6 +907,7 @@
|
|||||||
- md_classes
|
- md_classes
|
||||||
- md_ded_notes
|
- md_ded_notes
|
||||||
- md_estimators
|
- md_estimators
|
||||||
|
- md_filehandlers
|
||||||
- md_hour_split
|
- md_hour_split
|
||||||
- md_ins_cos
|
- md_ins_cos
|
||||||
- md_jobline_presets
|
- md_jobline_presets
|
||||||
@@ -2590,6 +2592,7 @@
|
|||||||
- date_exported
|
- date_exported
|
||||||
- date_invoiced
|
- date_invoiced
|
||||||
- date_last_contacted
|
- date_last_contacted
|
||||||
|
- date_next_contact
|
||||||
- date_open
|
- date_open
|
||||||
- date_scheduled
|
- date_scheduled
|
||||||
- ded_amt
|
- ded_amt
|
||||||
@@ -2841,6 +2844,7 @@
|
|||||||
- date_exported
|
- date_exported
|
||||||
- date_invoiced
|
- date_invoiced
|
||||||
- date_last_contacted
|
- date_last_contacted
|
||||||
|
- date_next_contact
|
||||||
- date_open
|
- date_open
|
||||||
- date_scheduled
|
- date_scheduled
|
||||||
- ded_amt
|
- ded_amt
|
||||||
@@ -3102,6 +3106,7 @@
|
|||||||
- date_exported
|
- date_exported
|
||||||
- date_invoiced
|
- date_invoiced
|
||||||
- date_last_contacted
|
- date_last_contacted
|
||||||
|
- date_next_contact
|
||||||
- date_open
|
- date_open
|
||||||
- date_scheduled
|
- date_scheduled
|
||||||
- ded_amt
|
- ded_amt
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."bodyshops" add column "md_filehandlers" jsonb
|
||||||
|
-- null default jsonb_build_array();
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."bodyshops" add column "md_filehandlers" jsonb
|
||||||
|
null default jsonb_build_array();
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||||
|
null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."jobs" alter column "date_next_contact" drop not null;
|
||||||
|
alter table "public"."jobs" add column "date_next_contact" timestamptz;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."jobs" drop column "date_next_contact" cascade;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||||
|
null;
|
||||||
@@ -17,7 +17,8 @@
|
|||||||
"start": "node server.js"
|
"start": "node server.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aws-sdk": "^2.1013.0",
|
"aws-sdk": "^2.1023.0",
|
||||||
|
"axios": "^0.24.0",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
"body-parser": "^1.18.3",
|
"body-parser": "^1.18.3",
|
||||||
"cloudinary": "^1.27.1",
|
"cloudinary": "^1.27.1",
|
||||||
@@ -43,10 +44,10 @@
|
|||||||
"phone": "^3.1.8",
|
"phone": "^3.1.8",
|
||||||
"query-string": "^7.0.1",
|
"query-string": "^7.0.1",
|
||||||
"soap": "^0.42.0",
|
"soap": "^0.42.0",
|
||||||
"socket.io": "^4.3.1",
|
"socket.io": "^4.3.2",
|
||||||
"ssh2-sftp-client": "^7.1.0",
|
"ssh2-sftp-client": "^7.1.0",
|
||||||
"stripe": "^8.184.0",
|
"stripe": "^8.186.1",
|
||||||
"twilio": "^3.70.0",
|
"twilio": "^3.71.1",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"xmlbuilder2": "^3.0.2"
|
"xmlbuilder2": "^3.0.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ require("dotenv").config({
|
|||||||
`.env.${process.env.NODE_ENV || "development"}`
|
`.env.${process.env.NODE_ENV || "development"}`
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
const CdkBase = require("../web-sockets/web-socket");
|
|
||||||
|
|
||||||
const IMEX_PBS_USER = process.env.IMEX_PBS_USER,
|
const IMEX_PBS_USER = process.env.IMEX_PBS_USER,
|
||||||
IMEX_PBS_PASSWORD = process.env.IMEX_PBS_PASSWORD;
|
IMEX_PBS_PASSWORD = process.env.IMEX_PBS_PASSWORD;
|
||||||
@@ -19,3 +18,13 @@ exports.PBS_CREDENTIALS = PBS_CREDENTIALS;
|
|||||||
// process.env.NODE_ENV === "production"
|
// process.env.NODE_ENV === "production"
|
||||||
// ? "https://3pa.dmotorworks.com"
|
// ? "https://3pa.dmotorworks.com"
|
||||||
// : "https://uat-3pa.dmotorworks.com";
|
// : "https://uat-3pa.dmotorworks.com";
|
||||||
|
|
||||||
|
const pbsDomain = `https://partnerhub.pbsdealers.com/json/reply`;
|
||||||
|
exports.PBS_ENDPOINTS = {
|
||||||
|
AccountGet: `${pbsDomain}/AccountGet`,
|
||||||
|
ContactGet: `${pbsDomain}/ContactGet`,
|
||||||
|
VehicleGet: `${pbsDomain}/VehicleGet`,
|
||||||
|
AccountingPostingChange: `${pbsDomain}/AccountingPostingChange`,
|
||||||
|
ContactChange: `${pbsDomain}/ContactChange`,
|
||||||
|
VehicleChange: `${pbsDomain}/VehicleChange`,
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,25 +6,48 @@ require("dotenv").config({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||||
const soap = require("soap");
|
const axios = require("axios").default;
|
||||||
const queries = require("../../graphql-client/queries");
|
const queries = require("../../graphql-client/queries");
|
||||||
const CdkBase = require("../../web-sockets/web-socket");
|
const { PBS_ENDPOINTS, PBS_CREDENTIALS } = require("./pbs-constants");
|
||||||
|
|
||||||
//const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl");
|
//const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl");
|
||||||
//const CalcualteAllocations = require("./cdk-calculate-allocations").default;
|
const CalculateAllocations =
|
||||||
|
require("../../cdk/cdk-calculate-allocations").default;
|
||||||
|
const CdkBase = require("../../web-sockets/web-socket");
|
||||||
const moment = require("moment");
|
const moment = require("moment");
|
||||||
|
|
||||||
exports.default = async function (socket, jobid) {
|
exports.default = async function (socket, { txEnvelope, jobid }) {
|
||||||
socket.logEvents = [];
|
socket.logEvents = [];
|
||||||
socket.recordid = jobid;
|
socket.recordid = jobid;
|
||||||
|
socket.txEnvelope = txEnvelope;
|
||||||
try {
|
try {
|
||||||
CdkBase.createLogEvent(
|
CdkBase.createLogEvent(
|
||||||
socket,
|
socket,
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
`Received Job export request for id ${jobid}`
|
`Received Job export request for id ${jobid}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const JobData = await QueryJobData(socket, jobid);
|
||||||
|
socket.JobData = JobData;
|
||||||
|
|
||||||
|
//Query for the Vehicle record to get the associated customer.
|
||||||
|
// socket.DmsVeh = await QueryVehicleFromDms(socket);
|
||||||
|
//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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
socket.DMSCustList = await QueryCustomersFromDms(socket);
|
||||||
|
|
||||||
|
socket.emit("pbs-select-customer", [
|
||||||
|
...(socket.DMSVehCustomer
|
||||||
|
? [{ ...socket.DMSVehCustomer, vinOwner: true }]
|
||||||
|
: []),
|
||||||
|
...socket.DMSCustList,
|
||||||
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CdkBase.createLogEvent(
|
CdkBase.createLogEvent(
|
||||||
socket,
|
socket,
|
||||||
@@ -33,3 +56,570 @@ exports.default = async function (socket, jobid) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.PbsSelectedCustomer = async function PbsSelectedCustomer(
|
||||||
|
socket,
|
||||||
|
selectedCustomerId
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"DEBUG",
|
||||||
|
`User selected customer ${selectedCustomerId || "NEW"}`
|
||||||
|
);
|
||||||
|
|
||||||
|
//Upsert the contact information as per Wafaa's Email.
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"DEBUG",
|
||||||
|
`Upserting contact information to DMS for ${socket.JobData.ownr_fn} ${socket.JobData.ownr_ln} ${socket.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 UpsertVehicleData(socket, ownerRef.ReferenceId);
|
||||||
|
CdkBase.createLogEvent(socket, "DEBUG", `Inserting account data.`);
|
||||||
|
await InsertAccountPostingData(socket);
|
||||||
|
CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported.`);
|
||||||
|
// await MarkJobExported(socket, socket.JobData.id);
|
||||||
|
|
||||||
|
socket.emit("export-success", socket.JobData.id);
|
||||||
|
} catch (error) {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"ERROR",
|
||||||
|
`Error encountered in CdkSelectedCustomer. ${error}`
|
||||||
|
);
|
||||||
|
await InsertFailedExportLog(socket, error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function CheckForErrors(socket, response) {
|
||||||
|
if (response.WasSuccessful === undefined || response.WasSuccessful === true) {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"DEBUG",
|
||||||
|
`Succesful 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)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function QueryJobData(socket, jobid) {
|
||||||
|
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)}`
|
||||||
|
);
|
||||||
|
return result.jobs_by_pk;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function QueryVehicleFromDms(socket) {
|
||||||
|
try {
|
||||||
|
const { data: VehicleGetResponse } = await axios.post(
|
||||||
|
PBS_ENDPOINTS.VehicleGet,
|
||||||
|
{
|
||||||
|
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||||
|
// VehicleId: "00000000000000000000000000000000",
|
||||||
|
// Year: "String",
|
||||||
|
// Make: "String",
|
||||||
|
// Model: "String",
|
||||||
|
// Trim: "String",
|
||||||
|
// ModelNumber: "String",
|
||||||
|
// StockNumber: "String",
|
||||||
|
VIN: socket.JobData.v_vin,
|
||||||
|
// LicenseNumber: "String",
|
||||||
|
// Lot: "String",
|
||||||
|
// Status: "String",
|
||||||
|
// StatusList: ["String"],
|
||||||
|
// OwnerRef: "00000000000000000000000000000000",
|
||||||
|
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// LastSaleSince: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// VehicleIDList: ["00000000000000000000000000000000"],
|
||||||
|
// IncludeInactive: false,
|
||||||
|
// IncludeBuildVehicles: false,
|
||||||
|
// ShortVIN: "String",
|
||||||
|
},
|
||||||
|
{ auth: PBS_CREDENTIALS }
|
||||||
|
);
|
||||||
|
CheckForErrors(socket, VehicleGetResponse);
|
||||||
|
return VehicleGetResponse;
|
||||||
|
} catch (error) {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"ERROR",
|
||||||
|
`Error in QueryVehicleFromDms - ${error}`
|
||||||
|
);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function QueryCustomersFromDms(socket) {
|
||||||
|
try {
|
||||||
|
const { data: CustomerGetResponse } = await axios.post(
|
||||||
|
PBS_ENDPOINTS.ContactGet,
|
||||||
|
{
|
||||||
|
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||||
|
//ContactId: "00000000000000000000000000000000",
|
||||||
|
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,
|
||||||
|
// EmailAddress: "String",
|
||||||
|
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// ContactIdList: ["00000000000000000000000000000000"],
|
||||||
|
// IncludeInactive: false,
|
||||||
|
// PayableAccount: "String",
|
||||||
|
// ReceivableAccount: "String",
|
||||||
|
// DriverLicense: "String",
|
||||||
|
// ZipCode: "String",
|
||||||
|
},
|
||||||
|
{ auth: PBS_CREDENTIALS }
|
||||||
|
);
|
||||||
|
CheckForErrors(socket, CustomerGetResponse);
|
||||||
|
return CustomerGetResponse && CustomerGetResponse.Contacts;
|
||||||
|
} catch (error) {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"ERROR",
|
||||||
|
`Error in QueryCustomersFromDms - ${error}`
|
||||||
|
);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function QueryCustomerBycodeFromDms(socket, CustomerRef) {
|
||||||
|
try {
|
||||||
|
const { data: CustomerGetResponse } = await axios.post(
|
||||||
|
PBS_ENDPOINTS.ContactGet,
|
||||||
|
{
|
||||||
|
SerialNumber: socket.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,
|
||||||
|
// EmailAddress: "String",
|
||||||
|
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// ContactIdList: ["00000000000000000000000000000000"],
|
||||||
|
// IncludeInactive: false,
|
||||||
|
// PayableAccount: "String",
|
||||||
|
// ReceivableAccount: "String",
|
||||||
|
// DriverLicense: "String",
|
||||||
|
// ZipCode: "String",
|
||||||
|
},
|
||||||
|
{ auth: PBS_CREDENTIALS }
|
||||||
|
);
|
||||||
|
CheckForErrors(socket, CustomerGetResponse);
|
||||||
|
return CustomerGetResponse && CustomerGetResponse.Contacts;
|
||||||
|
} catch (error) {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"ERROR",
|
||||||
|
`Error in QueryCustomersFromDms - ${error}`
|
||||||
|
);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function UpsertContactData(socket, selectedCustomerId) {
|
||||||
|
try {
|
||||||
|
const { data: ContactChangeResponse } = await axios.post(
|
||||||
|
PBS_ENDPOINTS.ContactChange,
|
||||||
|
{
|
||||||
|
ContactInfo: {
|
||||||
|
// Id: socket.JobData.owner.id,
|
||||||
|
...(selectedCustomerId ? { ContactId: selectedCustomerId } : {}),
|
||||||
|
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||||
|
Code: socket.JobData.owner.accountingid,
|
||||||
|
...(socket.JobData.ownr_co_nm
|
||||||
|
? {
|
||||||
|
//LastName: socket.JobData.ownr_ln,
|
||||||
|
FirstName: socket.JobData.ownr_co_nm,
|
||||||
|
IsBusiness: true,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
LastName: socket.JobData.ownr_ln,
|
||||||
|
FirstName: socket.JobData.ownr_fn,
|
||||||
|
IsBusiness: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
//Salutation: "String",
|
||||||
|
//MiddleName: "String",
|
||||||
|
//ContactName: "String",
|
||||||
|
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,
|
||||||
|
//BusinessPhone: "String",
|
||||||
|
//BusinessPhoneExt: "String",
|
||||||
|
HomePhone: socket.JobData.ownr_ph2,
|
||||||
|
CellPhone: socket.JobData.ownr_ph1,
|
||||||
|
//BusinessPhoneRawReverse: "String",
|
||||||
|
//HomePhoneRawReverse: "String",
|
||||||
|
//CellPhoneRawReverse: "String",
|
||||||
|
//FaxNumber: "String",
|
||||||
|
EmailAddress: socket.JobData.ownr_ea,
|
||||||
|
//Notes: "String",
|
||||||
|
//CriticalMemo: "String",
|
||||||
|
//BirthDate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// Gender: "String",
|
||||||
|
// DriverLicense: "String",
|
||||||
|
//PreferredContactMethods: ["String"],
|
||||||
|
// LastUpdate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// CustomFields: [{ Key: "String", Value: "String", Type: "String" }],
|
||||||
|
// FleetType: "String",
|
||||||
|
// CommunicationPreferences: {
|
||||||
|
// Email: "String",
|
||||||
|
// Phone: "String",
|
||||||
|
// TextMessage: "String",
|
||||||
|
// Letter: "String",
|
||||||
|
// Preferred: "String",
|
||||||
|
// },
|
||||||
|
// SalesRepRef: "00000000000000000000000000000000",
|
||||||
|
// Language: "String",
|
||||||
|
// PayableAccount: "String",
|
||||||
|
// ReceivableAccount: "String",
|
||||||
|
// IsStatic: false,
|
||||||
|
// PrimaryImageRef: "00000000000000000000000000000000",
|
||||||
|
// PayableAccounts: [{ SerialNumber: "String", Account: "String" }],
|
||||||
|
// ReceivableAccounts: [{ SerialNumber: "String", Account: "String" }],
|
||||||
|
// ManufacturerLoyaltyNumber: "String",
|
||||||
|
},
|
||||||
|
IsAsynchronous: false,
|
||||||
|
// UserRequest: "String",
|
||||||
|
// UserRef: "00000000000000000000000000000000",
|
||||||
|
},
|
||||||
|
{ auth: PBS_CREDENTIALS }
|
||||||
|
);
|
||||||
|
CheckForErrors(socket, ContactChangeResponse);
|
||||||
|
return ContactChangeResponse;
|
||||||
|
} catch (error) {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"ERROR",
|
||||||
|
`Error in UpsertContactData - ${error}`
|
||||||
|
);
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function UpsertVehicleData(socket, ownerRef) {
|
||||||
|
try {
|
||||||
|
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,
|
||||||
|
//StockNumber: "String",
|
||||||
|
VIN: socket.JobData.v_vin,
|
||||||
|
LicenseNumber: socket.JobData.plate_no,
|
||||||
|
//FleetNumber: "String",
|
||||||
|
//Status: "String",
|
||||||
|
OwnerRef: ownerRef, // "00000000000000000000000000000000",
|
||||||
|
//ModelNumber: "String",
|
||||||
|
Make: socket.JobData.v_make_desc,
|
||||||
|
Model: socket.JobData.v_model_desc,
|
||||||
|
//Trim: "String",
|
||||||
|
//VehicleType: "String",
|
||||||
|
Year: socket.JobData.v_model_yr,
|
||||||
|
Odometer: socket.JobData.kmin,
|
||||||
|
ExteriorColor: {
|
||||||
|
Code: socket.JobData.v_color,
|
||||||
|
//Description: "String",
|
||||||
|
},
|
||||||
|
// InteriorColor: { Code: "String", Description: "String" },
|
||||||
|
//Engine: "String",
|
||||||
|
// Cylinders: "String",
|
||||||
|
// Transmission: "String",
|
||||||
|
// DriveWheel: "String",
|
||||||
|
// Fuel: "String",
|
||||||
|
// Weight: 0,
|
||||||
|
// InServiceDate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// LastServiceDate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// LastServiceMileage: 0,
|
||||||
|
// Lot: "String",
|
||||||
|
// LotDescription: "String",
|
||||||
|
// Category: "String",
|
||||||
|
// Options: [
|
||||||
|
// {
|
||||||
|
// Group: "String",
|
||||||
|
// Code: "String",
|
||||||
|
// Description: "String",
|
||||||
|
// AdditionalInfo: "String",
|
||||||
|
// Price: 0,
|
||||||
|
// Cost: 0,
|
||||||
|
// Residual: 0,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// Refurbishments: [
|
||||||
|
// {
|
||||||
|
// ReferenceNumber: "String",
|
||||||
|
// Description: "String",
|
||||||
|
// Price: 0,
|
||||||
|
// Cost: 0,
|
||||||
|
// Date: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// ApplicationModel: "String",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// Order: {
|
||||||
|
// InvoiceNumber: "String",
|
||||||
|
// Price: 0,
|
||||||
|
// Status: "String",
|
||||||
|
// Eta: "String",
|
||||||
|
// EstimatedCost: 0,
|
||||||
|
// OrderDate: "String",
|
||||||
|
// StatusDate: "String",
|
||||||
|
// IgnitionKeyCode: "String",
|
||||||
|
// DoorKeyCode: "String",
|
||||||
|
// Description: "String",
|
||||||
|
// LocationStatus: "String",
|
||||||
|
// LocationStatusDate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// },
|
||||||
|
// MSR: 0,
|
||||||
|
// BaseMSR: 0,
|
||||||
|
// Retail: 0,
|
||||||
|
// DateReceived: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// InternetPrice: 0,
|
||||||
|
// Lotpack: 0,
|
||||||
|
// Holdback: 0,
|
||||||
|
// InternetNotes: "String",
|
||||||
|
// Notes: "String",
|
||||||
|
// CriticalMemo: "String",
|
||||||
|
// IsCertified: false,
|
||||||
|
// LastSaleDate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// LastUpdate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// AppraisedValue: 0,
|
||||||
|
// Warranties: [
|
||||||
|
// {
|
||||||
|
// Type: "String",
|
||||||
|
// CompanyName: "String",
|
||||||
|
// CoveragePlan: "String",
|
||||||
|
// Description: "String",
|
||||||
|
// Price: 0,
|
||||||
|
// Cost: 0,
|
||||||
|
// Term: "String",
|
||||||
|
// Deductible: 0,
|
||||||
|
// PolicyNumber: "String",
|
||||||
|
// StartDate: "String",
|
||||||
|
// StartMileage: 0,
|
||||||
|
// ExpirationDate: "String",
|
||||||
|
// ExpirationMileage: 0,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// Freight: 0,
|
||||||
|
// Air: 0,
|
||||||
|
// Inventory: 0,
|
||||||
|
// IsInactive: false,
|
||||||
|
// CustomFields: [{ Key: "String", Value: "String", Type: "String" }],
|
||||||
|
// FloorPlanCode: "String",
|
||||||
|
// FloorPlanAmount: 0,
|
||||||
|
// Insurance: {
|
||||||
|
// Company: "String",
|
||||||
|
// Policy: "String",
|
||||||
|
// ExpiryDate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// AgentName: "String",
|
||||||
|
// AgentPhoneNumber: "String",
|
||||||
|
// },
|
||||||
|
// Body: "String",
|
||||||
|
// ShortVIN: "String",
|
||||||
|
// AdditionalDrivers: ["00000000000000000000000000000000"],
|
||||||
|
// OrderDetails: { Distributor: "String" },
|
||||||
|
// PrimaryImageRef: "00000000000000000000000000000000",
|
||||||
|
// Hold: {
|
||||||
|
// VehicleRef: "00000000000000000000000000000000",
|
||||||
|
// HoldFrom: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// HoldUntil: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// UserRef: "00000000000000000000000000000000",
|
||||||
|
// ContactRef: "00000000000000000000000000000000",
|
||||||
|
// Comments: "String",
|
||||||
|
// },
|
||||||
|
// SeatingCapacity: "String",
|
||||||
|
// DeliveryDate: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// WarrantyExpiry: "0001-01-01T00:00:00.0000000Z",
|
||||||
|
// IsConditionallySold: false,
|
||||||
|
// SalesDivision: 0,
|
||||||
|
// StyleRef: "String",
|
||||||
|
},
|
||||||
|
IsAsynchronous: false,
|
||||||
|
// UserRequest: "String",
|
||||||
|
// UserRef: "00000000000000000000000000000000",
|
||||||
|
},
|
||||||
|
{ auth: PBS_CREDENTIALS }
|
||||||
|
);
|
||||||
|
CheckForErrors(socket, VehicleChangeResponse);
|
||||||
|
return VehicleChangeResponse;
|
||||||
|
} catch (error) {
|
||||||
|
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 wips = [];
|
||||||
|
allocations.forEach((alloc) => {
|
||||||
|
//Add the sale item from each allocation.
|
||||||
|
if (alloc.sale.getAmount() > 0 && !alloc.tax) {
|
||||||
|
const item = {
|
||||||
|
Account: alloc.profitCenter.dms_acctnumber,
|
||||||
|
ControlNumber: socket.JobData.ro_number,
|
||||||
|
Amount: alloc.sale.multiply(-1).toFormat("0.0"),
|
||||||
|
//Comment: "String",
|
||||||
|
//AdditionalInfo: "String",
|
||||||
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
|
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||||
|
};
|
||||||
|
wips.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add the cost Item.
|
||||||
|
if (alloc.cost.getAmount() > 0 && !alloc.tax) {
|
||||||
|
const item = {
|
||||||
|
Account: alloc.costCenter.dms_acctnumber,
|
||||||
|
ControlNumber: socket.JobData.ro_number,
|
||||||
|
Amount: alloc.cost.toFormat("0.0"),
|
||||||
|
//Comment: "String",
|
||||||
|
//AdditionalInfo: "String",
|
||||||
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
|
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||||
|
};
|
||||||
|
wips.push(item);
|
||||||
|
|
||||||
|
const itemWip = {
|
||||||
|
Account: alloc.costCenter.dms_wip_acctnumber,
|
||||||
|
ControlNumber: socket.JobData.ro_number,
|
||||||
|
Amount: alloc.cost.multiply(-1).toFormat("0.0"),
|
||||||
|
//Comment: "String",
|
||||||
|
//AdditionalInfo: "String",
|
||||||
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
|
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||||
|
};
|
||||||
|
wips.push(itemWip);
|
||||||
|
//Add to the WIP account.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alloc.tax) {
|
||||||
|
if (alloc.sale.getAmount() > 0) {
|
||||||
|
const item2 = {
|
||||||
|
Account: alloc.profitCenter.dms_acctnumber,
|
||||||
|
ControlNumber: socket.JobData.ro_number,
|
||||||
|
Amount: alloc.sale.multiply(-1).toFormat("0.0"),
|
||||||
|
//Comment: "String",
|
||||||
|
//AdditionalInfo: "String",
|
||||||
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
|
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||||
|
};
|
||||||
|
wips.push(item2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: AccountPostingChange } = await axios.post(
|
||||||
|
PBS_ENDPOINTS.AccountingPostingChange,
|
||||||
|
{
|
||||||
|
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||||
|
Posting: {
|
||||||
|
Reference: socket.JobData.ro_number,
|
||||||
|
JournalCode: socket.txEnvelope.journal,
|
||||||
|
TransactionDate: moment(socket.JobData.date_invoiced).toISOString(), //"0001-01-01T00:00:00.0000000Z",
|
||||||
|
Description: socket.txEnvelope.story,
|
||||||
|
//AdditionalInfo: "String",
|
||||||
|
Source: "ImEX Online",
|
||||||
|
Lines: wips,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ auth: PBS_CREDENTIALS }
|
||||||
|
);
|
||||||
|
|
||||||
|
CheckForErrors(socket, AccountPostingChange);
|
||||||
|
return AccountPostingChange;
|
||||||
|
} catch (error) {
|
||||||
|
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}`
|
||||||
|
);
|
||||||
|
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||||
|
const result = 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*",
|
||||||
|
date_exported: new Date(),
|
||||||
|
},
|
||||||
|
log: {
|
||||||
|
bodyshopid: socket.JobData.bodyshop.id,
|
||||||
|
jobid: jobid,
|
||||||
|
successful: true,
|
||||||
|
useremail: socket.user.email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function InsertFailedExportLog(socket, error) {
|
||||||
|
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||||
|
const result = await client
|
||||||
|
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||||
|
.request(queries.INSERT_EXPORT_LOG, {
|
||||||
|
log: {
|
||||||
|
bodyshopid: socket.JobData.bodyshop.id,
|
||||||
|
jobid: socket.JobData.id,
|
||||||
|
successful: false,
|
||||||
|
message: [error],
|
||||||
|
useremail: socket.user.email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,7 +76,12 @@ exports.default = function ({
|
|||||||
{
|
{
|
||||||
local: false,
|
local: false,
|
||||||
federal: true,
|
federal: true,
|
||||||
state: (jobline.db_ref === "900511" || jobline.db_ref === "900510") ? true: jobline.tax_part,
|
state:
|
||||||
|
jobs_by_pk.state_tax_rate === 0
|
||||||
|
? false
|
||||||
|
: jobline.db_ref === "900511" || jobline.db_ref === "900510"
|
||||||
|
? true
|
||||||
|
: jobline.tax_part,
|
||||||
},
|
},
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||||
);
|
);
|
||||||
@@ -142,7 +147,7 @@ exports.default = function ({
|
|||||||
{
|
{
|
||||||
local: false,
|
local: false,
|
||||||
federal: true,
|
federal: true,
|
||||||
state: true,
|
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||||
},
|
},
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||||
);
|
);
|
||||||
@@ -204,7 +209,7 @@ exports.default = function ({
|
|||||||
{
|
{
|
||||||
local: false,
|
local: false,
|
||||||
federal: true,
|
federal: true,
|
||||||
state: true,
|
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||||
},
|
},
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||||
);
|
);
|
||||||
@@ -267,7 +272,7 @@ exports.default = function ({
|
|||||||
{
|
{
|
||||||
local: false,
|
local: false,
|
||||||
federal: true,
|
federal: true,
|
||||||
state: true,
|
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||||
},
|
},
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||||
);
|
);
|
||||||
@@ -346,7 +351,7 @@ exports.default = function ({
|
|||||||
{
|
{
|
||||||
local: false,
|
local: false,
|
||||||
federal: true,
|
federal: true,
|
||||||
state: true,
|
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||||
},
|
},
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||||
);
|
);
|
||||||
@@ -394,7 +399,7 @@ exports.default = function ({
|
|||||||
{
|
{
|
||||||
local: false,
|
local: false,
|
||||||
federal: true,
|
federal: true,
|
||||||
state: true,
|
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||||
},
|
},
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||||
);
|
);
|
||||||
@@ -445,7 +450,7 @@ exports.default = function ({
|
|||||||
{
|
{
|
||||||
local: false,
|
local: false,
|
||||||
federal: true,
|
federal: true,
|
||||||
state: true,
|
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||||
},
|
},
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -70,11 +70,15 @@ exports.default = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ret = builder
|
var ret = builder
|
||||||
.create(autoHouseObject, {
|
.create(
|
||||||
version: "1.0",
|
{
|
||||||
encoding: "UTF-8",
|
version: "1.0",
|
||||||
})
|
encoding: "UTF-8",
|
||||||
.end({ pretty: true, allowEmptyTags: true });
|
keepNullNodes: true,
|
||||||
|
},
|
||||||
|
autoHouseObject
|
||||||
|
)
|
||||||
|
.end({ allowEmptyTags: true });
|
||||||
|
|
||||||
allxmlsToUpload.push({
|
allxmlsToUpload.push({
|
||||||
xml: ret,
|
xml: ret,
|
||||||
@@ -107,6 +111,11 @@ exports.default = async (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== "production") {
|
||||||
|
res.sendStatus(200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let sftp = new Client();
|
let sftp = new Client();
|
||||||
sftp.on("error", (errors) =>
|
sftp.on("error", (errors) =>
|
||||||
logger.log("autohouse-sftp-error", "ERROR", "api", null, {
|
logger.log("autohouse-sftp-error", "ERROR", "api", null, {
|
||||||
@@ -239,7 +248,8 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
ReferralDate: null,
|
ReferralDate: null,
|
||||||
EstimateAppointmentDate: null,
|
EstimateAppointmentDate: null,
|
||||||
SecondFollowUpDate: null,
|
SecondFollowUpDate: null,
|
||||||
AssignedDate: null,
|
AssignedDate:
|
||||||
|
job.asgn_date && moment(job.asgn_date).format(AhDateFormat),
|
||||||
EstComplete: null,
|
EstComplete: null,
|
||||||
CustomerAuthorizationDate: null,
|
CustomerAuthorizationDate: null,
|
||||||
InsuranceAuthorizationDate: null,
|
InsuranceAuthorizationDate: null,
|
||||||
@@ -248,7 +258,7 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
job.scheduled_in && moment(job.scheduled_in).format(AhDateFormat),
|
job.scheduled_in && moment(job.scheduled_in).format(AhDateFormat),
|
||||||
CarinShop: job.actual_in && moment(job.actual_in).format(AhDateFormat),
|
CarinShop: job.actual_in && moment(job.actual_in).format(AhDateFormat),
|
||||||
InsInspDate: null,
|
InsInspDate: null,
|
||||||
StartDate: null,
|
StartDate: job.actual_in && moment(job.actual_in).format(AhDateFormat),
|
||||||
PartsOrder: null,
|
PartsOrder: null,
|
||||||
TeardownHold: null,
|
TeardownHold: null,
|
||||||
SupplementSubmittedDate: null,
|
SupplementSubmittedDate: null,
|
||||||
@@ -287,7 +297,10 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
StructuralRate: job.rate_las,
|
StructuralRate: job.rate_las,
|
||||||
PMRate: job.rate_mapa,
|
PMRate: job.rate_mapa,
|
||||||
BMRate: job.rate_mash,
|
BMRate: job.rate_mash,
|
||||||
TaxRate: null,
|
TaxRate:
|
||||||
|
job.parts_tax_rates &&
|
||||||
|
job.parts_tax_rates.PAN &&
|
||||||
|
job.parts_tax_rates.PAN.prt_tax_rt,
|
||||||
StorageRateperDay: null,
|
StorageRateperDay: null,
|
||||||
DaysStored: null,
|
DaysStored: null,
|
||||||
},
|
},
|
||||||
@@ -389,39 +402,45 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
job.job_totals.parts.parts.list.PAA.total
|
job.job_totals.parts.parts.list.PAA.total
|
||||||
).toFormat(AHDineroFormat),
|
).toFormat(AHDineroFormat),
|
||||||
PartsAMCost: repairCosts.PartsAMCost.toFormat(AHDineroFormat),
|
PartsAMCost: repairCosts.PartsAMCost.toFormat(AHDineroFormat),
|
||||||
PartsReconditioned: null,
|
PartsReconditioned:
|
||||||
|
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
|
||||||
PartsReconditionedCost:
|
PartsReconditionedCost:
|
||||||
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
|
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
|
||||||
PartsRecycled: Dinero(
|
PartsRecycled: Dinero(
|
||||||
job.job_totals.parts.parts.list.PAR &&
|
job.job_totals.parts.parts.list.PAR &&
|
||||||
job.job_totals.parts.parts.list.PAR.total
|
job.job_totals.parts.parts.list.PAR.total
|
||||||
).toFormat(AHDineroFormat),
|
).toFormat(AHDineroFormat),
|
||||||
PartsRecycledCost: null,
|
PartsRecycledCost:
|
||||||
|
repairCosts.PartsRecycledCost.toFormat(AHDineroFormat),
|
||||||
PartsOther: Dinero(
|
PartsOther: Dinero(
|
||||||
job.job_totals.parts.parts.list.PAO &&
|
job.job_totals.parts.parts.list.PAO &&
|
||||||
job.job_totals.parts.parts.list.PAO.total
|
job.job_totals.parts.parts.list.PAO.total
|
||||||
).toFormat(AHDineroFormat),
|
).toFormat(AHDineroFormat),
|
||||||
PartsOtherCost: null,
|
PartsOtherCost: repairCosts.PartsOtherCost.toFormat(AHDineroFormat),
|
||||||
SubletTotal: Dinero(job.job_totals.parts.sublets.total).toFormat(
|
SubletTotal: Dinero(job.job_totals.parts.sublets.total).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
SubletTotalCost: 0,
|
SubletTotalCost: repairCosts.SubletTotalCost.toFormat(AHDineroFormat),
|
||||||
BodyLaborTotal: Dinero(job.job_totals.rates.lab.total).toFormat(
|
BodyLaborTotal: Dinero(job.job_totals.rates.lab.total).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
BodyLaborTotalCost: 0,
|
BodyLaborTotalCost:
|
||||||
|
repairCosts.BodyLaborTotalCost.toFormat(AHDineroFormat),
|
||||||
RefinishLaborTotal: Dinero(job.job_totals.rates.lar.total).toFormat(
|
RefinishLaborTotal: Dinero(job.job_totals.rates.lar.total).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
RefinishLaborTotalCost: 0,
|
RefinishLaborTotalCost:
|
||||||
|
repairCosts.RefinishLaborTotalCost.toFormat(AHDineroFormat),
|
||||||
MechanicalLaborTotal: Dinero(job.job_totals.rates.lam.total).toFormat(
|
MechanicalLaborTotal: Dinero(job.job_totals.rates.lam.total).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
MechanicalLaborTotalCost: 0,
|
MechanicalLaborTotalCost:
|
||||||
|
repairCosts.MechanicalLaborTotalCost.toFormat(AHDineroFormat),
|
||||||
StructuralLaborTotal: Dinero(job.job_totals.rates.las.total).toFormat(
|
StructuralLaborTotal: Dinero(job.job_totals.rates.las.total).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
StructuralLaborTotalCost: null,
|
StructuralLaborTotalCost:
|
||||||
|
repairCosts.StructuralLaborTotalCost.toFormat(AHDineroFormat),
|
||||||
MiscellaneousChargeTotal: null,
|
MiscellaneousChargeTotal: null,
|
||||||
MiscellaneousChargeTotalCost: null,
|
MiscellaneousChargeTotalCost: null,
|
||||||
PMTotal: Dinero(job.job_totals.rates.mapa.total).toFormat(
|
PMTotal: Dinero(job.job_totals.rates.mapa.total).toFormat(
|
||||||
@@ -437,11 +456,11 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
TowingTotal: Dinero(job.job_totals.additional.towing).toFormat(
|
TowingTotal: Dinero(job.job_totals.additional.towing).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
TowingTotalCost: null,
|
TowingTotalCost: repairCosts.TowingTotalCost.toFormat(AHDineroFormat),
|
||||||
StorageTotal: Dinero(job.job_totals.additional.storage).toFormat(
|
StorageTotal: Dinero(job.job_totals.additional.storage).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
StorageTotalCost: null,
|
StorageTotalCost: repairCosts.StorageTotalCost.toFormat(AHDineroFormat),
|
||||||
DetailTotal: null,
|
DetailTotal: null,
|
||||||
DetailTotalCost: null,
|
DetailTotalCost: null,
|
||||||
SalesTaxTotal: Dinero(job.job_totals.totals.local_tax)
|
SalesTaxTotal: Dinero(job.job_totals.totals.local_tax)
|
||||||
@@ -472,7 +491,7 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
Hub50Comment: null,
|
Hub50Comment: null,
|
||||||
DateofChange: null,
|
DateofChange: null,
|
||||||
BodyTechName: null,
|
BodyTechName: null,
|
||||||
TotalLossYN: null,
|
TotalLossYN: job.tlos_ind ? "Y" : "N",
|
||||||
InsScreenCommentsLine1: null,
|
InsScreenCommentsLine1: null,
|
||||||
InsScreenCommentsLine2: null,
|
InsScreenCommentsLine2: null,
|
||||||
AssignmentCaller: null,
|
AssignmentCaller: null,
|
||||||
@@ -483,7 +502,9 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
PaintTechName: null,
|
PaintTechName: null,
|
||||||
ImportType: null,
|
ImportType: null,
|
||||||
ImportFile: null,
|
ImportFile: null,
|
||||||
GSTTax: null,
|
GSTTax: Dinero(job.job_totals.totals.federal_tax).toFormat(
|
||||||
|
AHDineroFormat
|
||||||
|
),
|
||||||
RepairDelayStatusCode: null,
|
RepairDelayStatusCode: null,
|
||||||
RepairDelaycomment: null,
|
RepairDelaycomment: null,
|
||||||
AgentMktgID: null,
|
AgentMktgID: null,
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
|
|||||||
towing_payable
|
towing_payable
|
||||||
storage_payable
|
storage_payable
|
||||||
adjustment_bottom_line
|
adjustment_bottom_line
|
||||||
|
state_tax_rate
|
||||||
owner {
|
owner {
|
||||||
accountingid
|
accountingid
|
||||||
}
|
}
|
||||||
@@ -242,6 +243,94 @@ query QUERY_JOBS_FOR_CDK_EXPORT($id: uuid!) {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports.QUERY_JOBS_FOR_PBS_EXPORT = `
|
||||||
|
query QUERY_JOBS_FOR_PBS_EXPORT($id: uuid!) {
|
||||||
|
jobs_by_pk(id: $id) {
|
||||||
|
id
|
||||||
|
job_totals
|
||||||
|
date_invoiced
|
||||||
|
ro_number
|
||||||
|
clm_total
|
||||||
|
clm_no
|
||||||
|
invoice_allocation
|
||||||
|
ownerid
|
||||||
|
ownr_ln
|
||||||
|
ownr_fn
|
||||||
|
ownr_addr1
|
||||||
|
ownr_addr2
|
||||||
|
ownr_ph1
|
||||||
|
ownr_ph2
|
||||||
|
ownr_zip
|
||||||
|
ownr_city
|
||||||
|
ownr_ctry
|
||||||
|
ownr_st
|
||||||
|
ownr_ea
|
||||||
|
ins_co_nm
|
||||||
|
job_totals
|
||||||
|
rate_la1
|
||||||
|
rate_la2
|
||||||
|
rate_la3
|
||||||
|
rate_la4
|
||||||
|
rate_laa
|
||||||
|
rate_lab
|
||||||
|
rate_lad
|
||||||
|
rate_lae
|
||||||
|
rate_laf
|
||||||
|
rate_lag
|
||||||
|
rate_lam
|
||||||
|
rate_lar
|
||||||
|
rate_las
|
||||||
|
rate_lau
|
||||||
|
rate_ma2s
|
||||||
|
rate_ma2t
|
||||||
|
rate_ma3s
|
||||||
|
rate_mabl
|
||||||
|
rate_macs
|
||||||
|
rate_mahw
|
||||||
|
rate_mapa
|
||||||
|
rate_mash
|
||||||
|
rate_matd
|
||||||
|
class
|
||||||
|
ca_bc_pvrt
|
||||||
|
plate_no
|
||||||
|
plate_st
|
||||||
|
v_vin
|
||||||
|
v_model_yr
|
||||||
|
v_model_desc
|
||||||
|
v_make_desc
|
||||||
|
v_color
|
||||||
|
ca_customer_gst
|
||||||
|
bodyshop {
|
||||||
|
id
|
||||||
|
md_ro_statuses
|
||||||
|
md_responsibility_centers
|
||||||
|
accountingconfig
|
||||||
|
pbs_serialnumber
|
||||||
|
pbs_configuration
|
||||||
|
}
|
||||||
|
owner {
|
||||||
|
id
|
||||||
|
accountingid
|
||||||
|
}
|
||||||
|
joblines(where:{removed: {_eq:false}}) {
|
||||||
|
id
|
||||||
|
line_desc
|
||||||
|
part_type
|
||||||
|
act_price
|
||||||
|
mod_lb_hrs
|
||||||
|
mod_lbr_ty
|
||||||
|
part_qty
|
||||||
|
op_code_desc
|
||||||
|
profitcenter_labor
|
||||||
|
profitcenter_part
|
||||||
|
db_ref
|
||||||
|
prt_dsmk_p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
exports.QUERY_BILLS_FOR_PAYABLES_EXPORT = `
|
exports.QUERY_BILLS_FOR_PAYABLES_EXPORT = `
|
||||||
query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
|
query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
|
||||||
bills(where: {id: {_in: $bills}}) {
|
bills(where: {id: {_in: $bills}}) {
|
||||||
@@ -465,6 +554,7 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshop
|
|||||||
rate_mash
|
rate_mash
|
||||||
job_totals
|
job_totals
|
||||||
driveable
|
driveable
|
||||||
|
parts_tax_rates
|
||||||
bodyshop {
|
bodyshop {
|
||||||
id
|
id
|
||||||
shopname
|
shopname
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const CdkCalculateAllocations =
|
|||||||
require("../cdk/cdk-calculate-allocations").default;
|
require("../cdk/cdk-calculate-allocations").default;
|
||||||
const { isArray } = require("lodash");
|
const { isArray } = require("lodash");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
const PbsExportJob = require("../accounting/pbs/pbs-job-export");
|
const {default: PbsExportJob, PbsSelectedCustomer} = require("../accounting/pbs/pbs-job-export");
|
||||||
|
|
||||||
io.use(function (socket, next) {
|
io.use(function (socket, next) {
|
||||||
try {
|
try {
|
||||||
@@ -99,9 +99,29 @@ io.on("connection", (socket) => {
|
|||||||
//END CDK
|
//END CDK
|
||||||
|
|
||||||
//PBS
|
//PBS
|
||||||
|
socket.on("pbs-calculate-allocations", async (jobid, callback) => {
|
||||||
|
const allocations = await CdkCalculateAllocations(socket, jobid);
|
||||||
|
createLogEvent(socket, "DEBUG", `Allocations calculated.`);
|
||||||
|
createLogEvent(
|
||||||
|
socket,
|
||||||
|
"TRACE",
|
||||||
|
`Allocations calculated. ${JSON.stringify(allocations, null, 2)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
callback(allocations);
|
||||||
|
});
|
||||||
socket.on("pbs-export-job", (jobid) => {
|
socket.on("pbs-export-job", (jobid) => {
|
||||||
PbsExportJob(socket, jobid);
|
PbsExportJob(socket, jobid);
|
||||||
});
|
});
|
||||||
|
socket.on("pbs-selected-customer", (selectedCustomerId) => {
|
||||||
|
createLogEvent(
|
||||||
|
socket,
|
||||||
|
"DEBUG",
|
||||||
|
`User selected customer ID ${selectedCustomerId}`
|
||||||
|
);
|
||||||
|
socket.selectedCustomerId = selectedCustomerId;
|
||||||
|
PbsSelectedCustomer(socket, selectedCustomerId);
|
||||||
|
});
|
||||||
//End PBS
|
//End PBS
|
||||||
|
|
||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
|
|||||||
44
yarn.lock
44
yarn.lock
@@ -600,10 +600,10 @@ atob@2.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||||
|
|
||||||
aws-sdk@^2.1013.0:
|
aws-sdk@^2.1023.0:
|
||||||
version "2.1013.0"
|
version "2.1023.0"
|
||||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1013.0.tgz#85babc473b0bc90cc1160eb48baf616ddb86e346"
|
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1023.0.tgz#0de16e4e8878ccec4fcd0146322dcf94fdbe09ba"
|
||||||
integrity sha512-TXxkp/meAdofpC15goFpNuur7fvh/mcMRfHJoP1jYzTtD0wcoB4FK16GLcny0uDYgkQgZuiO9QYv3Rq5bhGCqQ==
|
integrity sha512-RAI8sUfK+00yL9i3xz5kbM3+t/0mjjnKhKyauXAlJN4seDYtIX5+BqMghpkZwvLBdi6idXIuz+FHWETHZccyuA==
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer "4.9.2"
|
buffer "4.9.2"
|
||||||
events "1.1.1"
|
events "1.1.1"
|
||||||
@@ -646,6 +646,13 @@ axios@^0.21.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.14.0"
|
follow-redirects "^1.14.0"
|
||||||
|
|
||||||
|
axios@^0.24.0:
|
||||||
|
version "0.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
|
||||||
|
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.14.4"
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
@@ -1743,6 +1750,11 @@ follow-redirects@^1.14.0:
|
|||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
|
||||||
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
|
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
|
||||||
|
|
||||||
|
follow-redirects@^1.14.4:
|
||||||
|
version "1.14.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381"
|
||||||
|
integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==
|
||||||
|
|
||||||
forever-agent@~0.6.1:
|
forever-agent@~0.6.1:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||||
@@ -3541,10 +3553,10 @@ socket.io-parser@~4.0.4:
|
|||||||
component-emitter "~1.3.0"
|
component-emitter "~1.3.0"
|
||||||
debug "~4.3.1"
|
debug "~4.3.1"
|
||||||
|
|
||||||
socket.io@^4.3.1:
|
socket.io@^4.3.2:
|
||||||
version "4.3.1"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.3.1.tgz#c0aa14f3f916a8ab713e83a5bd20c16600245763"
|
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.3.2.tgz#85ae0cf5cf18acbce648ac9f48aba66df8cea6bf"
|
||||||
integrity sha512-HC5w5Olv2XZ0XJ4gOLGzzHEuOCfj3G0SmoW3jLHYYh34EVsIr3EkW9h6kgfW+K3TFEcmYy8JcPWe//KUkBp5jA==
|
integrity sha512-6S5tV4jcY6dbZ/lLzD6EkvNWI3s81JO6ABP/EpvOlK1NPOcIj3AS4khi6xXw6JlZCASq82HQV4SapfmVMMl2dg==
|
||||||
dependencies:
|
dependencies:
|
||||||
accepts "~1.3.4"
|
accepts "~1.3.4"
|
||||||
base64id "~2.0.0"
|
base64id "~2.0.0"
|
||||||
@@ -3751,10 +3763,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||||
|
|
||||||
stripe@^8.184.0:
|
stripe@^8.186.1:
|
||||||
version "8.184.0"
|
version "8.186.1"
|
||||||
resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.184.0.tgz#ea68470ca6045bb47516c4fea3b775fd6ce15a36"
|
resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.186.1.tgz#fb717cfcb8c2e73c91e3873dc286f3e8442bfb65"
|
||||||
integrity sha512-ZUdvyX+sizTxXLEbUjgTShrulSWSkMIt7hIKdAkhnajYrHdzVtdmhBJl8sQbR9chMVox3Ig5ohilyeIrvcCE2g==
|
integrity sha512-BBByVyqKEBY2GNQDLmfwL1RtfsPmjForD+up7tu+P7KYxxvwEzF1gM2Iv4npfOQevGaBmR70sxIWRwn7utS5pg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" ">=8.1.0"
|
"@types/node" ">=8.1.0"
|
||||||
qs "^6.6.0"
|
qs "^6.6.0"
|
||||||
@@ -3918,10 +3930,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
|||||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||||
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
||||||
|
|
||||||
twilio@^3.70.0:
|
twilio@^3.71.1:
|
||||||
version "3.70.0"
|
version "3.71.1"
|
||||||
resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.70.0.tgz#9e6a96f0c46e8256d74bce918baeb7e678c4c1aa"
|
resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.71.1.tgz#15bbb4b51c75d91cc07a8149378c4af330e543cc"
|
||||||
integrity sha512-GhohvQfP3aHEwiCb6MWqDJ/KeSyFmFwCQtoSuHEwevE7GCxCq6spK36HlCNg3UyTTZNvfdIhN9Sf1wDWeDIbOg==
|
integrity sha512-P/KFvm33UW15EnpHJKgdTxUa1u6MlR/u+sCVnL4ie2TDRv6t7kX+ieIGQMpH7bP/z7FXkTjEt0lz4M+XJ/XWOg==
|
||||||
dependencies:
|
dependencies:
|
||||||
axios "^0.21.4"
|
axios "^0.21.4"
|
||||||
dayjs "^1.8.29"
|
dayjs "^1.8.29"
|
||||||
|
|||||||
Reference in New Issue
Block a user