Merge branch 'feature/cdk-cert' into feature/qbo

This commit is contained in:
Patrick Fic
2021-08-25 12:08:06 -07:00
35 changed files with 2402 additions and 1443 deletions

View File

@@ -7550,6 +7550,32 @@
<folder_node>
<name>dms</name>
<children>
<folder_node>
<name>cdk</name>
<children>
<concept_node>
<name>payers</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<concept_node>
<name>cdk_dealerid</name>
<definition_loaded>false</definition_loaded>

View File

@@ -1,17 +1,21 @@
import { Button, Table } from "antd";
import React, { useState } from "react";
import { Button, Table, Typography } from "antd";
import React, { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import Dinero from "dinero.js";
import { SyncOutlined } from "@ant-design/icons";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
@@ -20,6 +24,15 @@ export default connect(
export function DmsAllocationsSummary({ socket, bodyshop, jobId }) {
const { t } = useTranslation();
const [allocationsSummary, setAllocationsSummary] = useState([]);
useEffect(() => {
if (socket.connected) {
socket.emit("cdk-calculate-allocations", jobId, (ack) =>
setAllocationsSummary(ack)
);
}
}, [socket, socket.connected, jobId]);
const columns = [
{
title: t("jobs.fields.dms.center"),
@@ -71,13 +84,45 @@ export function DmsAllocationsSummary({ socket, bodyshop, jobId }) {
);
}}
>
Get
<SyncOutlined />
</Button>
)}
pagination={{ position: "top", defaultPageSize: 50 }}
columns={columns}
rowKey="center"
dataSource={allocationsSummary}
summary={() => {
const totals = allocationsSummary.reduce(
(acc, val) => {
return {
totalSale: acc.totalSale.add(Dinero(val.sale)),
totalCost: acc.totalCost.add(Dinero(val.cost)),
};
},
{
totalSale: Dinero(),
totalCost: Dinero(),
}
);
return (
<Table.Summary.Row>
<Table.Summary.Cell>
<Typography.Title level={4}>
{t("general.labels.totals")}
</Typography.Title>
</Table.Summary.Cell>
<Table.Summary.Cell>
{totals.totalSale.toFormat()}
</Table.Summary.Cell>
<Table.Summary.Cell>
{totals.totalCost.toFormat()}
</Table.Summary.Cell>
<Table.Summary.Cell></Table.Summary.Cell>
<Table.Summary.Cell></Table.Summary.Cell>
</Table.Summary.Row>
);
}}
/>
);
}

View File

@@ -4,6 +4,9 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { useTranslation } from "react-i18next";
import { useLazyQuery } from "@apollo/client";
import { SEARCH_DMS_VEHICLES } from "../../graphql/dms.queries";
import AlertComponent from "../alert/alert.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -12,83 +15,75 @@ const mapStateToProps = createStructuredSelector({
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(DmsCdkMakes);
export default connect(mapStateToProps, mapDispatchToProps)(DmsCdkVehicles);
export function DmsCdkMakes({ bodyshop, form, socket }) {
const [makesList, setMakesList] = useState([]);
const [searchText, setSearchText] = useState("");
const [loading, setLoading] = useState(false);
export function DmsCdkVehicles({ bodyshop, form, socket, job }) {
const [visible, setVisible] = useState(false);
const [selectedModel, setSelectedModel] = useState(null);
const { t } = useTranslation();
const [callSearch, { loading, error, data }] =
useLazyQuery(SEARCH_DMS_VEHICLES);
const columns = [
{
title: t("jobs.fields.dms.makeFullName"),
dataIndex: "makeFullName",
key: "makeFullName",
title: t("jobs.fields.dms.make"),
dataIndex: "make",
key: "make",
},
{
title: t("jobs.fields.dms.modelFullName"),
dataIndex: "modelFullName",
key: "modelFullName",
title: t("jobs.fields.dms.model"),
dataIndex: "model",
key: "model",
},
{
title: t("jobs.fields.dms.makeCode"),
dataIndex: "makeCode",
key: "makeCode",
title: t("jobs.fields.dms.makecode"),
dataIndex: "makecode",
key: "makecode",
},
{
title: t("jobs.fields.dms.modelCode"),
dataIndex: "modelCode",
key: "modelCode",
title: t("jobs.fields.dms.modelcode"),
dataIndex: "modelcode",
key: "modelcode",
},
];
const filteredMakes =
searchText !== "" && searchText
? makesList.filter(
(make) =>
searchText
.split(" ")
.some((v) =>
make.makeFullName.toLowerCase().includes(v.toLowerCase())
) ||
searchText
.split(" ")
.some((v) =>
make.modelFullName.toLowerCase().includes(v.toLowerCase())
)
)
: makesList;
console.log(
"🚀 ~ file: dms-cdk-makes.component.jsx ~ line 95 ~ selectedModel",
selectedModel
);
return (
<div>
<Modal width={"90%"} visible={visible} onCancel={() => setVisible(false)}>
<Modal
width={"90%"}
visible={visible}
onCancel={() => setVisible(false)}
onOk={() => {
form.setFieldsValue({
dms_make: selectedModel.makecode,
dms_model: selectedModel.modelcode,
});
setVisible(false);
}}
>
{error && <AlertComponent error={error.message} />}
<Table
title={() => (
<Input.Search
onSearch={(val) => setSearchText(val)}
onSearch={(val) => callSearch({ variables: { search: val } })}
placeholder={t("general.labels.search")}
/>
)}
columns={columns}
loading={loading}
id="id"
dataSource={filteredMakes}
rowKey="id"
dataSource={data ? data.search_dms_vehicles : []}
onRow={(record) => {
return {
onClick: setSelectedModel(record),
onClick: () => setSelectedModel(record),
};
}}
rowSelection={{
onSelect: (record, selected, ...props) => {
console.log(
"🚀 ~ file: dms-cdk-makes.component.jsx ~ line 85 ~ record, selected, ...props",
record,
selected,
...props
);
onSelect: (record) => {
setSelectedModel(record);
},
@@ -100,15 +95,14 @@ export function DmsCdkMakes({ bodyshop, form, socket }) {
<Button
onClick={() => {
setVisible(true);
setLoading(true);
socket.emit("cdk-get-makes", bodyshop.cdk_dealerid, (makes) => {
console.log("Called back", makes);
setMakesList(makes);
setLoading(false);
callSearch({
variables: {
search: job && job.v_model_desc && job.v_model_desc.substr(0, 3),
},
});
}}
>
Get Makes
{t("jobs.actions.dms.getmakes")}
</Button>
</div>
);

View File

@@ -0,0 +1,32 @@
import { Button } from "antd";
import axios from "axios";
import React, { useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(DmsCdkMakesRefetch);
export function DmsCdkMakesRefetch({ bodyshop, form, socket }) {
const [loading, setLoading] = useState(false);
const handleRefetch = async () => {
setLoading(true);
const response = await axios.post("/cdk/getvehicles", {
cdk_dealerid: bodyshop.cdk_dealerid,
bodyshopid: bodyshop.id,
});
console.log(response);
setLoading(false);
};
return (
<Button loading={loading} onClick={handleRefetch}>
Refetch Models
</Button>
);
}

View File

@@ -1,10 +1,24 @@
import { Button, Table } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { socket } from "../../pages/dms/dms.container";
import PhoneFormatter from "../../utils/PhoneFormatter";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { alphaSort } from "../../utils/sorters";
export default function DmsCustomerSelector() {
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(DmsCustomerSelector);
export function DmsCustomerSelector({ bodyshop }) {
const { t } = useTranslation();
const [customerList, setcustomerList] = useState([]);
const [visible, setVisible] = useState(false);
@@ -15,11 +29,24 @@ export default function DmsCustomerSelector() {
setcustomerList(customerList);
});
const onOk = () => {
const onUseSelected = () => {
setVisible(false);
socket.emit("cdk-selected-customer", selectedCustomer);
};
const onUseGeneric = () => {
setVisible(false);
socket.emit(
"cdk-selected-customer",
bodyshop.cdk_configuration.generic_customer_number
);
};
const onCreateNew = () => {
setVisible(false);
socket.emit("cdk-selected-customer", null);
};
const columns = [
{
title: t("dms.fields.name1"),
@@ -27,28 +54,13 @@ export default function DmsCustomerSelector() {
key: "name1",
sorter: (a, b) => alphaSort(a.name1?.fullName, b.name1?.fullName),
},
{
title: t("dms.fields.name2"),
dataIndex: ["name2", "fullName"],
key: "name2",
sorter: (a, b) => alphaSort(a.name2?.fullName, b.name2?.fullName),
},
{
title: t("dms.fields.phone"),
dataIndex: ["contactInfo", "mainTelephoneNumber", "value"],
key: "phone",
render: (record, value) => (
<PhoneFormatter>
{record.contactInfo?.mainTelephoneNumber?.value}
</PhoneFormatter>
),
},
{
title: t("dms.fields.address"),
//dataIndex: ["name2", "fullName"],
key: "address",
render: (record, value) =>
`${record.address?.addressLine[0]}, ${record.address?.city} ${record.address?.stateOrProvince} ${record.address?.postalCode}`,
`${record?.address?.addressLine[0]}, ${record.address?.city} ${record.address?.stateOrProvince} ${record.address?.postalCode}`,
},
];
@@ -57,7 +69,23 @@ export default function DmsCustomerSelector() {
<Table
title={() => (
<div>
<Button onClick={onOk}>Select</Button>
<Button onClick={onUseSelected} disabled={!selectedCustomer}>
{t("jobs.actions.dms.useselected")}
</Button>
<Button
onClick={onUseGeneric}
disabled={
!(
bodyshop.cdk_configuration &&
bodyshop.cdk_configuration.generic_customer_number
)
}
>
{t("jobs.actions.dms.usegeneric")}
</Button>
<Button onClick={onCreateNew}>
{t("jobs.actions.dms.createnewcustomer")}
</Button>
</div>
)}
pagination={{ position: "top" }}

View File

@@ -1,5 +1,13 @@
import { DeleteFilled } from "@ant-design/icons";
import { Button, Form, Input } from "antd";
import {
Button,
Form,
Input,
InputNumber,
Select,
Space,
Statistic,
} from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -8,7 +16,9 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import DmsCdkMakes from "../dms-cdk-makes/dms-cdk-makes.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import Dinero from "dinero.js";
import { determineDmsType } from "../../pages/dms/dms.container";
import DmsCdkMakesRefetch from "../dms-cdk-makes/dms-cdk-makes.refetch.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
@@ -17,11 +27,38 @@ const mapDispatchToProps = (dispatch) => ({
});
export default connect(mapStateToProps, mapDispatchToProps)(DmsPostForm);
export function DmsPostForm({ bodyshop, socket, jobId }) {
export function DmsPostForm({ bodyshop, socket, job }) {
const [form] = Form.useForm();
const { t } = useTranslation();
const handlePayerSelect = (value, index) => {
form.setFieldsValue({
payers: form.getFieldValue("payers").map((payer, mapIndex) => {
if (index !== mapIndex) return payer;
const cdkPayer =
bodyshop.cdk_configuration.payers &&
bodyshop.cdk_configuration.payers.find((i) => i.name === value);
if (!cdkPayer) return payer;
return {
...cdkPayer,
dms_acctnumber: cdkPayer.dms_acctnumber,
controlnumber: job && job[cdkPayer.control_type],
};
}),
});
};
const handleFinish = (values) => {
socket.emit(`${determineDmsType(bodyshop)}-export-job`, {
jobid: job.id,
txEnvelope: values,
});
};
return (
<Form form={form} layout="vertical">
<Form form={form} layout="vertical" onFinish={handleFinish}>
<LayoutFormRow>
<Form.Item
name="journal"
@@ -40,15 +77,41 @@ export function DmsPostForm({ bodyshop, socket, jobId }) {
<Input />
</Form.Item>
<Form.Item
name="dms_make"
label={t("jobs.fields.dms.dms_make")}
name="story"
label={t("jobs.fields.dms.story")}
rules={[
{
required: true,
},
]}
>
<Input />
<Input.TextArea />
</Form.Item>
<Form.Item
name="kmin"
label={t("jobs.fields.kmin")}
initialValue={job && job.kmin}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<InputNumber disabled />
</Form.Item>
<Form.Item
name="kmout"
label={t("jobs.fields.kmout")}
initialValue={job && job.kmout}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<InputNumber disabled />
</Form.Item>
<Form.Item
name="dms_make"
@@ -59,9 +122,21 @@ export function DmsPostForm({ bodyshop, socket, jobId }) {
},
]}
>
<Input />
<Input disabled />
</Form.Item>
<DmsCdkMakes form={form} socket={socket} />
<Form.Item
name="dms_model"
label={t("jobs.fields.dms.dms_model")}
rules={[
{
required: true,
},
]}
>
<Input disabled />
</Form.Item>
<DmsCdkMakes form={form} socket={socket} job={job} />
<DmsCdkMakesRefetch />
</LayoutFormRow>
<Form.List name={["payers"]}>
@@ -81,20 +156,30 @@ export function DmsPostForm({ bodyshop, socket, jobId }) {
},
]}
>
<Input />
<Select
onSelect={(value) => handlePayerSelect(value, index)}
>
{bodyshop.cdk_configuration &&
bodyshop.cdk_configuration.payers &&
bodyshop.cdk_configuration.payers.map((payer) => (
<Select.Option key={payer.name}>
{payer.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("jobs.fields.dms.payer.account")}
key={`${index}account`}
name={[field.name, "account"]}
label={t("jobs.fields.dms.payer.dms_acctnumber")}
key={`${index}dms_acctnumber`}
name={[field.name, "dms_acctnumber"]}
rules={[
{
required: true,
},
]}
>
<Input />
<Input disabled />
</Form.Item>
<Form.Item
@@ -107,8 +192,9 @@ export function DmsPostForm({ bodyshop, socket, jobId }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.dms.payer.controlnumber")}
key={`${index}controlnumber`}
@@ -122,6 +208,27 @@ export function DmsPostForm({ bodyshop, socket, jobId }) {
<Input />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
const payers = form.getFieldValue("payers");
const row = payers && payers[index];
const cdkPayer =
bodyshop.cdk_configuration.payers &&
bodyshop.cdk_configuration.payers.find(
(i) => i && row && i.name === row.name
);
return (
<div>
{cdkPayer &&
t(`jobs.fields.${cdkPayer.control_type}`)}
</div>
);
}}
</Form.Item>
<DeleteFilled
onClick={() => {
remove(field.name);
@@ -133,18 +240,69 @@ export function DmsPostForm({ bodyshop, socket, jobId }) {
<Form.Item>
<Button
type="dashed"
disabled={!(fields.length < 3)}
onClick={() => {
add();
if (fields.length < 3) add();
}}
style={{ width: "100%" }}
>
{t("general.actions.add")}
{t("dms.actions.addpayer")}
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
<Form.Item shouldUpdate>
{() => {
//Perform Calculation to determine discrepancy.
let totalAllocated = Dinero();
const payers = form.getFieldValue("payers");
payers &&
payers.forEach((payer) => {
totalAllocated = totalAllocated.add(
Dinero({ amount: Math.round((payer?.amount || 0) * 100) })
);
});
const discrep = Dinero(job.job_totals.totals.total_repairs).subtract(
totalAllocated
);
return (
<Space>
<Statistic
title={t("jobs.labels.dms.totalallocated")}
value={totalAllocated.toFormat()}
/>
<Statistic
title={t("jobs.fields.subtotal")}
value={Dinero(job.job_totals.totals.total_repairs).toFormat()}
/>
<Statistic
title={t("jobs.labels.dms.notallocated")}
valueStyle={{
color: discrep.getAmount() === 0 ? "green" : "red",
}}
value={discrep.toFormat()}
/>
<Button //disabled={discrep.getAmount() !== 0} //TODO: REMOVE THIS COMMENT.
htmlType="submit"
>
{t("jobs.actions.dms.post")}
</Button>
<Button
onClick={() => {
socket.emit(`${determineDmsType(bodyshop)}-export-job`, {
jobid: job.id,
});
}}
>
Bypass
</Button>
</Space>
);
}}
</Form.Item>
</Form>
);
}

View File

@@ -91,6 +91,93 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.dms.generic_customer_number")}
name={["cdk_configuration", "generic_customer_number"]}
>
<Input />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("bodyshop.labels.dms.cdk.payers")}>
<Form.List name={["cdk_configuration", "payers"]}>
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key}>
<LayoutFormRow noDivider>
<Form.Item
label={t("bodyshop.fields.dms.payer.name")}
key={`${index}name`}
name={[field.name, "name"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t(
"bodyshop.fields.dms.payer.dms_acctnumber"
)}
key={`${index}dms_acctnumber`}
name={[field.name, "dms_acctnumber"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.dms.payer.control_type")}
key={`${index}control_type`}
name={[field.name, "control_type"]}
rules={[
{
required: true,
},
]}
>
<Select>
<Select.Option value="ro_number">
{t("jobs.fields.ro_number")}
</Select.Option>
<Select.Option value="clm_no">
{t("jobs.fields.clm_no")}
</Select.Option>
<Select.Option value="po_number">
{t("jobs.fields.ponumber")}
</Select.Option>
</Select>
</Form.Item>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
</LayoutFormRow>
</Form.Item>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "100%" }}
>
{t("general.actions.add")}
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</LayoutFormRow>
</>
)}
@@ -1335,8 +1422,6 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
</>
)}
{!bodyshop.cdk_dealerid && (
<>
<LayoutFormRow header={t("bodyshop.labels.defaultcostsmapping")}>
<Form.Item
label={t("bodyshop.fields.responsibilitycenters.ats")}
@@ -1706,12 +1791,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"costs",
"MAPA",
]}
name={["md_responsibility_centers", "defaults", "costs", "MAPA"]}
>
<Select>
{costOptions.map((item, idx) => (
@@ -1729,12 +1809,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"costs",
"MASH",
]}
name={["md_responsibility_centers", "defaults", "costs", "MASH"]}
>
<Select>
{costOptions.map((item, idx) => (
@@ -1754,12 +1829,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"ATS",
]}
name={["md_responsibility_centers", "defaults", "profits", "ATS"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1777,12 +1847,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAB",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAB"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1800,12 +1865,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAD",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAD"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1823,12 +1883,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAE",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAE"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1846,12 +1901,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAF",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAF"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1869,12 +1919,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAG",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAG"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1892,12 +1937,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAM",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAM"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1915,12 +1955,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAR",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAR"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1938,12 +1973,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAS",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAS"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1961,12 +1991,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"LAU",
]}
name={["md_responsibility_centers", "defaults", "profits", "LAU"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -1984,12 +2009,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAA",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAA"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2007,12 +2027,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAC",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAC"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2030,12 +2045,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAL",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAL"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2053,12 +2063,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAM",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAM"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2076,12 +2081,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAN",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAN"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2099,12 +2099,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAO",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAO"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2122,12 +2117,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAP",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAP"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2145,12 +2135,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAR",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAR"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2168,12 +2153,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"PAS",
]}
name={["md_responsibility_centers", "defaults", "profits", "PAS"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2191,12 +2171,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"TOW",
]}
name={["md_responsibility_centers", "defaults", "profits", "TOW"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2214,12 +2189,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"MAPA",
]}
name={["md_responsibility_centers", "defaults", "profits", "MAPA"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2237,12 +2207,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
//message: t("general.validation.required"),
},
]}
name={[
"md_responsibility_centers",
"defaults",
"profits",
"MASH",
]}
name={["md_responsibility_centers", "defaults", "profits", "MASH"]}
>
<Select>
{profitOptions.map((item, idx) => (
@@ -2253,8 +2218,6 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
</Select>
</Form.Item>
</LayoutFormRow>
</>
)}
</SelectorDiv>
<LayoutFormRow

View File

@@ -0,0 +1,13 @@
import { gql } from "@apollo/client";
export const SEARCH_DMS_VEHICLES = gql`
query SEARCH_DMS_VEHICLES($search: String) {
search_dms_vehicles(args: { search: $search }) {
id
make
makecode
model
modelcode
}
}
`;

View File

@@ -1726,6 +1726,8 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
actual_delivery
scheduled_in
actual_in
kmin
kmout
joblines(where: { removed: { _eq: false } }) {
id
removed
@@ -1878,98 +1880,16 @@ export const FIND_JOBS_BY_CLAIM = gql`
`;
export const QUERY_JOB_EXPORT_DMS = gql`
query QUERY_JOB_CLOSE_DETAILS($id: uuid!) {
query QUERY_JOB_EXPORT_DMS($id: uuid!) {
jobs_by_pk(id: $id) {
id
ro_number
invoice_allocation
ins_co_id
id
ded_amt
ded_status
depreciation_taxes
other_amount_payable
towing_payable
storage_payable
adjustment_bottom_line
federal_tax_rate
state_tax_rate
local_tax_rate
tax_tow_rt
tax_str_rt
tax_paint_mat_rt
tax_sub_rt
tax_lbr_rt
tax_levies_rt
parts_tax_rates
po_number
clm_no
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
status
date_exported
date_invoiced
voided
scheduled_completion
actual_completion
scheduled_delivery
actual_delivery
scheduled_in
actual_in
bills {
id
federal_tax_rate
local_tax_rate
state_tax_rate
is_credit_memo
billlines {
actual_cost
cost_center
id
quantity
}
}
joblines(where: { removed: { _eq: false } }) {
id
removed
tax_part
line_desc
prt_dsmk_p
prt_dsmk_m
part_type
oem_partno
db_price
act_price
part_qty
mod_lbr_ty
db_hrs
mod_lb_hrs
lbr_op
lbr_amt
op_code_desc
profitcenter_labor
profitcenter_part
prt_dsmk_p
}
kmin
kmout
v_model_desc
}
}
`;

View File

@@ -1,4 +1,4 @@
//import { useQuery } from "@apollo/client";
import { useQuery } from "@apollo/client";
import { Button, Col, Result, Row, Select, Space } from "antd";
import queryString from "query-string";
import React, { useEffect, useState } from "react";
@@ -7,14 +7,14 @@ import { connect } from "react-redux";
import { useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import SocketIO from "socket.io-client";
//import AlertComponent from "../../components/alert/alert.component";
import AlertComponent from "../../components/alert/alert.component";
import DmsAllocationsSummary from "../../components/dms-allocations-summary/dms-allocations-summary.component";
import DmsCustomerSelector from "../../components/dms-customer-selector/dms-customer-selector.component";
import DmsLogEvents from "../../components/dms-log-events/dms-log-events.component";
import DmsPostForm from "../../components/dms-post-form/dms-post-form.component";
//import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import { auth } from "../../firebase/firebase.utils";
//import { QUERY_JOB_EXPORT_DMS } from "../../graphql/jobs.queries";
import { QUERY_JOB_EXPORT_DMS } from "../../graphql/jobs.queries";
import {
setBreadcrumbs,
setSelectedHeader,
@@ -52,10 +52,10 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
const search = queryString.parse(useLocation().search);
const { jobId } = search;
// const { loading, error } = useQuery(QUERY_JOB_EXPORT_DMS, {
// variables: { id: jobId },
// skip: true, //!jobId,
// });
const { loading, error, data } = useQuery(QUERY_JOB_EXPORT_DMS, {
variables: { id: jobId },
skip: !jobId,
});
useEffect(() => {
document.title = t("titles.dms");
@@ -73,7 +73,6 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
console.log("Connected again.");
});
socket.on("reconnect", () => {
console.log("Connected again.");
setLogs((logs) => {
return [
...logs,
@@ -104,24 +103,23 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
if (!jobId || !bodyshop.cdk_dealerid) return <Result status="404" />;
const dmsType = determineDmsType(bodyshop);
// if (loading) return <LoadingSpinner />;
// if (error) return <AlertComponent message={error.message} type="error" />;
if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />;
return (
<div>
<Row gutter={32}>
<Col span={18}>
{data && data.jobs_by_pk.ro_number}
<DmsAllocationsSummary socket={socket} jobId={jobId} />
<DmsPostForm
socket={socket}
jobId={jobId}
job={data && data.jobs_by_pk}
/>
</Col>
<Col span={6}>
<Space>
<Button
onClick={() => {
socket.emit(
`${dmsType}-export-job`,
"752a4f5f-22ab-414b-b182-98d4e62227ef"
);
}}
>
Export
</Button>
<Select
placeholder="Log Level"
value={logLevel}
@@ -138,12 +136,6 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
</Select>
<Button onClick={() => setLogs([])}>Clear Logs</Button>
</Space>
<Row gutter={32}>
<Col span={18}>
<DmsAllocationsSummary socket={socket} jobId={jobId} />
<DmsPostForm socket={socket} jobId={jobId} />
</Col>
<Col span={6}>
<div style={{ maxHeight: "500px", overflowY: "auto" }}>
<DmsLogEvents socket={socket} logs={logs} />
</div>
@@ -155,7 +147,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
);
}
const determineDmsType = (bodyshop) => {
export const determineDmsType = (bodyshop) => {
if (bodyshop.cdk_dealerid) return "cdk";
else {
return "pbs";

View File

@@ -8,6 +8,7 @@ import {
Alert,
Divider,
PageHeader,
InputNumber,
} from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
@@ -56,6 +57,8 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
actual_in: values.actual_in,
actual_completion: values.actual_completion,
actual_delivery: values.actual_delivery,
kmin: values.kmin,
kmout: values.kmout,
},
},
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
@@ -112,6 +115,8 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
actual_delivery: job.actual_delivery
? moment(job.actual_delivery)
: job.scheduled_delivery && moment(job.scheduled_delivery),
kmin: job.kmin,
kmout: job.kmout,
}}
scrollToFirstError
>
@@ -203,6 +208,45 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
>
<DateTimePicker disabled={jobRO} />
</Form.Item>
{bodyshop.cdk_dealerid && (
<Form.Item
label={t("jobs.fields.kmin")}
name="kmin"
rules={[
{
required: true,
},
]}
>
<InputNumber disabled={jobRO} />
</Form.Item>
)}
{bodyshop.cdk_dealerid && (
<Form.Item
label={t("jobs.fields.kmout")}
name="kmout"
dependencies={["kmin"]}
hasFeedback
rules={[
{
required: true,
},
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue("kmin") <= value) {
return Promise.resolve();
}
return Promise.reject(
new Error(t("jobs.labels.dms.kmoutnotgreaterthankmin"))
);
},
}),
]}
>
<InputNumber disabled={jobRO} />
</Form.Item>
)}
</LayoutFormRow>
<Divider />
<JobsCloseLines job={job} />

View File

@@ -474,6 +474,9 @@
"defaultprofitsmapping": "Default Profits Mapping",
"deliverchecklist": "Delivery Checklist",
"dms": {
"cdk": {
"payers": "CDK Payers"
},
"cdk_dealerid": "CDK Dealer ID",
"title": "DMS"
},

View File

@@ -474,6 +474,9 @@
"defaultprofitsmapping": "",
"deliverchecklist": "",
"dms": {
"cdk": {
"payers": ""
},
"cdk_dealerid": "",
"title": ""
},

View File

@@ -474,6 +474,9 @@
"defaultprofitsmapping": "",
"deliverchecklist": "",
"dms": {
"cdk": {
"payers": ""
},
"cdk_dealerid": "",
"title": ""
},

View File

@@ -0,0 +1,5 @@
- args:
cascade: false
read_only: false
sql: DROP TABLE "public"."dms_vehicles";
type: run_sql

View File

@@ -0,0 +1,18 @@
- args:
cascade: false
read_only: false
sql: CREATE EXTENSION IF NOT EXISTS pgcrypto;
type: run_sql
- args:
cascade: false
read_only: false
sql: CREATE TABLE "public"."dms_vehicles"("id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NOT NULL DEFAULT now(), "makecode" text NOT NULL, "modelcode"
text NOT NULL, "make" text NOT NULL, "model" text NOT NULL, "bodyshopid" uuid
NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("bodyshopid") REFERENCES "public"."bodyshops"("id")
ON UPDATE cascade ON DELETE cascade);
type: run_sql
- args:
name: dms_vehicles
schema: public
type: add_existing_table_or_view

View File

@@ -0,0 +1,12 @@
- args:
relationship: dms_vehicles
table:
name: bodyshops
schema: public
type: drop_relationship
- args:
relationship: bodyshop
table:
name: dms_vehicles
schema: public
type: drop_relationship

View File

@@ -0,0 +1,20 @@
- args:
name: dms_vehicles
table:
name: bodyshops
schema: public
using:
foreign_key_constraint_on:
column: bodyshopid
table:
name: dms_vehicles
schema: public
type: create_array_relationship
- args:
name: bodyshop
table:
name: dms_vehicles
schema: public
using:
foreign_key_constraint_on: bodyshopid
type: create_object_relationship

View File

@@ -0,0 +1,6 @@
- args:
role: user
table:
name: dms_vehicles
schema: public
type: drop_select_permission

View File

@@ -0,0 +1,28 @@
- args:
permission:
allow_aggregations: false
backend_only: false
columns:
- id
- created_at
- makecode
- modelcode
- make
- model
- bodyshopid
computed_fields: []
filter:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
limit: null
role: user
table:
name: dms_vehicles
schema: public
type: create_select_permission

View File

@@ -0,0 +1,6 @@
- args:
role: user
table:
name: dms_vehicles
schema: public
type: drop_insert_permission

View File

@@ -0,0 +1,27 @@
- args:
permission:
allow_upsert: true
backend_only: false
check:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- id
- created_at
- makecode
- modelcode
- make
- model
- bodyshopid
set: {}
role: user
table:
name: dms_vehicles
schema: public
type: create_insert_permission

View File

@@ -0,0 +1,6 @@
- args:
role: user
table:
name: dms_vehicles
schema: public
type: drop_update_permission

View File

@@ -0,0 +1,26 @@
- args:
permission:
backend_only: false
columns:
- make
- makecode
- model
- modelcode
- created_at
- bodyshopid
- id
filter:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
set: {}
role: user
table:
name: dms_vehicles
schema: public
type: create_update_permission

View File

@@ -0,0 +1,6 @@
- args:
role: user
table:
name: dms_vehicles
schema: public
type: drop_delete_permission

View File

@@ -0,0 +1,17 @@
- args:
permission:
backend_only: false
filter:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
role: user
table:
name: dms_vehicles
schema: public
type: create_delete_permission

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,13 @@
- args:
cascade: true
read_only: false
sql: CREATE OR REPLACE FUNCTION public.search_dms_vehicles(search text)RETURNS
SETOF dms_vehicles LANGUAGE plpgsql STABLE AS $FUNCTION$ BEGIN IF search=''
THEN RETURN query SELECT*FROM dms_vehicles;ELSE RETURN query SELECT*FROM dms_vehicles
WHERE make ILIKE'%'||search||'%' OR model ILIKE'%'||search||'%' ORDER BY make
ILIKE'%'||search||'%' OR NULL,model ILIKE'%'||search||'%' OR NULL;END IF;END$FUNCTION$;
type: run_sql
- args:
name: search_dms_vehicles
schema: public
type: track_function

View File

@@ -721,6 +721,13 @@ tables:
table:
schema: public
name: csiquestions
- name: dms_vehicles
using:
foreign_key_constraint_on:
column: bodyshopid
table:
schema: public
name: dms_vehicles
- name: documents
using:
foreign_key_constraint_on:
@@ -1527,6 +1534,87 @@ tables:
- active:
_eq: true
check: null
- table:
schema: public
name: dms_vehicles
object_relationships:
- name: bodyshop
using:
foreign_key_constraint_on: bodyshopid
insert_permissions:
- role: user
permission:
check:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- id
- created_at
- makecode
- modelcode
- make
- model
- bodyshopid
backend_only: false
select_permissions:
- role: user
permission:
columns:
- id
- created_at
- makecode
- modelcode
- make
- model
- bodyshopid
filter:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
update_permissions:
- role: user
permission:
columns:
- make
- makecode
- model
- modelcode
- created_at
- bodyshopid
- id
filter:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
check: null
delete_permissions:
- role: user
permission:
filter:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
- table:
schema: public
name: documents
@@ -4554,6 +4642,9 @@ functions:
- function:
schema: public
name: search_cccontracts
- function:
schema: public
name: search_dms_vehicles
- function:
schema: public
name: search_exportlog

View File

@@ -21,6 +21,23 @@ const app = express();
const port = process.env.PORT || 5000;
//const port = 5000;
const http = require("http");
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server, {
path: "/ws",
cors: {
origin: [
"https://test.imex.online",
"http://localhost:3000",
"https://imex.online",
],
methods: ["GET", "POST"],
},
});
exports.io = io;
require("./server/web-sockets/web-socket");
//app.use(fb.validateFirebaseIdToken);
app.use(compression());
app.use(bodyParser.json({ limit: "50mb" }));
@@ -136,25 +153,13 @@ app.post("/data/ah", data.autohouse);
var ioevent = require("./server/ioevent/ioevent");
app.post("/ioevent", ioevent.default);
var cdkGetMake = require("./server/cdk/cdk-get-makes");
app.post("/cdk/getvehicles", fb.validateFirebaseIdToken, cdkGetMake.default);
app.get("/", async function (req, res) {
res.status(200).send("Access Forbidden.");
});
const http = require("http");
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server, {
path: "/ws",
cors: {
origin: [
"https://test.imex.online",
"http://localhost:3000",
"https://imex.online",
],
methods: ["GET", "POST"],
},
});
server.listen(port, (error) => {
if (error) throw error;
logger.log(
@@ -163,5 +168,3 @@ server.listen(port, (error) => {
"api"
);
});
exports.io = io;
require("./server/web-sockets/web-socket");

View File

@@ -15,32 +15,101 @@ const Dinero = require("dinero.js");
const _ = require("lodash");
const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl");
const { performance } = require("perf_hooks");
const apiGqlClient = require("../graphql-client/graphql-client").client;
exports.default = async function (socket, cdk_dealerid) {
// exports.default = async function (socket, cdk_dealerid) {
// try {
// CdkBase.createLogEvent(
// socket,
// "DEBUG",
// `Getting makes and models list from CDK.`
// );
// return await GetCdkMakes(socket, cdk_dealerid);
// } catch (error) {
// CdkBase.createLogEvent(
// socket,
// "ERROR",
// `Error encountered in CdkGetMakes. ${error}`
// );
// }
// };
exports.default = async function ReloadCdkMakes(req, res) {
const { bodyshopid, cdk_dealerid } = req.body;
try {
CdkBase.createLogEvent(
socket,
"DEBUG",
`Getting makes and models list from CDK.`
const BearerToken = req.headers.authorization;
//Query all CDK Models
const newList = await GetCdkMakes(req, cdk_dealerid);
console.log("🚀 ~ file: cdk-get-makes.js ~ line 40 ~ newList", newList);
//Clear out the existing records
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
headers: {
Authorization: BearerToken,
},
});
const deleteResult = await client
.setHeaders({ Authorization: BearerToken })
.request(queries.DELETE_ALL_DMS_VEHICLES, {});
console.log(
"🚀 ~ file: cdk-get-makes.js ~ line 53 ~ deleteResult",
deleteResult
);
//Insert the new ones.
const insertResult = await client
.setHeaders({ Authorization: BearerToken })
.request(queries.INSERT_DMS_VEHICLES, {
vehicles: newList.map((i) => {
return {
bodyshopid,
makecode: i.makeCode,
modelcode: i.modelCode,
make: i.makeFullName,
model: i.modelFullName,
};
}),
});
console.log(
"🚀 ~ file: cdk-get-makes.js ~ line 66 ~ insertResult",
insertResult
);
logger.log(
"cdk-replace-makes-models-success",
"DEBUG",
req.user.email,
null,
{
cdk_dealerid,
count: newList.length,
}
);
return await GetCdkMakes(socket, cdk_dealerid);
} catch (error) {
CdkBase.createLogEvent(
socket,
logger.log(
"cdk-replace-makes-models-error",
"ERROR",
`Error encountered in CdkGetMakes. ${error}`
req.user.email,
null,
{
cdk_dealerid,
error,
}
);
}
};
async function GetCdkMakes(socket, cdk_dealerid) {
CdkBase.createLogEvent(socket, "TRACE", `{1} Begin GetCDkMakes WSDL Call`);
async function GetCdkMakes(req, cdk_dealerid) {
logger.log("cdk-replace-makes-models", "DEBUG", req.user.email, null, {
cdk_dealerid,
});
try {
const soapClientVehicleInsert = await soap.createClientAsync(
CdkWsdl.VehicleInsert
);
const start = performance.now();
const soapResponseVehicleSearch =
await soapClientVehicleInsert.getMakeModelAsync(
@@ -51,28 +120,25 @@ async function GetCdkMakes(socket, cdk_dealerid) {
{}
);
CheckCdkResponseForError(socket, soapResponseVehicleSearch);
CheckCdkResponseForError(null, soapResponseVehicleSearch);
const [
result, //rawResponse, soapheader, rawRequest
] = soapResponseVehicleSearch;
const end = performance.now();
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientVehicleInsert.getMakeModelAsync Result Length ${
result.return.length
} and took ${end - start}ms`
return result.return;
} catch (error) {
logger.log(
"cdk-replace-makes-models-error",
"ERROR",
req.user.email,
null,
{
cdk_dealerid,
error,
}
);
return result.return.map((element, index) => {
return { id: index, ...element };
});
} catch (error) {
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in GetCdkMakes - ${JSON.stringify(error, null, 2)}`
);
throw new Error(error);
}
}

View File

@@ -10,153 +10,72 @@ const soap = require("soap");
const queries = require("../graphql-client/queries");
const CdkBase = require("../web-sockets/web-socket");
const CdkWsdl = require("./cdk-wsdl").default;
const logger = require("../utils/logger");
const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl");
const moment = require("moment");
exports.default = async function (socket, jobid) {
exports.default = async function (socket, { txEnvelope, jobid }) {
socket.logEvents = [];
socket.recordid = jobid;
socket.txEnvelope = txEnvelope;
try {
CdkBase.createLogEvent(
socket,
"DEBUG",
`Received Job export request for id ${jobid}`
);
//The following values will be stored on the socket to allow callbacks.
//let clVFV, clADPV, clADPC;
const JobData = await QueryJobData(socket, jobid);
socket.JobData = JobData;
const DealerId = JobData.bodyshop.cdk_dealerid;
CdkBase.createLogEvent(
socket,
"TRACE",
"DEBUG",
`Dealer ID detected: ${JSON.stringify(DealerId)}`
);
//{1} Begin Calculate DMS Vehicle Id
socket.clVFV = await CalculateDmsVid(socket, JobData);
if (socket.clVFV.newId === "Y") {
//{1.2} This is a new Vehicle ID
CdkBase.createLogEvent(
socket,
"DEBUG",
`{1.2} clVFV DMSVid does *not* exist.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`{1.2} clVFV: ${JSON.stringify(socket.clVFV, null, 2)}`
);
//Check if DMSCustId is Empty - which it should always be?
//{6.6} Should check to see if a customer exists so that we can marry it to the new vehicle.
CdkBase.createLogEvent(
socket,
"DEBUG",
`{6.6} Trying to find customer ID in DMS.`
`{1} Begin Calculate DMS Vehicle ID using VIN: ${JobData.v_vin}`
);
socket.DMSVid = await CalculateDmsVid(socket, JobData);
//Array
const strIDS = await FindCustomerIdFromDms(socket, JobData);
if (strIDS && strIDS.length > 0) {
if (socket.DMSVid.newId === "N") {
CdkBase.createLogEvent(
socket,
"DEBUG",
`{8.2} ${strIDS.length} Customer ID(s) found.`
`{2.1} Querying the Vehicle using the DMSVid: ${socket.DMSVid}`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`{8.2} strIDS: ${JSON.stringify(strIDS, null, 2)}`
);
if (strIDS.length > 1) {
//We have multiple IDs
//TODO: Do we need to let the person select it?
CdkBase.createLogEvent(
socket,
"WARNING",
`{F} Mutliple customer ids have been found (${strIDS.length})`
);
CdkBase.createLogEvent(
socket,
"DEBUG",
`Asking for user intervention to select customer.`
);
socket.emit("cdk-select-customer", strIDS);
socket.DMSVeh = await QueryDmsVehicleById(socket, JobData, socket.DMSVid);
const DMSVehCustomer =
socket.DMSVeh &&
socket.DMSVeh.owners.find((o) => o.id.assigningPartyId === "CURRENT");
return;
}
} else {
CdkBase.createLogEvent(
socket,
"DEBUG",
`{8.5} Customer ID(s) *not* found.`
`{2.2} Querying the Customer using the ID from DMSVeh: ${DMSVehCustomer.id.value}`
);
//Create a customer number, then use that to insert the customer record.
const newCustomerNumber = await GenerateCustomerNumberFromDms(
socket,
JobData
);
CdkBase.createLogEvent(
socket,
"DEBUG",
`{10.1} New Customer number generated. newCustomerNumber: ${newCustomerNumber}`
);
//Use the new customer number to insert the customer record.
socket.clADPC = await CreateCustomerInDms(
socket.DMSVehCustomer = await QueryDmsCustomerById(
socket,
JobData,
newCustomerNumber
DMSVehCustomer.id.value
);
}
CdkBase.createLogEvent(
socket,
"DEBUG",
`{11.1} New Customer inserted.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`{11.1} clADPC: ${JSON.stringify(socket.clADPC, null, 2)}`
);
}
} else {
CdkBase.createLogEvent(socket, "DEBUG", `{1.1} clVFV DMSVid does exist.`);
CdkBase.createLogEvent(
socket,
"TRACE",
`{1.1} clVFV: ${JSON.stringify(socket.clVFV, null, 2)}`
`{2.3} Querying the Customer using the name.`
);
//{2} Begin Find Vehicle in DMS
socket.clADPV = await FindVehicleInDms(socket, JobData, socket.clVFV); //TODO: Verify that this should always return a result. If an ID was found previously, it should be correct?
socket.DMSCustList = await QueryDmsCustomerByName(socket, JobData);
//{2.2} Check if the vehicle was found in the DMS.
if (socket.clADPV.AppErrorNo === "0") {
//Vehicle was found.
CdkBase.createLogEvent(
socket,
"DEBUG",
`{1.4} Vehicle was found in the DMS.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`{1.4} clADPV: ${JSON.stringify(socket.clADPV, null, 2)}`
);
} else {
//Vehicle was not found.
CdkBase.createLogEvent(
socket,
"DEBUG",
`{6.4} Vehicle does not exist in DMS. Will have to create one.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`{6.4} clVFV: ${JSON.stringify(socket.clVFV, null, 2)}`
);
}
}
socket.emit("cdk-select-customer", [
...(socket.DMSVehCustomer ? [socket.DMSVehCustomer] : []),
...socket.DMSCustList,
]);
} catch (error) {
CdkBase.createLogEvent(
socket,
@@ -174,6 +93,79 @@ exports.default = async function (socket, jobid) {
}
};
async function CdkSelectedCustomer(socket, selectedCustomerId) {
try {
if (selectedCustomerId) {
CdkBase.createLogEvent(
socket,
"DEBUG",
`{3.1} Querying the Customer using Customer ID: ${selectedCustomerId}`
);
socket.DMSCust = await QueryDmsCustomerById(socket, selectedCustomerId);
} else {
CdkBase.createLogEvent(
socket,
"DEBUG",
`{3.2} Generating a new customer ID.`
);
const newCustomerId = await GenerateDmsCustomerNumber(socket);
CdkBase.createLogEvent(
socket,
"DEBUG",
`{3.3} Inserting new customer with ID: ${newCustomerId}`
);
socket.DMSCust = await InsertDmsCustomer(socket, newCustomerId);
}
if (socket.DMSVid.newId === "Y") {
CdkBase.createLogEvent(
socket,
"DEBUG",
`{4.1} Inserting new vehicle with ID: ID ${socket.DMSVid.vehiclesVehId}`
);
socket.DMSVeh = await InsertDmsVehicle(socket);
} else {
CdkBase.createLogEvent(
socket,
"DEBUG",
`{4.2} Querying Existing Vehicle using ID ${socket.DMSVid.vehiclesVehId}`
);
socket.DMSVeh = await QueryDmsVehicleById(
socket,
socket.JobData,
socket.DMSVid
);
CdkBase.createLogEvent(
socket,
"DEBUG",
`{4.3} Updating Existing Vehicle to associate to owner.`
);
socket.DMSVeh = await UpdateDmsVehicle(socket);
}
CdkBase.createLogEvent(
socket,
"DEBUG",
`{5} **NOT DONE YET** Updating Service Vehicle History.`
);
} catch (error) {
CdkBase.createLogEvent(
socket,
"ERROR",
`Error encountered in CdkSelectedCustomer. ${error}`
);
} finally {
//Ensure we always insert logEvents
//GQL to insert logevents.
CdkBase.createLogEvent(
socket,
"DEBUG",
`Capturing log events to database.`
);
}
}
exports.CdkSelectedCustomer = CdkSelectedCustomer;
async function QueryJobData(socket, jobid) {
CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`);
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
@@ -188,81 +180,255 @@ async function QueryJobData(socket, jobid) {
return result.jobs_by_pk;
}
async function CreateCustomerInDms(socket, JobData, newCustomerNumber) {
CdkBase.createLogEvent(socket, "DEBUG", `{11} Begin Create Customer in DMS`);
async function CalculateDmsVid(socket, JobData) {
try {
const soapClientCustomerInsertUpdate = await soap.createClientAsync(
CdkWsdl.CustomerInsertUpdate
const soapClientVehicleInsertUpdate = await soap.createClientAsync(
CdkWsdl.VehicleInsertUpdate
);
const soapResponseCustomerInsertUpdate =
await soapClientCustomerInsertUpdate.insertAsync(
{
const soapResponseVehicleInsertUpdate =
await soapClientVehicleInsertUpdate.getVehIdsAsync({
arg0: CDK_CREDENTIALS,
arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, //TODO: Verify why this does not follow the other standards.
arg2: { userId: null },
arg3: {
//Copied the required fields from the other integration.
//TODO: Verify whether we need to bring more information in.
id: { value: newCustomerNumber },
address: {
city: JobData.ownr_city,
country: null,
postalcode: JobData.ownr_zip,
stateOrProvince: JobData.ownr_st,
},
contactInfo: {
mainTelephoneNumber: { main: true, value: JobData.ownr_ph1 },
},
demographics: null,
name1: {
companyname: null,
firstName: JobData.ownr_fn,
fullname: null,
lastName: JobData.ownr_ln,
middleName: null,
nameType: "Person",
suffix: null,
title: null,
},
},
},
arg1: { id: JobData.bodyshop.cdk_dealerid },
arg2: { VIN: JobData.v_vin },
});
{}
const [result, rawResponse, , rawRequest] = soapResponseVehicleInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientVehicleInsertUpdate.getVehIdsAsync request.`
);
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientVehicleInsertUpdate.getVehIdsAsync response.`
);
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
const [
result, //rawResponse, soapheader, rawRequest
] = soapResponseCustomerInsertUpdate;
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientCustomerInsertUpdate.insertAsync Result ${JSON.stringify(
`soapClientVehicleInsertUpdate.getVehIdsAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
const customer = result && result.return;
return customer;
CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate);
return result && result.return && result.return[0];
} catch (error) {
CdkBase.createXmlEvent(
socket,
error.request,
`soapClientVehicleInsertUpdate.getVehIdsAsync request.`,
true
);
CdkBase.createXmlEvent(
socket,
error.response && error.response.data,
`soapClientVehicleInsertUpdate.getVehIdsAsync response.`,
true
);
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in CreateCustomerInDms - ${JSON.stringify(error, null, 2)}`
`{1} Error in CalculateDmsVid - ${error}`
);
throw new Error(error);
}
}
async function GenerateCustomerNumberFromDms(socket, JobData) {
async function QueryDmsVehicleById(socket, JobData, DMSVid) {
try {
const soapClientVehicleInsertUpdate = await soap.createClientAsync(
CdkWsdl.VehicleInsertUpdate
);
const soapResponseVehicleInsertUpdate =
await soapClientVehicleInsertUpdate.readAsync({
arg0: CDK_CREDENTIALS,
arg1: { id: JobData.bodyshop.cdk_dealerid },
arg2: {
fileType: "VEHICLES",
vehiclesVehicleId: DMSVid.vehiclesVehId,
},
});
const [result, rawResponse, , rawRequest] = soapResponseVehicleInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientVehicleInsertUpdate.readAsync request.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientVehicleInsertUpdate.readAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientVehicleInsertUpdate.readAsync response.`
);
CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate);
const VehicleFromDMS = result && result.return && result.return.vehicle;
return VehicleFromDMS;
} catch (error) {
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in QueryDmsVehicleById - ${error}`
);
throw new Error(error);
}
}
async function QueryDmsCustomerById(socket, JobData, CustomerId) {
try {
const soapClientCustomerInsertUpdate = await soap.createClientAsync(
CdkWsdl.CustomerInsertUpdate
);
const soapResponseCustomerInsertUpdate =
await soapClientCustomerInsertUpdate.readAsync({
arg0: CDK_CREDENTIALS,
arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, //TODO: Verify why this does not follow the other standards.
arg2: {
// userId: CustomerId,
},
arg3: CustomerId,
});
const [result, rawResponse, , rawRequest] =
soapResponseCustomerInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientCustomerInsertUpdate.readAsync request.`
);
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientCustomerInsertUpdate.readAsync response.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientCustomerInsertUpdate.readAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
const CustomersFromDms =
result && result.return && result.return.customerParty;
return CustomersFromDms;
} catch (error) {
CdkBase.createXmlEvent(
socket,
error.request,
`soapClientCustomerInsertUpdate.readAsync request.`,
true
);
CdkBase.createXmlEvent(
socket,
error.response && error.response.data,
`soapClientCustomerInsertUpdate.readAsync response.`,
true
);
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in QueryDmsCustomerById - ${error}`
);
throw new Error(error);
}
}
async function QueryDmsCustomerByName(socket, JobData) {
const ownerName = `${JobData.ownr_ln},${JobData.ownr_fn}`;
CdkBase.createLogEvent(
socket,
"DEBUG",
`{10} Begin Generate Customer Number from DMS`
`Begin Query DMS Customer by Name using: ${ownerName}`
);
try {
const soapClientCustomerSearch = await soap.createClientAsync(
CdkWsdl.CustomerSearch
);
const soapResponseCustomerSearch =
await soapClientCustomerSearch.executeSearchAsync({
arg0: CDK_CREDENTIALS,
arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, //TODO: Verify why this does not follow the other standards.
arg2: {
verb: "EXACT",
key: ownerName,
},
});
const [result, rawResponse, , rawRequest] = soapResponseCustomerSearch;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientCustomerSearch.executeSearchBulkAsync request.`
);
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientCustomerSearch.executeSearchBulkAsync response.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientCustomerSearch.executeSearchBulkAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
CheckCdkResponseForError(socket, soapResponseCustomerSearch);
const CustomersFromDms = (result && result.return) || [];
return CustomersFromDms;
} catch (error) {
CdkBase.createXmlEvent(
socket,
error.request,
`soapClientCustomerSearch.executeSearchBulkAsync request.`,
true
);
CdkBase.createXmlEvent(
socket,
error.response && error.response.data,
`soapClientCustomerSearch.executeSearchBulkAsync response.`,
true
);
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in QueryDmsCustomerByName - ${error}`
);
throw new Error(error);
}
}
async function GenerateDmsCustomerNumber(socket) {
try {
const soapClientCustomerInsertUpdate = await soap.createClientAsync(
CdkWsdl.CustomerInsertUpdate
@@ -271,16 +437,27 @@ async function GenerateCustomerNumberFromDms(socket, JobData) {
await soapClientCustomerInsertUpdate.getCustomerNumberAsync(
{
arg0: CDK_CREDENTIALS,
arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, //TODO: Verify why this does not follow the other standards.
arg1: { dealerId: socket.JobData.bodyshop.cdk_dealerid }, //TODO: Verify why this does not follow the other standards.
arg2: { userId: null },
},
{}
);
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
const [
result, //rawResponse, soapheader, rawRequest
] = soapResponseCustomerInsertUpdate;
const [result, rawResponse, , rawRequest] =
soapResponseCustomerInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientCustomerInsertUpdate.getCustomerNumberAsync request.`
);
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientCustomerInsertUpdate.getCustomerNumberAsync response.`
);
CdkBase.createLogEvent(
socket,
@@ -291,163 +468,320 @@ async function GenerateCustomerNumberFromDms(socket, JobData) {
2
)}`
);
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
const customerNumber =
result && result.return && result.return.customerNumber;
return customerNumber;
} catch (error) {
CdkBase.createXmlEvent(
socket,
error.request,
`soapClientCustomerInsertUpdate.getCustomerNumberAsync request.`,
true
);
CdkBase.createXmlEvent(
socket,
error.response && error.response.data,
`soapClientCustomerInsertUpdate.getCustomerNumberAsync response.`,
true
);
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in GenerateCustomerNumberFromDms - ${JSON.stringify(
error,
null,
2
)}`
`Error in GenerateDmsCustomerNumber - ${error}`
);
throw new Error(error);
}
}
async function FindCustomerIdFromDms(socket, JobData) {
const ownerName = `${JobData.ownr_ln},${JobData.ownr_fn}`;
CdkBase.createLogEvent(
socket,
"DEBUG",
`{8} Begin Read Customer from DMS using OWNER NAME: ${ownerName}`
);
async function InsertDmsCustomer(socket, newCustomerNumber) {
try {
const soapClientCustomerSearch = await soap.createClientAsync(
CdkWsdl.CustomerSearch
const soapClientCustomerInsertUpdate = await soap.createClientAsync(
CdkWsdl.CustomerInsertUpdate
);
const soapResponseCustomerSearch =
await soapClientCustomerSearch.executeSearchAsync(
const soapResponseCustomerInsertUpdate =
await soapClientCustomerInsertUpdate.insertAsync(
{
arg0: CDK_CREDENTIALS,
arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, //TODO: Verify why this does not follow the other standards.
arg2: {
verb: "EXACT",
key: ownerName,
arg1: { dealerId: socket.JobData.bodyshop.cdk_dealerid }, //TODO: Verify why this does not follow the other standards.
arg2: { userId: null },
arg3: {
//Copied the required fields from the other integration.
//TODO: Verify whether we need to bring more information in.
id: { value: newCustomerNumber },
address: {
addressLine: socket.JobData.ownr_addr1,
city: socket.JobData.ownr_city,
country: null,
postalCode: socket.JobData.ownr_zip,
stateOrProvince: socket.JobData.ownr_st,
},
contactInfo: {
mainTelephoneNumber: {
main: true,
value: socket.JobData.ownr_ph1,
},
},
demographics: null,
name1: {
companyname: socket.JobData.ownr_co_nm,
firstName: socket.JobData.ownr_fn,
fullname: null,
lastName: socket.JobData.ownr_ln,
middleName: null,
nameType: "Person",
suffix: null,
title: null,
},
},
},
{}
);
CheckCdkResponseForError(socket, soapResponseCustomerSearch);
const [
result, // rawResponse, soapheader, rawRequest
] = soapResponseCustomerSearch;
const [result, rawResponse, , rawRequest] =
soapResponseCustomerInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientCustomerInsertUpdate.insertAsync request.`
);
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientCustomerInsertUpdate.insertAsync response.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientCustomerSearch.executeSearchBulkAsync Result ${JSON.stringify(
`soapClientCustomerInsertUpdate.insertAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
const CustomersFromDms = result && result.return;
return CustomersFromDms;
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
const customer = result && result.return && result.return.customerParty;
return customer;
} catch (error) {
CdkBase.createXmlEvent(
socket,
error.request,
`soapClientCustomerInsertUpdate.insertAsync request.`,
true
);
CdkBase.createXmlEvent(
socket,
error.response && error.response.data,
`soapClientCustomerInsertUpdate.insertAsync response.`,
true
);
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in FindCustomerIdFromDms - ${JSON.stringify(error, null, 2)}`
`Error in InsertDmsCustomer - ${error}`
);
throw new Error(error);
}
}
async function FindVehicleInDms(socket, JobData, clVFV) {
CdkBase.createLogEvent(
socket,
"DEBUG",
`{2}/{6} Begin Find Vehicle In DMS using clVFV: ${clVFV}`
);
async function InsertDmsVehicle(socket) {
try {
const soapClientVehicleInsertUpdate = await soap.createClientAsync(
CdkWsdl.VehicleInsertUpdate
);
const soapResponseVehicleInsertUpdate =
await soapClientVehicleInsertUpdate.readBulkAsync(
{
arg0: CDK_CREDENTIALS,
arg1: { id: JobData.bodyshop.cdk_dealerid },
arg2: {
fileType: "VEHICLES",
vehiclesVehicleId: clVFV.vehiclesVehId,
},
},
{}
const soapResponseVehicleInsertUpdate =
await soapClientVehicleInsertUpdate.insertAsync({
arg0: CDK_CREDENTIALS,
arg1: { id: socket.JobData.bodyshop.cdk_dealerid },
arg2: {
dealer: {
dealerNumber: socket.JobData.bodyshop.cdk_dealerid,
inServiceDate: moment().startOf("day").toISOString(),
vehicleId: socket.DMSVid.vehiclesVehId,
},
manufacturer: {},
vehicle: {
deliveryDate: moment().format("YYYYMMDD"),
make: socket.txEnvelope.dms_make,
modelAbrev: socket.txEnvelope.dms_model,
modelYear: socket.JobData.v_model_yr,
odometerStatus: socket.txEnvelope.kmout,
saleClassValue: "MISC",
VIN: socket.JobData.v_vin,
},
owners: {
id: {
assigningPartyId: "CURRENT",
value: socket.DMSCust.id.value,
},
},
},
arg3: "VEHICLES",
});
const [result, rawResponse, , rawRequest] = soapResponseVehicleInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientVehicleInsertUpdate.insertAsync request.`
);
CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate);
const [
result, //rawResponse, soapheader, rawRequest
] = soapResponseVehicleInsertUpdate;
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientVehicleInsertUpdate.readBulkAsync Result ${JSON.stringify(
`soapClientVehicleInsertUpdate.insertAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
const VehicleFromDMS = result && result.return && result.return[0];
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientVehicleInsertUpdate.insertAsync response.`
);
CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate);
const VehicleFromDMS = result && result.return && result.return.vehicle;
return VehicleFromDMS;
} catch (error) {
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in FindVehicleInDms - ${JSON.stringify(error, null, 2)}`
`Error in InsertDmsVehicle - ${error}`
);
throw new Error(error);
}
}
async function CalculateDmsVid(socket, JobData) {
CdkBase.createLogEvent(
socket,
"TRACE",
`{1} Begin Calculate DMS Vehicle ID using VIN: ${JobData.v_vin}`
);
async function UpdateDmsVehicle(socket) {
try {
const soapClientVehicleInsertUpdate = await soap.createClientAsync(
CdkWsdl.VehicleInsertUpdate
);
const soapResponseVehicleInsertUpdate =
await soapClientVehicleInsertUpdate.getVehIdsAsync(
{
arg0: CDK_CREDENTIALS,
arg1: { id: JobData.bodyshop.cdk_dealerid },
arg2: { VIN: JobData.v_vin },
},
{}
const soapResponseVehicleInsertUpdate =
await soapClientVehicleInsertUpdate.updateAsync({
arg0: CDK_CREDENTIALS,
arg1: { id: socket.JobData.bodyshop.cdk_dealerid },
arg2: {
...socket.DMSVeh,
dealer: {
...socket.DMSVeh.dealer,
inServiceDate: moment(
socket.DMSVeh.dealer.inServiceDate
).toISOString(),
},
vehicle: {
...socket.DMSVeh.vehicle,
deliveryDate: moment(
socket.DMSVeh.vehicle.deliveryDate
).toISOString(),
},
owners: {
id: {
assigningPartyId: "CURRENT",
value: socket.DMSCust.id.value,
},
},
},
arg3: "VEHICLES",
});
const [result, rawResponse, , rawRequest] = soapResponseVehicleInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientVehicleInsertUpdate.updateAsync request.`
);
CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate);
const [
result, //rawResponse, soapheader, rawRequest
] = soapResponseVehicleInsertUpdate;
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientVehicleInsertUpdate.searchIDsByVINAsync Result ${JSON.stringify(
`soapClientVehicleInsertUpdate.updateAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
const DmsVehicle = result && result.return && result.return[0];
return DmsVehicle;
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientVehicleInsertUpdate.updateAsync response.`
);
CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate);
const VehicleFromDMS = result && result.return && result.return.vehicle;
return VehicleFromDMS;
} catch (error) {
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in CalculateDmsVid - ${JSON.stringify(error, null, 2)}`
`Error in UpdateDmsVehicle - ${error}`
);
throw new Error(error);
}
}
async function InsertDmsStartWip(socket) {
try {
const soapClientAccountingGLInsertUpdate = await soap.createClientAsync(
CdkWsdl.AccountingGLInsertUpdate
);
const soapResponseAccountingGLInsertUpdate =
await soapClientAccountingGLInsertUpdate.startWIPAsync({
arg0: CDK_CREDENTIALS,
arg1: { id: socket.JobData.bodyshop.cdk_dealerid },
arg2: {
acctgDate: moment().toISOString(),
desc: socket.txEnvelope.story,
docType: 7 || 10, //Need to check what this usually would be?
//1 Cash Receipt , 2 Check, 3 Journal Voucher, 4 Parts invoice, 5 Payable Invoice, 6 Recurring Entry, 7 Repair Order Invoice, 8 Vehicle Purchase Invoice, 9 Vehicle Sale Invoice, 10 Other, 11 Payroll, 12 Finance Charge, 13 FMLR Invoice, 14 Parts Credit Memo, 15 Manufacturer Document, 16 FMLR Credit Memo
m13Flag: 0,
refer: socket.JobData.ro_number,
srcCo: socket.txEnvelope.journal,
srcJrnl: socket.txEnvelope.journal,
userID: "?", //Where is this coming from?
//userName: "IMEX",
},
});
const [result, rawResponse, , rawRequest] =
soapResponseAccountingGLInsertUpdate;
CdkBase.createXmlEvent(
socket,
rawRequest,
`soapClientAccountingGLInsertUpdate.startWIPAsync request.`
);
CdkBase.createLogEvent(
socket,
"TRACE",
`soapClientAccountingGLInsertUpdate.startWIPAsync Result ${JSON.stringify(
result,
null,
2
)}`
);
CdkBase.createXmlEvent(
socket,
rawResponse,
`soapClientAccountingGLInsertUpdate.startWIPAsync response.`
);
CheckCdkResponseForError(socket, soapResponseAccountingGLInsertUpdate);
const VehicleFromDMS = result && result.return && result.return.vehicle;
return VehicleFromDMS;
} catch (error) {
CdkBase.createLogEvent(
socket,
"ERROR",
`Error in QueryDmsVehicleById - ${error}`
);
throw new Error(error);
}

View File

@@ -78,11 +78,11 @@ exports.checkIndividualResult = checkIndividualResult;
const cdkDomain = "https://uat-3pa.dmotorworks.com";
exports.default = {
// VehicleSearch: `${cdkDomain}/pip-vehicle/services/VehicleSearch?wsdl`,
AccountingGLInsertUpdate: `${cdkDomain}/pip-accounting-gl/services/AccountingGLInsertUpdate?wsdl`,
VehicleInsertUpdate: `${cdkDomain}/pip-vehicle/services/VehicleInsertUpdate?wsdl`,
CustomerInsertUpdate: `${cdkDomain}/pip-customer/services/CustomerInsertUpdate?wsdl`,
CustomerSearch: `${cdkDomain}/pip-customer/services/CustomerSearch?wsdl`,
VehicleSearch: `${cdkDomain}/pip-vehicle/services/VehicleSearch?wsdl`,
VehicleInsert: `${cdkDomain}/pip-vehicle/services/VehicleInsertUpdate?wsdl`,
};
// The following login credentials will be used for all PIPs and all environments (User Acceptance Testing and Production).

View File

@@ -133,6 +133,7 @@ query QUERY_JOBS_FOR_CDK_EXPORT($id: uuid!) {
ownr_fn
ownr_addr1
ownr_addr2
ownr_ph1
ownr_zip
ownr_city
ownr_st
@@ -932,6 +933,19 @@ exports.GET_AUTOHOUSE_SHOPS = `query GET_AUTOHOUSE_SHOPS {
imexshopid
}
}
`;
exports.DELETE_ALL_DMS_VEHICLES = `mutation DELETE_ALL_DMS_VEHICLES{
delete_dms_vehicles(where: {}) {
affected_rows
}
}
`;
exports.INSERT_DMS_VEHICLES = `mutation INSERT_DMS_VEHICLES($vehicles: [dms_vehicles_insert_input!]!) {
insert_dms_vehicles(objects: $vehicles) {
affected_rows
}
}
`;
exports.GET_CDK_ALLOCATIONS = `

View File

@@ -8,7 +8,10 @@ require("dotenv").config({
const { io } = require("../../server");
const { admin } = require("../firebase/firebase-handler");
const CdkJobExport = require("../cdk/cdk-job-export").default;
const {
default: CdkJobExport,
CdkSelectedCustomer,
} = require("../cdk/cdk-job-export");
const CdkGetMakes = require("../cdk/cdk-get-makes").default;
const CdkCalculateAllocations =
require("../cdk/cdk-calculate-allocations").default;
@@ -60,7 +63,7 @@ io.on("connection", (socket) => {
`User selected customer ID ${selectedCustomerId}`
);
socket.selectedCustomerId = selectedCustomerId;
//CdkJobExport(socket, jobid);
CdkSelectedCustomer(socket, selectedCustomerId);
});
socket.on("cdk-get-makes", async (cdk_dealerid, callback) => {
@@ -123,8 +126,40 @@ function createLogEvent(socket, level, message) {
}
}
function createXmlEvent(socket, xml, message, isError = false) {
if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy("TRACE")) {
socket.emit("log-event", {
timestamp: new Date(),
level: isError ? "ERROR" : "TRACE",
message: `${message}: ${xml}`,
});
}
logger.log(
isError ? "ws-log-event-xml-error" : "ws-log-event-xml",
isError ? "ERROR" : "TRACE",
socket.user.email,
socket.recordid,
{
wsmessage: message,
xml,
}
);
if (socket.logEvents && isArray(socket.logEvents)) {
socket.logEvents.push({
timestamp: new Date(),
level: isError ? "ERROR" : "TRACE",
message,
xml,
});
}
}
function LogLevelHierarchy(level) {
switch (level) {
case "XML":
return 5;
case "TRACE":
return 5;
case "DEBUG":
@@ -141,3 +176,4 @@ function LogLevelHierarchy(level) {
}
exports.createLogEvent = createLogEvent;
exports.createXmlEvent = createXmlEvent;