diff --git a/client/src/components/job-costing-modal/job-costing-modal.container.jsx b/client/src/components/job-costing-modal/job-costing-modal.container.jsx index cef43bfd0..fd15d6345 100644 --- a/client/src/components/job-costing-modal/job-costing-modal.container.jsx +++ b/client/src/components/job-costing-modal/job-costing-modal.container.jsx @@ -26,11 +26,6 @@ export function JobCostingModalContainer({ const { visible, context } = jobCostingModal; const { jobId } = context; - // const { loading, error, data } = useQuery(QUERY_JOB_COSTING_DETAILS, { - // variables: { id: jobId }, - // skip: !jobId, - // }); - useEffect(() => { async function getData() { if (jobId && visible) { @@ -46,8 +41,14 @@ export function JobCostingModalContainer({ toggleModalVisible()} - onCancel={() => toggleModalVisible()} + onOk={() => { + toggleModalVisible(); + setCostingData(null); + }} + onCancel={() => { + toggleModalVisible(); + setCostingData(null); + }} cancelButtonProps={{ style: { display: "none" } }} width="90%" destroyOnClose diff --git a/client/src/components/job-costing-statistics/job-costing-statistics.component.jsx b/client/src/components/job-costing-statistics/job-costing-statistics.component.jsx index d63a60149..fe73a76ac 100644 --- a/client/src/components/job-costing-statistics/job-costing-statistics.component.jsx +++ b/client/src/components/job-costing-statistics/job-costing-statistics.component.jsx @@ -16,6 +16,10 @@ export default function JobCostingStatistics({ summaryData }) { value={Dinero(summaryData.totalPartsSales).toFormat()} title={t("jobs.labels.sale_parts")} /> + + 0 ? 1 : -1) ); - if (!acc.parts[partsProfitCenter]) - acc.parts[partsProfitCenter] = Dinero(); - acc.parts[partsProfitCenter] = - acc.parts[partsProfitCenter].add(partsAmount); + if (!acc.additional[partsProfitCenter]) + acc.additional[partsProfitCenter] = Dinero(); + acc.additional[partsProfitCenter] = + acc.additional[partsProfitCenter].add(partsAmount); } } return acc; }, - { parts: {}, labor: {} } + { parts: {}, labor: {}, additional: {} } ); if (!hasMapaLine) { - if (!jobLineTotalsByProfitCenter.parts[defaultProfits["MAPA"]]) - jobLineTotalsByProfitCenter.parts[defaultProfits["MAPA"]] = Dinero(); - jobLineTotalsByProfitCenter.parts[defaultProfits["MAPA"]] = - jobLineTotalsByProfitCenter.parts[defaultProfits["MAPA"]].add( + if (!jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]]) + jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = Dinero(); + jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = + jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]].add( Dinero({ amount: Math.round((job.rate_mapa || 0) * 100), }).multiply(materialsHours.mapaHrs || 0) ); } if (!hasMashLine) { - if (!jobLineTotalsByProfitCenter.parts[defaultProfits["MASH"]]) - jobLineTotalsByProfitCenter.parts[defaultProfits["MASH"]] = Dinero(); - jobLineTotalsByProfitCenter.parts[defaultProfits["MASH"]] = - jobLineTotalsByProfitCenter.parts[defaultProfits["MASH"]].add( + if (!jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]]) + jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]] = Dinero(); + jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]] = + jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]].add( Dinero({ amount: Math.round((job.rate_mash || 0) * 100), }).multiply(materialsHours.mashHrs || 0) @@ -381,54 +401,88 @@ function GenerateCostingData(job) { )) || job.bodyshop.md_responsibility_centers.defaults; - const billTotalsByCostCenters = job.bills.reduce((bill_acc, bill_val) => { - //At the bill level. - bill_val.billlines.map((line_val) => { - //At the bill line level. - if (job.bodyshop.pbs_serialnumber || job.bodyshop.cdk_dealerid) { - if (!bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]]) + const billTotalsByCostCenters = job.bills.reduce( + (bill_acc, bill_val) => { + //At the bill level. + bill_val.billlines.map((line_val) => { + //At the bill line level. + if (job.bodyshop.pbs_serialnumber || job.bodyshop.cdk_dealerid) { + if ( + !bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] + ) + bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] = + Dinero(); + bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] = - Dinero(); + bill_acc[ + selectedDmsAllocationConfig.costs[line_val.cost_center] + ].add( + Dinero({ + amount: Math.round((line_val.actual_cost || 0) * 100), + }) + .multiply(line_val.quantity) + .multiply(bill_val.is_credit_memo ? -1 : 1) + ); + } else { + const isAdditionalCostCenter = + // line_val.cost_center === + // job.bodyshop.md_responsibility_centers.defaults.costs.PAS || + // line_val.cost_center === + // job.bodyshop.md_responsibility_centers.defaults.costs.PASL || + line_val.cost_center === + job.bodyshop.md_responsibility_centers.defaults.costs.TOW || + line_val.cost_center === + job.bodyshop.md_responsibility_centers.defaults.costs.MAPA || + line_val.cost_center === + job.bodyshop.md_responsibility_centers.defaults.costs.MASH; - bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] = - bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]].add( - Dinero({ - amount: Math.round((line_val.actual_cost || 0) * 100), - }) - .multiply(line_val.quantity) - .multiply(bill_val.is_credit_memo ? -1 : 1) - ); - } else { - if (!bill_acc[line_val.cost_center]) - bill_acc[line_val.cost_center] = Dinero(); + if (isAdditionalCostCenter) { + if (!bill_acc.additionalCosts[line_val.cost_center]) + bill_acc.additionalCosts[line_val.cost_center] = Dinero(); - bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add( - Dinero({ - amount: Math.round((line_val.actual_cost || 0) * 100), - }) - .multiply(line_val.quantity) - .multiply(bill_val.is_credit_memo ? -1 : 1) - ); - } + bill_acc.additionalCosts[line_val.cost_center] = + bill_acc.additionalCosts[line_val.cost_center].add( + Dinero({ + amount: Math.round((line_val.actual_cost || 0) * 100), + }) + .multiply(line_val.quantity) + .multiply(bill_val.is_credit_memo ? -1 : 1) + ); + } else { + if (!bill_acc[line_val.cost_center]) + bill_acc[line_val.cost_center] = Dinero(); - return null; - }); - return bill_acc; - }, {}); + bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add( + Dinero({ + amount: Math.round((line_val.actual_cost || 0) * 100), + }) + .multiply(line_val.quantity) + .multiply(bill_val.is_credit_memo ? -1 : 1) + ); + } + } + + return null; + }); + return bill_acc; + }, + { additionalCosts: {} } + ); //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 ( - !billTotalsByCostCenters[ + !billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MAPA ] ) - billTotalsByCostCenters[ + billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MAPA ] = Dinero(); - billTotalsByCostCenters[ + billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MAPA - ] = billTotalsByCostCenters[ + ] = billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MAPA ].add( Dinero({ @@ -442,16 +496,16 @@ function GenerateCostingData(job) { if (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mash) { if ( - !billTotalsByCostCenters[ + !billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MASH ] ) - billTotalsByCostCenters[ + billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MASH ] = Dinero(); - billTotalsByCostCenters[ + billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MASH - ] = billTotalsByCostCenters[ + ] = billTotalsByCostCenters.additionalCosts[ job.bodyshop.md_responsibility_centers.defaults.costs.MASH ].add( Dinero({ @@ -511,9 +565,11 @@ function GenerateCostingData(job) { const summaryData = { totalLaborSales: Dinero({ amount: 0 }), totalPartsSales: Dinero({ amount: 0 }), + totalAdditionalSales: Dinero({ amount: 0 }), totalSales: Dinero({ amount: 0 }), totalLaborCost: Dinero({ amount: 0 }), totalPartsCost: Dinero({ amount: 0 }), + totalAdditionalCost: Dinero({ amount: 0 }), totalCost: Dinero({ amount: 0 }), totalLaborGp: Dinero({ amount: 0 }), totalPartsGp: Dinero({ amount: 0 }), @@ -533,14 +589,16 @@ function GenerateCostingData(job) { jobLineTotalsByProfitCenter.labor[ccVal] || Dinero({ amount: 0 }); const sale_parts = jobLineTotalsByProfitCenter.parts[ccVal] || Dinero({ amount: 0 }); + const sale_additional = + jobLineTotalsByProfitCenter.additional[ccVal] || Dinero({ amount: 0 }); const cost_labor = ticketTotalsByCostCenter[ccVal] || Dinero({ amount: 0 }); const cost_parts = billTotalsByCostCenters[ccVal] || Dinero({ amount: 0 }); + const cost_additional = + billTotalsByCostCenters.additionalCosts[ccVal] || Dinero({ amount: 0 }); - const costs = (billTotalsByCostCenters[ccVal] || Dinero({ amount: 0 })).add( - ticketTotalsByCostCenter[ccVal] || Dinero({ amount: 0 }) - ); - const totalSales = sale_labor.add(sale_parts); + const costs = cost_labor.add(cost_parts).add(cost_additional); + const totalSales = sale_labor.add(sale_parts).add(sale_additional); const gpdollars = totalSales.subtract(costs); const gppercent = ( (gpdollars.getAmount() / totalSales.getAmount()) * @@ -550,11 +608,13 @@ function GenerateCostingData(job) { //Push summary data to avoid extra loop. summaryData.totalLaborSales = summaryData.totalLaborSales.add(sale_labor); summaryData.totalPartsSales = summaryData.totalPartsSales.add(sale_parts); - summaryData.totalSales = summaryData.totalSales - .add(sale_labor) - .add(sale_parts); + summaryData.totalAdditionalSales = + summaryData.totalAdditionalSales.add(sale_additional); + summaryData.totalSales = summaryData.totalSales.add(totalSales); summaryData.totalLaborCost = summaryData.totalLaborCost.add(cost_labor); summaryData.totalPartsCost = summaryData.totalPartsCost.add(cost_parts); + summaryData.totalAdditionalCost = + summaryData.totalAdditionalCost.add(cost_additional); summaryData.totalCost = summaryData.totalCost.add(costs); return { @@ -564,14 +624,18 @@ function GenerateCostingData(job) { sale_labor_dinero: sale_labor, sale_parts: sale_parts && sale_parts.toFormat(), sale_parts_dinero: sale_parts, - sales: sale_labor.add(sale_parts).toFormat(), - sales_dinero: sale_labor.add(sale_parts), + sale_additional: sale_additional && sale_additional.toFormat(), + sale_additional_dinero: sale_additional, + sales: totalSales.toFormat(), + sales_dinero: totalSales, cost_parts: cost_parts && cost_parts.toFormat(), cost_parts_dinero: cost_parts, cost_labor: cost_labor && cost_labor.toFormat(), cost_labor_dinero: cost_labor, - costs: cost_parts.add(cost_labor).toFormat(), - costs_dinero: cost_parts.add(cost_labor), + cost_additional: cost_additional && cost_additional.toFormat(), + cost_additional_dinero: cost_additional, + costs: costs.toFormat(), + costs_dinero: costs, gpdollars_dinero: gpdollars, gpdollars: gpdollars.toFormat(), gppercent: formatGpPercent(gppercent),