const path = require("path"); require("dotenv").config({ path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`) }); const GraphQLClient = require("graphql-request").GraphQLClient; const soap = require("soap"); const queries = require("../graphql-client/queries"); const CdkBase = require("../web-sockets/web-socket"); const CdkWsdl = require("./cdk-wsdl").default; const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl"); const CalcualteAllocations = require("./cdk-calculate-allocations").default; const InstanceMgr = require("../utils/instanceMgr").default; const moment = require("moment-timezone"); const { setSessionData, getSessionData, getMultipleSessionData, setMultipleSessionData, clearList } = require("../../server"); const replaceSpecialRegex = /[^a-zA-Z0-9 .,\n #]+/g; exports.default = async function (socket, { txEnvelope, jobid }) { await setMultipleSessionData(socket.id, { recordid: jobid, txEnvelope }); await clearList(socket.id, "logEvents"); try { await CdkBase.createLogEvent(socket, "DEBUG", `Received Job export request for id ${jobid}`); const JobData = await QueryJobData(socket, jobid); await setSessionData(socket.id, "JobData", JobData); const DealerId = JobData.bodyshop.cdk_dealerid; await CdkBase.createLogEvent(socket, "DEBUG", `Dealer ID detected: ${JSON.stringify(DealerId)}`); await CdkBase.createLogEvent(socket, "DEBUG", `{1} Begin Calculate DMS Vehicle ID using VIN: ${JobData.v_vin}`); const DMSVid = await CalculateDmsVid(socket, JobData); await setSessionData(socket.id, "DMSVid", DMSVid); if (DMSVid.newId === "N") { await CdkBase.createLogEvent( socket, "DEBUG", `{2.1} Querying the Vehicle using the DMSVid: ${DMSVid.vehiclesVehId}` ); const DMSVeh = await QueryDmsVehicleById(socket, JobData, DMSVid); await setSessionData(socket.id, "DMSVeh", DMSVeh); const DMSVehCustomer = DMSVeh && DMSVeh.owners && DMSVeh.owners.find((o) => o.id.assigningPartyId === "CURRENT"); if (DMSVehCustomer?.id?.value) { await CdkBase.createLogEvent( socket, "DEBUG", `{2.2} Querying the Customer using the ID from DMSVeh: ${DMSVehCustomer.id.value}` ); await setSessionData( socket.id, "DMSVehCustomer", await QueryDmsCustomerById(socket, JobData, DMSVehCustomer.id.value) ); } } await CdkBase.createLogEvent(socket, "DEBUG", `{2.3} Querying the Customer using the name.`); /// const DMSCustList = await QueryDmsCustomerByName(socket, JobData); await setSessionData(socket.id, "DMSCustList", DMSCustList); const DMSVehCustomer = await getSessionData(socket.id, "DMSVehCustomer"); socket.emit("cdk-select-customer", [ ...(DMSVehCustomer ? [{ ...DMSVehCustomer, vinOwner: true }] : []), ...DMSCustList ]); } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkJobExport. ${error}`); } }; async function CdkSelectedCustomer(socket, selectedCustomerId) { try { await setSessionData(socket.id, "selectedCustomerId", selectedCustomerId); const JobData = await getSessionData(socket.id, "JobData"); if (selectedCustomerId) { await CdkBase.createLogEvent( socket, "DEBUG", `{3.1} Querying the Customer using Customer ID: ${selectedCustomerId}` ); const DMSCust = await QueryDmsCustomerById(socket, JobData, selectedCustomerId); await setSessionData(socket.id, "DMSCust", DMSCust); } else { await CdkBase.createLogEvent(socket, "DEBUG", `{3.2} Generating a new customer ID.`); const newCustomerId = await GenerateDmsCustomerNumber(socket); await CdkBase.createLogEvent(socket, "DEBUG", `{3.3} Inserting new customer with ID: ${newCustomerId}`); const DMSCust = await InsertDmsCustomer(socket, newCustomerId); await setSessionData(socket.id, "DMSCust", DMSCust); } const DMSVid = await getSessionData(socket.id, "DMSVid"); if (DMSVid.newId === "Y") { await CdkBase.createLogEvent(socket, "DEBUG", `{4.1} Inserting new vehicle with ID: ID ${DMSVid.vehiclesVehId}`); await setSessionData(socket.id, "DMSVeh", await InsertDmsVehicle(socket)); } else { await CdkBase.createLogEvent(socket, "DEBUG", `{4.2} Querying Existing Vehicle using ID ${DMSVid.vehiclesVehId}`); await setSessionData(socket.id, "DMSVeh", await QueryDmsVehicleById(socket, JobData, DMSVid)); await CdkBase.createLogEvent(socket, "DEBUG", `{4.3} Updating Existing Vehicle to associate to owner.`); await setSessionData(socket.id, "DMSVeh", await UpdateDmsVehicle(socket)); } await CdkBase.createLogEvent(socket, "DEBUG", `{5} Creating Transaction header with Dms Start WIP`); const DMSTransHeader = await InsertDmsStartWip(socket); await setSessionData(socket.id, "DMSTransHeader", DMSTransHeader); await CdkBase.createLogEvent(socket, "DEBUG", `{5.1} Creating Transaction with ID ${DMSTransHeader.transID}`); await setSessionData(socket.id, "DMSBatchTxn", await InsertDmsBatchWip(socket)); await CdkBase.createLogEvent( socket, "DEBUG", `{6} Attempting to post Transaction with ID ${DMSTransHeader.transID}` ); const DmsBatchTxnPost = await PostDmsBatchWip(socket); await setSessionData(socket.id, "DMSBatchTxnPost", DmsBatchTxnPost); if (DmsBatchTxnPost.code === "success") { await CdkBase.createLogEvent(socket, "DEBUG", `{6} Successfully posted transaction to DMS.`); await MarkJobExported(socket, JobData.id); await CdkBase.createLogEvent(socket, "DEBUG", `{5} Updating Service Vehicle History.`); const DMSVehHistory = await InsertServiceVehicleHistory(socket); await setSessionData(socket.id, "DMSVehHistory", DMSVehHistory); socket.emit("export-success", JobData.id); } else { await CdkBase.createLogEvent( socket, "DEBUG", `{6.1} Getting errors for Transaction ID ${DMSTransHeader.transID}` ); const DmsError = await QueryDmsErrWip(socket); await setSessionData(socket.id, "DmsError", DmsError); await CdkBase.createLogEvent(socket, "DEBUG", `{6.2} Deleting Transaction ID ${DMSTransHeader.transID}`); await setSessionData(socket.id, "DmsBatchTxnPost", await DeleteDmsWip(socket)); for (const e of DmsError.errMsg.split("|")) { if (e !== null && e !== "") { await CdkBase.createLogEvent(socket, "ERROR", `Error(s) encountered in posting transaction. ${e}`); } } } } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkSelectedCustomer. ${error}`); await InsertFailedExportLog(socket, error); } finally { await CdkBase.createLogEvent(socket, "DEBUG", `Capturing log events to database.`); } } exports.CdkSelectedCustomer = CdkSelectedCustomer; async function QueryJobData(socket, jobid) { await CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`); const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {}); const result = await client .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) .request(queries.QUERY_JOBS_FOR_CDK_EXPORT, { id: jobid }); await CdkBase.createLogEvent(socket, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`); return result.jobs_by_pk; } async function CalculateDmsVid(socket, JobData) { 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 [result, rawResponse, , rawRequest] = soapResponseVehicleInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientVehicleInsertUpdate.getVehIdsAsync request.`); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.getVehIdsAsync response.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientVehicleInsertUpdate.getVehIdsAsync Result ${JSON.stringify(result, null, 2)}` ); await CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate); //if (result && result.return && result.return.length > 1) { return result.return.find((r) => r.vehiclesVehId); //} //return result && result.return && result.return[0]; } catch (error) { await CdkBase.createXmlEvent(socket, error.request, `soapClientVehicleInsertUpdate.getVehIdsAsync request.`, true); await CdkBase.createXmlEvent( socket, error.response && error.response.data, `soapClientVehicleInsertUpdate.getVehIdsAsync response.`, true ); await CdkBase.createLogEvent(socket, "ERROR", `{1} Error in CalculateDmsVid - ${error}`); throw new Error(error); } } 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; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientVehicleInsertUpdate.readAsync request.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientVehicleInsertUpdate.readAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.readAsync response.`); await CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate); return result && result.return && result.return.vehicle; } catch (error) { await 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; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientCustomerInsertUpdate.readAsync request.`); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientCustomerInsertUpdate.readAsync response.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientCustomerInsertUpdate.readAsync Result ${JSON.stringify(result, null, 2)}` ); await CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate); return result && result.return && result.return.customerParty; } catch (error) { await CdkBase.createXmlEvent(socket, error.request, `soapClientCustomerInsertUpdate.readAsync request.`, true); await CdkBase.createXmlEvent( socket, error.response && error.response.data, `soapClientCustomerInsertUpdate.readAsync response.`, true ); await CdkBase.createLogEvent(socket, "ERROR", `Error in QueryDmsCustomerById - ${error}`); throw new Error(error); } } async function QueryDmsCustomerByName(socket, JobData) { const ownerName = ( JobData.ownr_co_nm && JobData.ownr_co_nm.trim() !== "" ? JobData.ownr_co_nm : `${JobData.ownr_ln},${JobData.ownr_fn}` ).replace(replaceSpecialRegex, ""); await CdkBase.createLogEvent(socket, "DEBUG", `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; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientCustomerSearch.executeSearchBulkAsync request.`); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientCustomerSearch.executeSearchBulkAsync response.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientCustomerSearch.executeSearchBulkAsync Result ${JSON.stringify(result, null, 2)}` ); await CheckCdkResponseForError(socket, soapResponseCustomerSearch); return (result && result.return) || []; } catch (error) { await CdkBase.createXmlEvent( socket, error.request, `soapClientCustomerSearch.executeSearchBulkAsync request.`, true ); await CdkBase.createXmlEvent( socket, error.response && error.response.data, `soapClientCustomerSearch.executeSearchBulkAsync response.`, true ); await CdkBase.createLogEvent(socket, "ERROR", `Error in QueryDmsCustomerByName - ${error}`); throw new Error(error); } } async function GenerateDmsCustomerNumber(socket) { try { const JobData = await getSessionData(socket.id, "JobData"); const soapClientCustomerInsertUpdate = await soap.createClientAsync(CdkWsdl.CustomerInsertUpdate); const soapResponseCustomerInsertUpdate = await soapClientCustomerInsertUpdate.getCustomerNumberAsync( { arg0: CDK_CREDENTIALS, arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, // TODO: Verify why this does not follow the other standards. arg2: { userId: null } }, {} ); const [result, rawResponse, , rawRequest] = soapResponseCustomerInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientCustomerInsertUpdate.getCustomerNumberAsync request.`); await CdkBase.createXmlEvent( socket, rawResponse, `soapClientCustomerInsertUpdate.getCustomerNumberAsync response.` ); await CdkBase.createLogEvent( socket, "TRACE", `soapClientCustomerInsertUpdate.getCustomerNumberAsync Result ${JSON.stringify(result, null, 2)}` ); await CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate); const customerNumber = result && result.return && result.return.customerNumber; return customerNumber; } catch (error) { await CdkBase.createXmlEvent( socket, error.request, `soapClientCustomerInsertUpdate.getCustomerNumberAsync request.`, true ); await CdkBase.createXmlEvent( socket, error.response && error.response.data, `soapClientCustomerInsertUpdate.getCustomerNumberAsync response.`, true ); await CdkBase.createLogEvent(socket, "ERROR", `Error in GenerateDmsCustomerNumber - ${error}`); throw new Error(error); } } async function InsertDmsCustomer(socket, newCustomerNumber) { try { const JobData = await getSessionData(socket.id, "JobData"); const soapClientCustomerInsertUpdate = await soap.createClientAsync(CdkWsdl.CustomerInsertUpdate); const soapResponseCustomerInsertUpdate = await soapClientCustomerInsertUpdate.insertAsync( { arg0: CDK_CREDENTIALS, arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, 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: JobData.ownr_addr1 && JobData.ownr_addr1.replace(replaceSpecialRegex, ""), city: JobData.ownr_city && JobData.ownr_city.replace(replaceSpecialRegex, ""), country: JobData.ownr_ctry && JobData.ownr_ctry.replace(replaceSpecialRegex, ""), postalCode: InstanceMgr({ imex: JobData.ownr_zip && JobData.ownr_zip.toUpperCase().replace(/\W/g, "").replace(/(...)/, "$1 "), rome: JobData.ownr_zip }), stateOrProvince: JobData.ownr_st && JobData.ownr_st.replace(replaceSpecialRegex, "") }, contactInfo: { mainTelephoneNumber: { main: true, value: JobData.ownr_ph1 && JobData.ownr_ph1.replace(replaceSpecialRegex, "") }, email: { desc: JobData.ownr_ea ? "Other" : "CustomerDeclined", value: JobData.ownr_ea ? JobData.ownr_ea : null } }, demographics: null, name1: { companyName: JobData.ownr_co_nm && JobData.ownr_co_nm.replace(replaceSpecialRegex, "").toUpperCase(), firstName: JobData.ownr_fn && JobData.ownr_fn.replace(replaceSpecialRegex, "").toUpperCase(), fullname: null, lastName: JobData.ownr_ln && JobData.ownr_ln.replace(replaceSpecialRegex, "").toUpperCase(), middleName: null, nameType: JobData.ownr_co_nm && String(JobData.ownr_co_nm).trim() !== "" ? "Business" : "Person", suffix: null, title: null } } }, {} ); const [result, rawResponse, , rawRequest] = soapResponseCustomerInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientCustomerInsertUpdate.insertAsync request.`); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientCustomerInsertUpdate.insertAsync response.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientCustomerInsertUpdate.insertAsync Result ${JSON.stringify(result, null, 2)}` ); await CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate); const customer = result && result.return && result.return.customerParty; return customer; } catch (error) { await CdkBase.createXmlEvent(socket, error.request, `soapClientCustomerInsertUpdate.insertAsync request.`, true); await CdkBase.createXmlEvent( socket, error.response && error.response.data, `soapClientCustomerInsertUpdate.insertAsync response.`, true ); await CdkBase.createLogEvent(socket, "ERROR", `Error in InsertDmsCustomer - ${error}`); throw new Error(error); } } async function InsertDmsVehicle(socket) { try { const { JobData, txEnvelope, DMSVid, DMSCust } = await getMultipleSessionData(socket.id, [ "JobData", "txEnvelope", "DMSVid", "DMSCust" ]); const soapClientVehicleInsertUpdate = await soap.createClientAsync(CdkWsdl.VehicleInsertUpdate); const soapResponseVehicleInsertUpdate = await soapClientVehicleInsertUpdate.insertAsync({ arg0: CDK_CREDENTIALS, arg1: { id: JobData.bodyshop.cdk_dealerid }, arg2: { dealer: { dealerNumber: JobData.bodyshop.cdk_dealerid, ...(txEnvelope.inservicedate && { inServiceDate: txEnvelope.dms_unsold === true ? "" : moment(txEnvelope.inservicedate) //.tz(JobData.bodyshop.timezone) .startOf("day") .toISOString() }), vehicleId: DMSVid.vehiclesVehId }, manufacturer: {}, vehicle: { deliveryDate: txEnvelope.dms_unsold === true ? "" : moment() //.tz(JobData.bodyshop.timezone) .format("YYYYMMDD"), licensePlateNo: JobData.plate_no === null ? null : String(JobData.plate_no).replace(/([^\w]|_)/g, "").length === 0 ? null : String(JobData.plate_no) .replace(/([^\w]|_)/g, "") .toUpperCase(), make: txEnvelope.dms_make, modelAbrev: txEnvelope.dms_model, modelYear: JobData.v_model_yr, odometerStatus: txEnvelope.kmout, saleClassValue: "MISC", VIN: JobData.v_vin }, owners: { id: { assigningPartyId: "CURRENT", value: DMSCust.id.value } } }, arg3: "VEHICLES" }); const [result, rawResponse, , rawRequest] = soapResponseVehicleInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientVehicleInsertUpdate.insertAsync request.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientVehicleInsertUpdate.insertAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.insertAsync response.`); await CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate); return result && result.return && result.return.vehicle; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in InsertDmsVehicle - ${error}`); throw new Error(error); } } async function UpdateDmsVehicle(socket) { try { const soapClientVehicleInsertUpdate = await soap.createClientAsync(CdkWsdl.VehicleInsertUpdate); const { JobData, DMSVeh, DMSCust, selectedCustomerId, txEnvelope } = await getMultipleSessionData(socket.id, [ "JobData", "DMSVeh", "DMSCust", "selectedCustomerId", "txEnvelope" ]); let ids = []; // If it's a generic customer, don't update the vehicle owners. if (selectedCustomerId === JobData.bodyshop.cdk_configuration.generic_customer_number) { ids = DMSVeh && DMSVeh.owners; } else { const existingOwnerinVeh = DMSVeh && DMSVeh.owners && DMSVeh.owners.find((o) => o.id.value === DMSCust.id.value); if (existingOwnerinVeh) { ids = DMSVeh.owners.map((o) => { return { id: { assigningPartyId: o.id.value === DMSCust.id.value ? "CURRENT" : "PREVIOUS", value: o.id.value } }; }); } else { const oldOwner = DMSVeh && DMSVeh.owners && DMSVeh.owners.find((o) => o.id.assigningPartyId === "CURRENT"); ids = [ { id: { assigningPartyId: "CURRENT", value: DMSCust.id.value } }, ...(oldOwner ? [ { id: { assigningPartyId: "PREVIOUS", value: oldOwner.id.value } } ] : []) ]; } } const soapResponseVehicleInsertUpdate = await soapClientVehicleInsertUpdate.updateAsync({ arg0: CDK_CREDENTIALS, arg1: { id: JobData.bodyshop.cdk_dealerid }, arg2: { ...DMSVeh, dealer: { ...DMSVeh.dealer, ...((txEnvelope.inservicedate || DMSVeh.dealer.inServiceDate) && { inServiceDate: txEnvelope.dms_unsold === true ? "" : moment(DMSVeh.dealer.inServiceDate || txEnvelope.inservicedate) // .tz(JobData.bodyshop.timezone) .toISOString() }) }, vehicle: { ...DMSVeh.vehicle, ...(txEnvelope.dms_model_override ? { make: txEnvelope.dms_make, modelAbrev: txEnvelope.dms_model } : {}), deliveryDate: txEnvelope.dms_unsold === true ? "" : moment(DMSVeh.vehicle.deliveryDate) // .tz(JobData.bodyshop.timezone) .toISOString() }, owners: ids }, arg3: "VEHICLES" }); const [result, rawResponse, , rawRequest] = soapResponseVehicleInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientVehicleInsertUpdate.updateAsync request.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientVehicleInsertUpdate.updateAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.updateAsync response.`); await CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate); return result && result.return && result.return.vehicle; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in UpdateDmsVehicle - ${error}`); throw new Error(error); } } async function InsertServiceVehicleHistory(socket) { try { const { JobData, DMSVid, txEnvelope } = await getMultipleSessionData(socket.id, [ "JobData", "DMSVid", "txEnvelope" ]); const soapClientServiceHistoryInsert = await soap.createClientAsync(CdkWsdl.ServiceHistoryInsert); const soapResponseServiceHistoryInsert = await soapClientServiceHistoryInsert.serviceHistoryHeaderInsertAsync({ authToken: CDK_CREDENTIALS, dealerId: { dealerId: JobData.bodyshop.cdk_dealerid }, serviceHistoryHeader: { vehID: DMSVid.vehiclesVehId, roNumber: JobData.ro_number.match(/\d+/g), mileage: txEnvelope.kmout, openDate: moment(JobData.actual_in).tz(JobData.bodyshop.timezone).format("YYYY-MM-DD"), openTime: moment(JobData.actual_in).tz(JobData.bodyshop.timezone).format("HH:mm:ss"), closeDate: moment(JobData.invoice_date).tz(JobData.bodyshop.timezone).format("YYYY-MM-DD"), closeTime: moment(JobData.invoice_date).tz(JobData.bodyshop.timezone).format("HH:mm:ss"), comments: txEnvelope.story, cashierID: JobData.bodyshop.cdk_configuration.cashierid } }); const [result, rawResponse, , rawRequest] = soapResponseServiceHistoryInsert; await CdkBase.createXmlEvent( socket, rawRequest, `soapClientServiceHistoryInsert.serviceHistoryHeaderInsert request.` ); await CdkBase.createLogEvent( socket, "TRACE", `soapClientServiceHistoryInsert.serviceHistoryHeaderInsert Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent( socket, rawResponse, `soapClientServiceHistoryInsert.serviceHistoryHeaderInsert response.` ); await CheckCdkResponseForError(socket, soapResponseServiceHistoryInsert); return result && result.return; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in InsertServiceVehicleHistory - ${error}`); throw new Error(error); } } async function InsertDmsStartWip(socket) { try { const { JobData, txEnvelope } = await getMultipleSessionData(socket.id, ["JobData", "txEnvelope"]); const soapClientAccountingGLInsertUpdate = await soap.createClientAsync(CdkWsdl.AccountingGLInsertUpdate); const soapResponseAccountingGLInsertUpdate = await soapClientAccountingGLInsertUpdate.doStartWIPAsync({ arg0: CDK_CREDENTIALS, arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, arg2: { acctgDate: moment().tz(JobData.bodyshop.timezone).format("YYYY-MM-DD"), desc: txEnvelope.story && txEnvelope.story.replace(replaceSpecialRegex, ""), docType: 10 || 7, // Need to check what this usually would be? Apparently it is almost always 10 or 7. // 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: JobData.ro_number, srcCo: JobData.bodyshop.cdk_configuration.srcco, srcJrnl: txEnvelope.journal, userID: JobData.bodyshop.cdk_configuration.cashierid // Where is this coming from? // userName: "IMEX", } }); const [result, rawResponse, , rawRequest] = soapResponseAccountingGLInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientAccountingGLInsertUpdate.doStartWIPAsync request.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientAccountingGLInsertUpdate.doStartWIPAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doStartWIPAsync response.`); await CheckCdkResponseForError(socket, soapResponseAccountingGLInsertUpdate); return result && result.return; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in InsertDmsStartWip - ${error}`); throw new Error(error); } } async function InsertDmsBatchWip(socket) { try { const JobData = await getSessionData(socket.id, "JobData"); const soapClientAccountingGLInsertUpdate = await soap.createClientAsync(CdkWsdl.AccountingGLInsertUpdate); const soapResponseAccountingGLInsertUpdate = await soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync({ arg0: CDK_CREDENTIALS, arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, arg2: { transWIPs: await GenerateTransWips(socket) } }); const [result, rawResponse, , rawRequest] = soapResponseAccountingGLInsertUpdate; await CdkBase.createXmlEvent( socket, rawRequest, `soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync request.` ); await CdkBase.createLogEvent( socket, "TRACE", `soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent( socket, rawResponse, `soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync response.` ); await CheckCdkResponseForError(socket, soapResponseAccountingGLInsertUpdate); return result && result.return; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in InsertDmsBatchWip - ${error}`); throw new Error(error); } } async function GenerateTransWips(socket) { const { JobData, DMSTransHeader, txEnvelope } = await getMultipleSessionData(socket.id, [ "JobData", "DMSTransHeader", "txEnvelope" ]); const allocations = await CalcualteAllocations(socket, JobData.id); const wips = []; allocations.forEach((alloc) => { // Add the sale item from each allocation. if (alloc.sale.getAmount() > 0 && !alloc.tax) { const item = { acct: alloc.profitCenter.dms_acctnumber, cntl: alloc.profitCenter.dms_control_override && alloc.profitCenter.dms_control_override !== null && alloc.profitCenter.dms_control_override !== undefined && alloc.profitCenter.dms_control_override?.trim() !== "" ? alloc.profitCenter.dms_control_override : JobData.ro_number, cntl2: null, credtMemoNo: null, postAmt: alloc.sale.multiply(-1).getAmount(), postDesc: null, prod: null, statCnt: 1, transID: DMSTransHeader.transID, trgtCoID: JobData.bodyshop.cdk_configuration.srcco }; wips.push(item); } // Add the cost item. if (alloc.cost.getAmount() > 0 && !alloc.tax) { const item = { acct: alloc.costCenter.dms_acctnumber, cntl: alloc.costCenter.dms_control_override && alloc.costCenter.dms_control_override !== null && alloc.costCenter.dms_control_override !== undefined && alloc.costCenter.dms_control_override?.trim() !== "" ? alloc.costCenter.dms_control_override : JobData.ro_number, cntl2: null, credtMemoNo: null, postAmt: alloc.cost.getAmount(), postDesc: null, prod: null, statCnt: 1, transID: DMSTransHeader.transID, trgtCoID: JobData.bodyshop.cdk_configuration.srcco }; wips.push(item); const itemWip = { acct: alloc.costCenter.dms_wip_acctnumber, cntl: alloc.costCenter.dms_control_override && alloc.costCenter.dms_control_override !== null && alloc.costCenter.dms_control_override !== undefined && alloc.costCenter.dms_control_override?.trim() !== "" ? alloc.costCenter.dms_control_override : JobData.ro_number, cntl2: null, credtMemoNo: null, postAmt: alloc.cost.multiply(-1).getAmount(), postDesc: null, prod: null, statCnt: 1, transID: DMSTransHeader.transID, trgtCoID: JobData.bodyshop.cdk_configuration.srcco }; wips.push(itemWip); } // Handle tax allocations if (alloc.tax && alloc.sale.getAmount() > 0) { const item2 = { acct: alloc.profitCenter.dms_acctnumber, cntl: alloc.profitCenter.dms_control_override && alloc.profitCenter.dms_control_override !== null && alloc.profitCenter.dms_control_override !== undefined && alloc.profitCenter.dms_control_override?.trim() !== "" ? alloc.profitCenter.dms_control_override : JobData.ro_number, cntl2: null, credtMemoNo: null, postAmt: alloc.sale.multiply(-1).getAmount(), postDesc: null, prod: null, statCnt: 1, transID: DMSTransHeader.transID, trgtCoID: JobData.bodyshop.cdk_configuration.srcco }; wips.push(item2); } }); // Add payers to the WIP txEnvelope.payers.forEach((payer) => { const item = { acct: payer.dms_acctnumber, cntl: payer.controlnumber, cntl2: null, credtMemoNo: null, postAmt: Math.round(payer.amount * 100), postDesc: null, prod: null, statCnt: 1, transID: DMSTransHeader.transID, trgtCoID: JobData.bodyshop.cdk_configuration.srcco }; wips.push(item); }); await setSessionData(socket.id, "transWips", wips); return wips; } async function PostDmsBatchWip(socket) { try { const { JobData, DMSTransHeader } = await getMultipleSessionData(socket.id, ["JobData", "DMSTransHeader"]); const soapClientAccountingGLInsertUpdate = await soap.createClientAsync(CdkWsdl.AccountingGLInsertUpdate); const soapResponseAccountingGLInsertUpdate = await soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync({ arg0: CDK_CREDENTIALS, arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, arg2: { postWIP: { opCode: "P", transID: DMSTransHeader.transID } } }); const [result, rawResponse, , rawRequest] = soapResponseAccountingGLInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync request.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent( socket, rawResponse, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync response.` ); return result && result.return; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in PostDmsBatchWip - ${error}`); throw new Error(error); } } async function QueryDmsErrWip(socket) { try { const { JobData, DMSTransHeader } = await getMultipleSessionData(socket.id, ["JobData", "DMSTransHeader"]); const soapClientAccountingGLInsertUpdate = await soap.createClientAsync(CdkWsdl.AccountingGLInsertUpdate); const soapResponseAccountingGLInsertUpdate = await soapClientAccountingGLInsertUpdate.doErrWIPAsync({ arg0: CDK_CREDENTIALS, arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, arg2: DMSTransHeader.transID }); const [result, rawResponse, , rawRequest] = soapResponseAccountingGLInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientAccountingGLInsertUpdate.doErrWIPAsync request.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientAccountingGLInsertUpdate.doErrWIPAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doErrWIPAsync response.`); await CheckCdkResponseForError(socket, soapResponseAccountingGLInsertUpdate); return result && result.return; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in QueryDmsErrWip - ${error}`); throw new Error(error); } } async function DeleteDmsWip(socket) { try { const { JobData, DMSTransHeader } = await getMultipleSessionData(socket.id, ["JobData", "DMSTransHeader"]); const soapClientAccountingGLInsertUpdate = await soap.createClientAsync(CdkWsdl.AccountingGLInsertUpdate); const soapResponseAccountingGLInsertUpdate = await soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync({ arg0: CDK_CREDENTIALS, arg1: { dealerId: JobData.bodyshop.cdk_dealerid }, arg2: { postWIP: { opCode: "D", transID: DMSTransHeader.transID } } }); const [result, rawResponse, , rawRequest] = soapResponseAccountingGLInsertUpdate; await CdkBase.createXmlEvent(socket, rawRequest, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync request.`); await CdkBase.createLogEvent( socket, "TRACE", `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync Result ${JSON.stringify(result, null, 2)}` ); await CdkBase.createXmlEvent( socket, rawResponse, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync response.` ); await CheckCdkResponseForError(socket, soapResponseAccountingGLInsertUpdate); return result && result.return; } catch (error) { await CdkBase.createLogEvent(socket, "ERROR", `Error in PostDmsBatchWip - ${error}`); throw new Error(error); } } async function MarkJobExported(socket, jobid) { await CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported for id ${jobid}`); const { JobData, transWips = [] } = await getMultipleSessionData(socket.id, ["JobData", "transWips"]); const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {}); return await client .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) .request(queries.MARK_JOB_EXPORTED, { jobId: jobid, job: { status: JobData.bodyshop.md_ro_statuses.default_exported || "Exported*", date_exported: new Date() }, log: { bodyshopid: JobData.bodyshop.id, jobid: jobid, successful: true, useremail: socket.user.email, metadata: transWips }, bill: { exported: true, exported_at: new Date() } }); } async function InsertFailedExportLog(socket, error) { const JobData = await getSessionData(socket.id, "JobData"); const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {}); return await client .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) .request(queries.INSERT_EXPORT_LOG, { log: { bodyshopid: JobData.bodyshop.id, jobid: JobData.id, successful: false, message: [error], useremail: socket.user.email } }); }