From 79124daa9a8ada0886354b9e3fa0a081017a2481 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 1 Mar 2022 13:14:03 -0800 Subject: [PATCH 1/5] IO-1719 Add invoice number to job line --- .../job-lines-bill-reference.component.jsx | 2 +- client/src/graphql/jobs.queries.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/components/job-lines-bill-reference/job-lines-bill-reference.component.jsx b/client/src/components/job-lines-bill-reference/job-lines-bill-reference.component.jsx index 84b43e9ab..7866d88fa 100644 --- a/client/src/components/job-lines-bill-reference/job-lines-bill-reference.component.jsx +++ b/client/src/components/job-lines-bill-reference/job-lines-bill-reference.component.jsx @@ -10,7 +10,7 @@ export default function JobLinesBillRefernece({ jobline }) { {subletRequired && } {`${(billLine.actual_price * billLine.quantity).toFixed(2)} (${ billLine.bill.vendor.name - })`} + } #${billLine.bill.invoice_number})`} ); } diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 9d0641d8a..c2b60a88c 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -696,6 +696,7 @@ export const GET_JOB_BY_PK = gql` joblineid bill { id + invoice_number vendor { id name From 0cd1b41ed94d6f85d56d1453405ebaf15fe8d329 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 1 Mar 2022 13:24:07 -0800 Subject: [PATCH 2/5] IO-1728 Remove unsaved changes popup when creating CC --- .../courtesy-car-form/courtesy-car-form.component.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx index e9486afa9..f994f25dc 100644 --- a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx +++ b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx @@ -9,7 +9,7 @@ import { DateFormatter } from "../../utils/DateFormatter"; import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component"; import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component"; import FormDatePicker from "../form-date-picker/form-date-picker.component"; -import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component"; +//import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; @@ -32,7 +32,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) { } /> - + {/* */} Date: Tue, 1 Mar 2022 14:53:42 -0800 Subject: [PATCH 3/5] IO-1745 Resolve scheduling showing incorrect days. --- server/scheduling/scheduling-job.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/server/scheduling/scheduling-job.js b/server/scheduling/scheduling-job.js index 24b5577b0..95091e8e7 100644 --- a/server/scheduling/scheduling-job.js +++ b/server/scheduling/scheduling-job.js @@ -111,10 +111,9 @@ exports.job = async (req, res) => { } if ( - moment(item.actual_completion || item.scheduled_completion).tz(timezone).isBefore( - moment().tz(timezone), - "day" - ) + moment(item.actual_completion || item.scheduled_completion) + .tz(timezone) + .isBefore(moment().tz(timezone), "day") ) { console.log("Job should have already gone. Ignoring it.", item); return; @@ -128,7 +127,9 @@ exports.job = async (req, res) => { } else { const itemDate = moment( item.actual_completion || item.scheduled_completion - ).tz(timezone).format("yyyy-MM-DD"); + ) + .tz(timezone) + .format("yyyy-MM-DD"); if (!!load[itemDate]) { load[itemDate].hoursOut = (load[itemDate].hoursOut || 0) + @@ -153,14 +154,20 @@ exports.job = async (req, res) => { const end = moment.max([ ...filteredArrJobs.map((a) => moment(a.scheduled_in).tz(timezone)), ...filteredCompJobs - .map((p) => moment(p.actual_completion || p.scheduled_completion).tz(timezone)) + .map((p) => + moment(p.actual_completion || p.scheduled_completion).tz(timezone) + ) .filter((p) => p.isValid() && p.isAfter(yesterday)), moment().tz(timezone).add(15, "days"), ]); const range = Math.round(moment.duration(end.diff(today)).asDays()); for (var day = 0; day < range; day++) { - const current = moment(today).tz(timezone).add(day, "days").format("yyyy-MM-DD"); - const prev = moment(today).tz(timezone) + const current = moment(today) + .tz(timezone) + .add(day, "days") + .format("yyyy-MM-DD"); + const prev = moment(today) + .tz(timezone) .add(day - 1, "days") .format("yyyy-MM-DD"); if (!!!load[current]) { @@ -204,7 +211,7 @@ exports.job = async (req, res) => { loadKeys.forEach((loadKey) => { const isShopOpen = - (workingdays[dayOfWeekMapper(moment(loadKey).tz(timezone).day())] || false) && + (workingdays[dayOfWeekMapper(moment(loadKey).day())] || false) && !load[loadKey].blocked; if ( From 63ec578b6a9d158796782aabad4c782d63e28591 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 1 Mar 2022 15:17:33 -0800 Subject: [PATCH 4/5] IO-1749 Inactive employees removed from drop downs. --- .../job-employee-assignments.component.jsx | 20 ++++++++++--------- ...n-list-columns.empassignment.component.jsx | 20 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx b/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx index 954d04970..6cfdc8307 100644 --- a/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx +++ b/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx @@ -55,15 +55,17 @@ export function JobEmployeeAssignments({ 0 } > - {bodyshop.employees.map((emp) => ( - - {`${emp.first_name} ${emp.last_name}`} - - ))} + {bodyshop.employees + .filter((emp) => emp.active) + .map((emp) => ( + + {`${emp.first_name} ${emp.last_name}`} + + ))} diff --git a/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx b/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx index 606867975..e2ed28896 100644 --- a/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx @@ -116,15 +116,17 @@ export function ProductionListEmpAssignment({ 0 } > - {bodyshop.employees.map((emp) => ( - - {`${emp.first_name} ${emp.last_name}`} - - ))} + {bodyshop.employees + .filter((emp) => emp.active) + .map((emp) => ( + + {`${emp.first_name} ${emp.last_name}`} + + ))} From 0660b79c01fa914b1852b0dd47bd3ccf0153d99f Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 1 Mar 2022 17:27:04 -0800 Subject: [PATCH 5/5] Autohouse Extract Updates & Remove duedate on payables. --- server/accounting/qbo/qbo-payables.js | 13 ++++---- server/accounting/qbxml/qbxml-payables.js | 13 ++++---- server/data/autohouse.js | 37 +++++++++++++++++++---- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js index b7bddd1a7..20f68441e 100644 --- a/server/accounting/qbo/qbo-payables.js +++ b/server/accounting/qbo/qbo-payables.js @@ -181,12 +181,13 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) { TxnDate: moment(bill.date) //.tz(bill.job.bodyshop.timezone) .format("YYYY-MM-DD"), - ...(bill.vendor.due_date && { - DueDate: moment(bill.date) - //.tz(bill.job.bodyshop.timezone) - .add(bill.vendor.due_date, "days") - .format("YYYY-MM-DD"), - }), + ...(!bill.is_credit_memo && + bill.vendor.due_date && { + DueDate: moment(bill.date) + //.tz(bill.job.bodyshop.timezone) + .add(bill.vendor.due_date, "days") + .format("YYYY-MM-DD"), + }), DocNumber: bill.invoice_number, //...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}), diff --git a/server/accounting/qbxml/qbxml-payables.js b/server/accounting/qbxml/qbxml-payables.js index 07d426da7..28e7ba2cd 100644 --- a/server/accounting/qbxml/qbxml-payables.js +++ b/server/accounting/qbxml/qbxml-payables.js @@ -75,12 +75,13 @@ const generateBill = (bill) => { TxnDate: moment(bill.date) //.tz(bill.job.bodyshop.timezone) .format("YYYY-MM-DD"), - ...(bill.vendor.due_date && { - DueDate: moment(bill.date) - // .tz(bill.job.bodyshop.timezone) - .add(bill.vendor.due_date, "days") - .format("YYYY-MM-DD"), - }), + ...(!bill.is_credit_memo && + bill.vendor.due_date && { + DueDate: moment(bill.date) + // .tz(bill.job.bodyshop.timezone) + .add(bill.vendor.due_date, "days") + .format("YYYY-MM-DD"), + }), RefNumber: bill.invoice_number, Memo: `RO ${bill.job.ro_number || ""}`, ExpenseLineAdd: bill.billlines.map((il) => diff --git a/server/data/autohouse.js b/server/data/autohouse.js index 1cba662d6..46b4e2d6d 100644 --- a/server/data/autohouse.js +++ b/server/data/autohouse.js @@ -214,7 +214,7 @@ const CreateRepairOrderTag = (job, errorCallback) => { Street: job.ownr_addr1 || "", City: job.ownr_city || "", State: job.ownr_st || "", - Zip: job.ownr_zip || "", + Zip: (job.ownr_zip && job.ownr_zip.substring(0, 3)) || "", Phone1: job.ownr_ph1 || "", Phone2: null, Phone2Extension: null, @@ -488,8 +488,8 @@ const CreateRepairOrderTag = (job, errorCallback) => { PartsReconditionedCost: repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat), PartsRecycled: Dinero( - job.job_totals.parts.parts.list.PAR && - job.job_totals.parts.parts.list.PAR.total + job.job_totals.parts.parts.list.PAL && + job.job_totals.parts.parts.list.PAL.total ).toFormat(AHDineroFormat), PartsRecycledCost: repairCosts.PartsRecycledCost.toFormat(AHDineroFormat), @@ -555,7 +555,9 @@ const CreateRepairOrderTag = (job, errorCallback) => { AHDineroFormat ), BMTotalCost: repairCosts.BMTotalCost.toFormat(AHDineroFormat), - MiscTotal: 0, + MiscTotal: Dinero(job.job_totals.additional.additionalCosts).toFormat( + AHDineroFormat + ), MiscTotalCost: 0, TowingTotal: Dinero(job.job_totals.additional.towing).toFormat( AHDineroFormat @@ -673,7 +675,7 @@ const CreateCosts = (job) => { }); return bill_acc; }, {}); - const materialsHours = { mapaHrs: 0, mashHrs: 0 }; + //If the hourly rates for job costing are set, add them in. if (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mapa) { if ( @@ -694,9 +696,32 @@ const CreateCosts = (job) => { (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mapa * 100) || 0, - }).multiply(materialsHours.mapaHrs) + }).multiply(job.job_totals.rates.mapa.hours) ); } + if (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mash) { + if ( + !billTotalsByCostCenters[ + job.bodyshop.md_responsibility_centers.defaults.costs.MASH + ] + ) + billTotalsByCostCenters[ + job.bodyshop.md_responsibility_centers.defaults.costs.MASH + ] = Dinero(); + billTotalsByCostCenters[ + job.bodyshop.md_responsibility_centers.defaults.costs.MASH + ] = billTotalsByCostCenters[ + job.bodyshop.md_responsibility_centers.defaults.costs.MASH + ].add( + Dinero({ + amount: + (job.bodyshop.jc_hourly_rates && + job.bodyshop.jc_hourly_rates.mash * 100) || + 0, + }).multiply(job.job_totals.rates.mash.hours) + ); + } + const ticketTotalsByCostCenter = job.timetickets.reduce( (ticket_acc, ticket_val) => { //At the invoice level.