From d50e845ba0d766191da3ade5579e18a722227f34 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Wed, 10 Nov 2021 08:18:29 -0800 Subject: [PATCH 1/6] IO-117 PBS WIP --- server/accounting/pbs/pbs-job-export.js | 100 ++++++++++++++++++++---- 1 file changed, 84 insertions(+), 16 deletions(-) diff --git a/server/accounting/pbs/pbs-job-export.js b/server/accounting/pbs/pbs-job-export.js index 260cf575c..a29d728c2 100644 --- a/server/accounting/pbs/pbs-job-export.js +++ b/server/accounting/pbs/pbs-job-export.js @@ -30,6 +30,9 @@ exports.default = async function (socket, { txEnvelope, jobid }) { const JobData = await QueryJobData(socket, jobid); socket.JobData = JobData; + socket.DmsVeh = await QueryVehicleFromDms(socket); + + socket.DmsCustList = await QueryCustomersFromDms(socket); //Upsert the contact information as per Wafaa's Email. CdkBase.createLogEvent( socket, @@ -42,7 +45,7 @@ exports.default = async function (socket, { txEnvelope, jobid }) { "DEBUG", `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.`); await InsertAccountPostingData(socket); CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported.`); @@ -60,7 +63,11 @@ exports.default = async function (socket, { txEnvelope, jobid }) { async function CheckForErrors(socket, response) { if (response.WasSuccessful) { - return; + CdkBase.createLogEvent( + socket, + "DEBUG", + `Succesful response from DMS:. ${response.Message}` + ); } else { CdkBase.createLogEvent( socket, @@ -89,6 +96,81 @@ async function QueryJobData(socket, jobid) { return result.jobs_by_pk; } +async function QueryVehicleFromDms(socket) { + try { + const { data: VehicleGetResponse } = await axios.post( + PBS_ENDPOINTS.VehicleGet, + { + SerialNumber: socket.JobData.bodyshop.pbs_serialnumber, + // VehicleId: "00000000000000000000000000000000", + // Year: "String", + // Make: "String", + // Model: "String", + // Trim: "String", + // ModelNumber: "String", + // StockNumber: "String", + VIN: socket.JobData.v_vin, + // LicenseNumber: "String", + // Lot: "String", + // Status: "String", + // StatusList: ["String"], + // OwnerRef: "00000000000000000000000000000000", + // ModifiedSince: "0001-01-01T00:00:00.0000000Z", + // ModifiedUntil: "0001-01-01T00:00:00.0000000Z", + // LastSaleSince: "0001-01-01T00:00:00.0000000Z", + // VehicleIDList: ["00000000000000000000000000000000"], + // IncludeInactive: false, + // IncludeBuildVehicles: false, + // ShortVIN: "String", + }, + { auth: PBS_CREDENTIALS } + ); + CheckForErrors(socket, VehicleGetResponse); + return VehicleGetResponse; + } catch (error) { + CdkBase.createLogEvent( + socket, + "ERROR", + `Error in QueryVehicleFromDms - ${error}` + ); + throw new Error(error); + } +} +async function QueryCustomersFromDms(socket) { + try { + const { data: CustomerGetResponse } = await axios.post( + PBS_ENDPOINTS.ContactGet, + { + SerialNumber: socket.JobData.bodyshop.pbs_serialnumber, + //ContactId: "00000000000000000000000000000000", + ContactCode: socket.JobData.owner.accountingid, + FirstName: socket.JobData.ownr_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; + } catch (error) { + CdkBase.createLogEvent( + socket, + "ERROR", + `Error in QueryCustomersFromDms - ${error}` + ); + throw new Error(error); + } +} + async function UpsertContactData(socket) { try { const { data: ContactChangeResponse } = await axios.post( @@ -393,20 +475,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( PBS_ENDPOINTS.AccountingPostingChange, { From 7e1431d65eff8a9f06a600f453a2da004f537b4b Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 10 Nov 2021 15:30:07 -0800 Subject: [PATCH 2/6] IO-117 WIP PBS --- .../dms-customer-selector.component.jsx | 70 +++++++++-- server/accounting/pbs/pbs-job-export.js | 116 ++++++++++++++++-- server/web-sockets/web-socket.js | 11 +- 3 files changed, 173 insertions(+), 24 deletions(-) diff --git a/client/src/components/dms-customer-selector/dms-customer-selector.component.jsx b/client/src/components/dms-customer-selector/dms-customer-selector.component.jsx index a8b7e3f96..6ba3e3451 100644 --- a/client/src/components/dms-customer-selector/dms-customer-selector.component.jsx +++ b/client/src/components/dms-customer-selector/dms-customer-selector.component.jsx @@ -1,4 +1,4 @@ -import { Button, Table, Col , Checkbox} from "antd"; +import { Button, Table, Col, Checkbox } from "antd"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -23,15 +23,26 @@ export function DmsCustomerSelector({ bodyshop }) { const [customerList, setcustomerList] = useState([]); const [visible, setVisible] = useState(false); const [selectedCustomer, setSelectedCustomer] = useState(null); + const [dmsType, setDmsType] = useState("cdk"); socket.on("cdk-select-customer", (customerList, callback) => { setVisible(true); + setDmsType("cdk"); 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 = () => { setVisible(false); - socket.emit("cdk-selected-customer", selectedCustomer); + socket.emit(`${dmsType}-selected-customer`, selectedCustomer); setSelectedCustomer(null); }; @@ -50,7 +61,7 @@ export function DmsCustomerSelector({ bodyshop }) { setSelectedCustomer(null); }; - const columns = [ + const cdkColumns = [ { title: t("jobs.fields.dms.id"), dataIndex: ["id", "value"], @@ -60,13 +71,14 @@ export function DmsCustomerSelector({ bodyshop }) { title: t("jobs.fields.dms.vinowner"), dataIndex: "vinOwner", key: "vinOwner", - render: (text, record) => + render: (text, record) => , }, { title: t("jobs.fields.dms.name1"), dataIndex: ["name1", "fullName"], 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"], key: "address", 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) => , + }, + { + 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 ( )} pagination={{ position: "top" }} - columns={columns} - rowKey={(record) => record.id.value} + columns={dmsType === "cdk" ? cdkColumns : pbsColumns} + rowKey={(record) => + dmsType === "cdk" ? record.id.value : record.ContactId + } dataSource={customerList} //onChange={handleTableChange} rowSelection={{ - onSelect: (props) => { - setSelectedCustomer(props.id.value); + onSelect: (record) => { + setSelectedCustomer( + dmsType === "cdk" ? record.id.value : record.ContactId + ); }, type: "radio", selectedRowKeys: [selectedCustomer], diff --git a/server/accounting/pbs/pbs-job-export.js b/server/accounting/pbs/pbs-job-export.js index a29d728c2..dd0c264a7 100644 --- a/server/accounting/pbs/pbs-job-export.js +++ b/server/accounting/pbs/pbs-job-export.js @@ -30,16 +30,52 @@ exports.default = async function (socket, { txEnvelope, jobid }) { const JobData = await QueryJobData(socket, jobid); socket.JobData = JobData; - socket.DmsVeh = await QueryVehicleFromDms(socket); + //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"}` + ); - socket.DmsCustList = await QueryCustomersFromDms(socket); //Upsert the contact information as per Wafaa's Email. CdkBase.createLogEvent( socket, "DEBUG", `Upserting contact information to DMS for ${socket.JobData.ownr_fn} ${socket.JobData.ownr_ln} ${socket.JobData.ownr_co_nm}` ); - const ownerRef = await UpsertContactData(socket); + const ownerRef = await UpsertContactData(socket, selectedCustomerId); + CdkBase.createLogEvent( socket, "DEBUG", @@ -56,28 +92,29 @@ exports.default = async function (socket, { txEnvelope, jobid }) { CdkBase.createLogEvent( socket, "ERROR", - `Error encountered in PbsJobExport. ${error}` + `Error encountered in CdkSelectedCustomer. ${error}` ); + await InsertFailedExportLog(socket, error); } }; async function CheckForErrors(socket, response) { - if (response.WasSuccessful) { + if (response.WasSuccessful === undefined || response.WasSuccessful === true) { CdkBase.createLogEvent( socket, "DEBUG", - `Succesful response from DMS:. ${response.Message}` + `Succesful response from DMS. ${response.Message || ""}` ); } else { CdkBase.createLogEvent( socket, "ERROR", - `Error received from DMS:. ${response.Message}` + `Error received from DMS: ${response.Message}` ); CdkBase.createLogEvent( socket, "TRACE", - `Error received from DMS:. ${JSON.stringify(response)}` + `Error received from DMS: ${JSON.stringify(response)}` ); } } @@ -144,7 +181,9 @@ async function QueryCustomersFromDms(socket) { SerialNumber: socket.JobData.bodyshop.pbs_serialnumber, //ContactId: "00000000000000000000000000000000", ContactCode: socket.JobData.owner.accountingid, - FirstName: socket.JobData.ownr_fn, + 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", @@ -160,7 +199,43 @@ async function QueryCustomersFromDms(socket) { { auth: PBS_CREDENTIALS } ); CheckForErrors(socket, CustomerGetResponse); - return 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, @@ -171,14 +246,14 @@ async function QueryCustomersFromDms(socket) { } } -async function UpsertContactData(socket) { +async function UpsertContactData(socket, selectedCustomerId) { try { const { data: ContactChangeResponse } = await axios.post( PBS_ENDPOINTS.ContactChange, { ContactInfo: { // Id: socket.JobData.owner.id, - ContactId: socket.JobData.owner.id, + ...(selectedCustomerId ? { ContactId: selectedCustomerId } : {}), SerialNumber: socket.JobData.bodyshop.pbs_serialnumber, Code: socket.JobData.owner.accountingid, ...(socket.JobData.ownr_co_nm @@ -531,3 +606,20 @@ async function MarkJobExported(socket, jobid) { 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; +} diff --git a/server/web-sockets/web-socket.js b/server/web-sockets/web-socket.js index 7bd126caf..315cf1c10 100644 --- a/server/web-sockets/web-socket.js +++ b/server/web-sockets/web-socket.js @@ -17,7 +17,7 @@ const CdkCalculateAllocations = require("../cdk/cdk-calculate-allocations").default; const { isArray } = require("lodash"); 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) { try { @@ -113,6 +113,15 @@ io.on("connection", (socket) => { socket.on("pbs-export-job", (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 socket.on("disconnect", () => { From 89af6d23e82b477fd24cc6ba27e32efa2360a52d Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 10 Nov 2021 16:22:52 -0800 Subject: [PATCH 3/6] IO-1513 Added next contact date. --- bodyshop_translations.babel | 23 +++++++++++++++- .../jobs-detail-dates.component.jsx | 6 +++++ .../production-list-columns.data.js | 26 ++++++++++++++++++- ...n-list-columns.lastcontacted.component.jsx | 18 +++++++++++-- client/src/graphql/jobs.queries.js | 4 +++ client/src/translations/en_us/common.json | 1 + client/src/translations/es/common.json | 1 + client/src/translations/fr/common.json | 1 + hasura/metadata/tables.yaml | 3 +++ .../down.sql | 4 +++ .../up.sql | 2 ++ .../down.sql | 2 ++ .../up.sql | 1 + .../down.sql | 4 +++ .../up.sql | 2 ++ 15 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 hasura/migrations/1636587357661_alter_table_public_jobs_add_column_date_next_contact/down.sql create mode 100644 hasura/migrations/1636587357661_alter_table_public_jobs_add_column_date_next_contact/up.sql create mode 100644 hasura/migrations/1636589196038_alter_table_public_jobs_drop_column_date_next_contact/down.sql create mode 100644 hasura/migrations/1636589196038_alter_table_public_jobs_drop_column_date_next_contact/up.sql create mode 100644 hasura/migrations/1636589211585_alter_table_public_jobs_add_column_date_next_contact/down.sql create mode 100644 hasura/migrations/1636589211585_alter_table_public_jobs_add_column_date_next_contact/up.sql diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index c6ab7bc49..62a2bc141 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -1,4 +1,4 @@ - +