Merged in release/2021-11-12 (pull request #262)
IO-117 PBS WIP 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
|
||||||
@@ -19779,6 +19779,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>
|
||||||
@@ -29314,6 +29335,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>
|
||||||
@@ -29466,6 +29508,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>
|
||||||
|
|||||||
@@ -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],
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ function Header({
|
|||||||
setReportCenterContext,
|
setReportCenterContext,
|
||||||
recentItems,
|
recentItems,
|
||||||
}) {
|
}) {
|
||||||
console.log("🚀 ~ file: header.component.jsx ~ line 85 ~ bodyshop", bodyshop);
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -131,14 +131,14 @@ export function ProductionBoardKanbanComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const totalHrs = data
|
const totalHrs = data
|
||||||
.reduce(
|
.reduce(
|
||||||
(acc, val) =>
|
(acc, val) =>
|
||||||
acc +
|
acc +
|
||||||
(val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) +
|
(val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) +
|
||||||
(val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
|
(val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
.toFixed(1);
|
.toFixed(1);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<IndefiniteLoading loading={isMoving} />
|
<IndefiniteLoading loading={isMoving} />
|
||||||
@@ -167,7 +167,7 @@ export function ProductionBoardKanbanComponent({
|
|||||||
<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">
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1207,6 +1207,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",
|
||||||
@@ -1727,7 +1728,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",
|
||||||
@@ -1737,6 +1739,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...",
|
||||||
|
|||||||
@@ -1207,6 +1207,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",
|
||||||
@@ -1727,7 +1728,8 @@
|
|||||||
"new": ""
|
"new": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalidphone": ""
|
"invalidphone": "",
|
||||||
|
"noattachedjobs": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"archive": "",
|
"archive": "",
|
||||||
@@ -1737,6 +1739,7 @@
|
|||||||
"nojobs": "",
|
"nojobs": "",
|
||||||
"phonenumber": "",
|
"phonenumber": "",
|
||||||
"presets": "",
|
"presets": "",
|
||||||
|
"recentonly": "",
|
||||||
"selectmedia": "",
|
"selectmedia": "",
|
||||||
"sentby": "",
|
"sentby": "",
|
||||||
"typeamessage": "Enviar un mensaje...",
|
"typeamessage": "Enviar un mensaje...",
|
||||||
|
|||||||
@@ -1207,6 +1207,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",
|
||||||
@@ -1727,7 +1728,8 @@
|
|||||||
"new": ""
|
"new": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"invalidphone": ""
|
"invalidphone": "",
|
||||||
|
"noattachedjobs": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"archive": "",
|
"archive": "",
|
||||||
@@ -1737,6 +1739,7 @@
|
|||||||
"nojobs": "",
|
"nojobs": "",
|
||||||
"phonenumber": "",
|
"phonenumber": "",
|
||||||
"presets": "",
|
"presets": "",
|
||||||
|
"recentonly": "",
|
||||||
"selectmedia": "",
|
"selectmedia": "",
|
||||||
"sentby": "",
|
"sentby": "",
|
||||||
"typeamessage": "Envoyer un message...",
|
"typeamessage": "Envoyer un message...",
|
||||||
|
|||||||
@@ -2592,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
|
||||||
@@ -2843,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
|
||||||
@@ -3104,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"."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;
|
||||||
@@ -30,19 +30,58 @@ exports.default = async function (socket, { txEnvelope, jobid }) {
|
|||||||
const JobData = await QueryJobData(socket, jobid);
|
const JobData = await QueryJobData(socket, jobid);
|
||||||
socket.JobData = JobData;
|
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) {
|
||||||
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"ERROR",
|
||||||
|
`Error encountered in PbsJobExport. ${error}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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.
|
//Upsert the contact information as per Wafaa's Email.
|
||||||
CdkBase.createLogEvent(
|
CdkBase.createLogEvent(
|
||||||
socket,
|
socket,
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
`Upserting contact information to DMS for ${socket.JobData.ownr_fn} ${socket.JobData.ownr_ln} ${socket.JobData.ownr_co_nm}`
|
`Upserting contact information to DMS for ${socket.JobData.ownr_fn} ${socket.JobData.ownr_ln} ${socket.JobData.ownr_co_nm}`
|
||||||
);
|
);
|
||||||
const ownerRef = await UpsertContactData(socket);
|
const ownerRef = await UpsertContactData(socket, selectedCustomerId);
|
||||||
|
|
||||||
CdkBase.createLogEvent(
|
CdkBase.createLogEvent(
|
||||||
socket,
|
socket,
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
`Upserting vehicle information to DMS for ${socket.JobData.v_vin}`
|
`Upserting vehicle information to DMS for ${socket.JobData.v_vin}`
|
||||||
);
|
);
|
||||||
// await UpsertVehicleData(socket, ownerRef.ReferenceId);
|
await UpsertVehicleData(socket, ownerRef.ReferenceId);
|
||||||
CdkBase.createLogEvent(socket, "DEBUG", `Inserting account data.`);
|
CdkBase.createLogEvent(socket, "DEBUG", `Inserting account data.`);
|
||||||
await InsertAccountPostingData(socket);
|
await InsertAccountPostingData(socket);
|
||||||
CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported.`);
|
CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported.`);
|
||||||
@@ -53,24 +92,29 @@ exports.default = async function (socket, { txEnvelope, jobid }) {
|
|||||||
CdkBase.createLogEvent(
|
CdkBase.createLogEvent(
|
||||||
socket,
|
socket,
|
||||||
"ERROR",
|
"ERROR",
|
||||||
`Error encountered in PbsJobExport. ${error}`
|
`Error encountered in CdkSelectedCustomer. ${error}`
|
||||||
);
|
);
|
||||||
|
await InsertFailedExportLog(socket, error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function CheckForErrors(socket, response) {
|
async function CheckForErrors(socket, response) {
|
||||||
if (response.WasSuccessful) {
|
if (response.WasSuccessful === undefined || response.WasSuccessful === true) {
|
||||||
return;
|
CdkBase.createLogEvent(
|
||||||
|
socket,
|
||||||
|
"DEBUG",
|
||||||
|
`Succesful response from DMS. ${response.Message || ""}`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
CdkBase.createLogEvent(
|
CdkBase.createLogEvent(
|
||||||
socket,
|
socket,
|
||||||
"ERROR",
|
"ERROR",
|
||||||
`Error received from DMS:. ${response.Message}`
|
`Error received from DMS: ${response.Message}`
|
||||||
);
|
);
|
||||||
CdkBase.createLogEvent(
|
CdkBase.createLogEvent(
|
||||||
socket,
|
socket,
|
||||||
"TRACE",
|
"TRACE",
|
||||||
`Error received from DMS:. ${JSON.stringify(response)}`
|
`Error received from DMS: ${JSON.stringify(response)}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,14 +133,127 @@ async function QueryJobData(socket, jobid) {
|
|||||||
return result.jobs_by_pk;
|
return result.jobs_by_pk;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function UpsertContactData(socket) {
|
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 {
|
try {
|
||||||
const { data: ContactChangeResponse } = await axios.post(
|
const { data: ContactChangeResponse } = await axios.post(
|
||||||
PBS_ENDPOINTS.ContactChange,
|
PBS_ENDPOINTS.ContactChange,
|
||||||
{
|
{
|
||||||
ContactInfo: {
|
ContactInfo: {
|
||||||
// Id: socket.JobData.owner.id,
|
// Id: socket.JobData.owner.id,
|
||||||
ContactId: socket.JobData.owner.id,
|
...(selectedCustomerId ? { ContactId: selectedCustomerId } : {}),
|
||||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||||
Code: socket.JobData.owner.accountingid,
|
Code: socket.JobData.owner.accountingid,
|
||||||
...(socket.JobData.ownr_co_nm
|
...(socket.JobData.ownr_co_nm
|
||||||
@@ -393,20 +550,6 @@ async function InsertAccountPostingData(socket) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(
|
|
||||||
JSON.stringify({
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
const { data: AccountPostingChange } = await axios.post(
|
const { data: AccountPostingChange } = await axios.post(
|
||||||
PBS_ENDPOINTS.AccountingPostingChange,
|
PBS_ENDPOINTS.AccountingPostingChange,
|
||||||
{
|
{
|
||||||
@@ -463,3 +606,20 @@ async function MarkJobExported(socket, jobid) {
|
|||||||
|
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -554,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").default;
|
const {default: PbsExportJob, PbsSelectedCustomer} = require("../accounting/pbs/pbs-job-export");
|
||||||
|
|
||||||
io.use(function (socket, next) {
|
io.use(function (socket, next) {
|
||||||
try {
|
try {
|
||||||
@@ -113,6 +113,15 @@ io.on("connection", (socket) => {
|
|||||||
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", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user