diff --git a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx index c38b5c642..ac18af0b5 100644 --- a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx +++ b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx @@ -1,228 +1,205 @@ -import {Table} from "antd"; -import Dinero from "dinero.js"; -import React, {useMemo} from "react"; -import {useTranslation} from "react-i18next"; +import { Table } from 'antd'; +import Dinero from 'dinero.js'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import {selectBodyshop} from "../../redux/user/user.selectors"; +import { connect } from 'react-redux'; +import { createStructuredSelector } from 'reselect'; +import { selectBodyshop } from '../../redux/user/user.selectors'; import InstanceRenderManager from '../../utils/instanceRenderMgr'; const mapStateToProps = createStructuredSelector({ - //currentUser: selectCurrentUser - bodyshop: selectBodyshop, + //currentUser: selectCurrentUser + bodyshop: selectBodyshop, }); const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) + //setUserLanguage: language => dispatch(setUserLanguage(language)) }); -export default connect( - mapStateToProps, - mapDispatchToProps -)(JobTotalsTableTotals); +export default connect(mapStateToProps, mapDispatchToProps)(JobTotalsTableTotals); -export function JobTotalsTableTotals({bodyshop, job}) { - const {t} = useTranslation(); +export function JobTotalsTableTotals({ bodyshop, job }) { + const { t } = useTranslation(); - const data = useMemo(() => { - return [ - { - key: t("jobs.labels.subtotal"), - total: job.job_totals.totals.subtotal, + const data = useMemo(() => { + return [ + { + key: t('jobs.labels.subtotal'), + total: job.job_totals.totals.subtotal, + bold: true, + }, + ...InstanceRenderManager({ + imex: [ + { + key: t('jobs.labels.local_tax_amt'), + total: job.job_totals.totals.local_tax, + }, + { + key: t('jobs.labels.state_tax_amt'), + total: job.job_totals.totals.state_tax, + }, + ...(bodyshop.region_config === 'CA_BC' + ? [ + { + key: t('jobs.fields.ca_bc_pvrt'), + total: job.job_totals.additional.pvrt, + }, + ] + : []), + { + key: t('jobs.labels.federal_tax_amt'), + total: job.job_totals.totals.federal_tax, + }, + ], + promanager: 'USE_ROME', + rome: job.job_totals.totals.us_sales_tax_breakdown + ? [ + { + key: `${bodyshop.md_responsibility_centers.taxes.tax_ty1?.tax_type1 || 'T1'} - ${[ + job.cieca_pft.ty1_rate1, + job.cieca_pft.ty1_rate2, + job.cieca_pft.ty1_rate3, + job.cieca_pft.ty1_rate4, + job.cieca_pft.ty1_rate5, + ] + .filter((i) => i > 0) + .join(', ')}%`, + total: job.job_totals.totals.us_sales_tax_breakdown.ty1Tax, + }, + { + key: `${bodyshop.md_responsibility_centers.taxes.tax_ty2?.tax_type2 || 'T2'} - ${[ + job.cieca_pft.ty2_rate1, + job.cieca_pft.ty2_rate2, + job.cieca_pft.ty2_rate3, + job.cieca_pft.ty2_rate4, + job.cieca_pft.ty2_rate5, + ] + .filter((i) => i > 0) + .join(', ')}%`, + total: job.job_totals.totals.us_sales_tax_breakdown.ty2Tax, + }, + { + key: `${bodyshop.md_responsibility_centers.taxes.tax_ty3?.tax_type3 || 'T3'} - ${[ + job.cieca_pft.ty3_rate1, + job.cieca_pft.ty3_rate2, + job.cieca_pft.ty3_rate3, + job.cieca_pft.ty3_rate4, + job.cieca_pft.ty3_rate5, + ] + .filter((i) => i > 0) + .join(', ')}%`, + total: job.job_totals.totals.us_sales_tax_breakdown.ty3Tax, + }, + { + key: `${bodyshop.md_responsibility_centers.taxes.tax_ty4?.tax_type4 || 'T4'} - ${[ + job.cieca_pft.ty4_rate1, + job.cieca_pft.ty4_rate2, + job.cieca_pft.ty4_rate3, + job.cieca_pft.ty4_rate4, + job.cieca_pft.ty4_rate5, + ] + .filter((i) => i > 0) + .join(', ')}%`, + total: job.job_totals.totals.us_sales_tax_breakdown.ty4Tax, + }, + { + key: `${bodyshop.md_responsibility_centers.taxes.tax_ty5?.tax_type5 || 'TT'} - ${[ + job.cieca_pft.ty5_rate1, + job.cieca_pft.ty5_rate2, + job.cieca_pft.ty5_rate3, + job.cieca_pft.ty5_rate4, + job.cieca_pft.ty5_rate5, + ] + .filter((i) => i > 0) + .join(', ')}%`, + total: job.job_totals.totals.us_sales_tax_breakdown.ty5Tax, + }, + { + key: t('jobs.labels.total_sales_tax'), bold: true, - }, -...InstanceRenderManager({imex: [ { - key: t("jobs.labels.local_tax_amt"), - total: job.job_totals.totals.local_tax, -}, -{ - key: t("jobs.labels.state_tax_amt"), - total: job.job_totals.totals.state_tax, -}, -...(bodyshop.region_config === "CA_BC" - ? [ - { - key: t("jobs.fields.ca_bc_pvrt"), - total: job.job_totals.additional.pvrt, - }, - ] - : []), -{ - key: t("jobs.labels.federal_tax_amt"), - total: job.job_totals.totals.federal_tax, -},], - promanager: "USE_ROME", -rome: [(job.job_totals.totals.us_sales_tax_breakdown - ? [ - { - key: `${ - bodyshop.md_responsibility_centers.taxes.tax_ty1?.tax_type1 || - "T1" - } - ${[ - job.cieca_pft.ty1_rate1, - job.cieca_pft.ty1_rate2, - job.cieca_pft.ty1_rate3, - job.cieca_pft.ty1_rate4, - job.cieca_pft.ty1_rate5, - ] - .filter((i) => i > 0) - .join(", ")}%`, - total: job.job_totals.totals.us_sales_tax_breakdown.ty1Tax, - }, - { - key: `${ - bodyshop.md_responsibility_centers.taxes.tax_ty2?.tax_type2 || - "T2" - } - ${[ - job.cieca_pft.ty2_rate1, - job.cieca_pft.ty2_rate2, - job.cieca_pft.ty2_rate3, - job.cieca_pft.ty2_rate4, - job.cieca_pft.ty2_rate5, - ] - .filter((i) => i > 0) - .join(", ")}%`, - total: job.job_totals.totals.us_sales_tax_breakdown.ty2Tax, - }, - { - key: `${ - bodyshop.md_responsibility_centers.taxes.tax_ty3?.tax_type3 || - "T3" - } - ${[ - job.cieca_pft.ty3_rate1, - job.cieca_pft.ty3_rate2, - job.cieca_pft.ty3_rate3, - job.cieca_pft.ty3_rate4, - job.cieca_pft.ty3_rate5, - ] - .filter((i) => i > 0) - .join(", ")}%`, - total: job.job_totals.totals.us_sales_tax_breakdown.ty3Tax, - }, - { - key: `${ - bodyshop.md_responsibility_centers.taxes.tax_ty4?.tax_type4 || - "T4" - } - ${[ - job.cieca_pft.ty4_rate1, - job.cieca_pft.ty4_rate2, - job.cieca_pft.ty4_rate3, - job.cieca_pft.ty4_rate4, - job.cieca_pft.ty4_rate5, - ] - .filter((i) => i > 0) - .join(", ")}%`, - total: job.job_totals.totals.us_sales_tax_breakdown.ty4Tax, - }, - { - key: `${ - bodyshop.md_responsibility_centers.taxes.tax_ty5?.tax_type5 || - "TT" - } - ${[ - job.cieca_pft.ty5_rate1, - job.cieca_pft.ty5_rate2, - job.cieca_pft.ty5_rate3, - job.cieca_pft.ty5_rate4, - job.cieca_pft.ty5_rate5, - ] - .filter((i) => i > 0) - .join(", ")}%`, - total: job.job_totals.totals.us_sales_tax_breakdown.ty5Tax, - }, - { - key: t("jobs.labels.total_sales_tax"), - bold: true, - total: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty1Tax) - .add( - Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty2Tax) - ) - .add( - Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty3Tax) - ) - .add( - Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty4Tax) - ) - .add( - Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty5Tax) - ).toJSON(), - }, - ].filter((item) => item.total.amount !== 0) - : [ - { - key: t("jobs.labels.state_tax_amt"), - total: job.job_totals.totals.state_tax, - }, - ])] -}), - + total: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty1Tax) + .add(Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty2Tax)) + .add(Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty3Tax)) + .add(Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty4Tax)) + .add(Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty5Tax)) + .toJSON(), + }, + ].filter((item) => item.total.amount !== 0) + : [ + { + key: t('jobs.labels.state_tax_amt'), + total: job.job_totals.totals.state_tax, + }, + ], + }), - { - key: t("jobs.labels.total_repairs"), - total: job.job_totals.totals.total_repairs, - bold: true, - }, - { - key: t("jobs.fields.ded_amt"), - total: job.job_totals.totals.custPayable.deductible, - }, - // { - // key: t("jobs.fields.federal_tax_payable"), - // total: job.job_totals.totals.custPayable.federal_tax, - // }, - { - key: t("jobs.fields.other_amount_payable"), - total: job.job_totals.totals.custPayable.other_customer_amount, - }, - { - key: t("jobs.fields.depreciation_taxes"), - total: job.job_totals.totals.custPayable.dep_taxes, - }, + { + key: t('jobs.labels.total_repairs'), + total: job.job_totals.totals.total_repairs, + bold: true, + }, + { + key: t('jobs.fields.ded_amt'), + total: job.job_totals.totals.custPayable.deductible, + }, + // { + // key: t("jobs.fields.federal_tax_payable"), + // total: job.job_totals.totals.custPayable.federal_tax, + // }, + { + key: t('jobs.fields.other_amount_payable'), + total: job.job_totals.totals.custPayable.other_customer_amount, + }, + { + key: t('jobs.fields.depreciation_taxes'), + total: job.job_totals.totals.custPayable.dep_taxes, + }, - { - key: t("jobs.labels.total_cust_payable"), - total: job.job_totals.totals.custPayable.total, - bold: true, - }, - { - key: t("jobs.labels.net_repairs"), - total: job.job_totals.totals.net_repairs, - bold: true, - }, - ]; - }, [job.job_totals, job.cieca_pft, t, bodyshop.md_responsibility_centers]); - - const columns = [ - { - //title: t("joblines.fields.part_type"), - dataIndex: "key", - key: "key", - width: "80%", - onCell: (record, rowIndex) => { - return {style: {fontWeight: record.bold && "bold"}}; - }, - }, - { - title: t("joblines.fields.total"), - dataIndex: "total", - key: "total", - align: "right", - render: (text, record) => Dinero(record.total).toFormat(), - width: "20%", - onCell: (record, rowIndex) => { - return {style: {fontWeight: record.bold && "bold"}}; - }, - }, + { + key: t('jobs.labels.total_cust_payable'), + total: job.job_totals.totals.custPayable.total, + bold: true, + }, + { + key: t('jobs.labels.net_repairs'), + total: job.job_totals.totals.net_repairs, + bold: true, + }, ]; + }, [job.job_totals, job.cieca_pft, t, bodyshop.md_responsibility_centers]); - return ( - - ); + const columns = [ + { + //title: t("joblines.fields.part_type"), + dataIndex: 'key', + key: 'key', + width: '80%', + onCell: (record, rowIndex) => { + return { style: { fontWeight: record.bold && 'bold' } }; + }, + }, + { + title: t('joblines.fields.total'), + dataIndex: 'total', + key: 'total', + align: 'right', + render: (text, record) => Dinero(record.total).toFormat(), + width: '20%', + onCell: (record, rowIndex) => { + return { style: { fontWeight: record.bold && 'bold' } }; + }, + }, + ]; + + return ( +
+ ); } diff --git a/client/src/components/jobs-available-table/jobs-available-table.container.jsx b/client/src/components/jobs-available-table/jobs-available-table.container.jsx index 5b801c045..d0177354f 100644 --- a/client/src/components/jobs-available-table/jobs-available-table.container.jsx +++ b/client/src/components/jobs-available-table/jobs-available-table.container.jsx @@ -600,11 +600,12 @@ async function CheckTaxRates(estData, bodyshop) { estData.joblines.data.forEach((line) => { if (line.misc_amt && line.misc_amt !== 0) { line.act_price = line.act_price + line.misc_amt; - line.tax_part = !!line.misc_tax; + line.tax_part = !!line.misc_tax; + line.notes += ` | Misc amount override.`; + } //WEB EST SPECIFIC CLEAN UP InstanceRenderManager({executeFunction: true, args:[], promanager: () => { - if (line.mod_lbr_ty === "LAET" || line.mod_lbr_ty === "LAUT") { line.notes += ` | ET/UT Update (prev = ${line.mod_lbr_ty})`; line.mod_lbr_ty = "LAR"; @@ -615,52 +616,65 @@ async function CheckTaxRates(estData, bodyshop) { //Group by line no // For everything but the first one, strip out the price number in - InstanceRenderManager({executeFunction:true, args:[], promanager: () => { - - - - const groupedByLineRef = _.groupBy(estData.joblines.data, "line_ref"); - Object.keys(groupedByLineRef).forEach((lineRef) => { - groupedByLineRef[lineRef].forEach((line, index) => { - //Let the first one keep it - if (index === 0) return; - //Web Est seems to have additional costs with UNQ_SEQ 0. Keep them all? - if (line.unq_seq === 0) return; - const indexInEstData = estData.joblines.data.findIndex( - (l) => l.unq_seq === line.unq_seq - ); - estData.joblines.data[ - indexInEstData - ].notes += ` | Scrubbed due to the line_ref issue. (prev act price = ${estData.joblines.data[indexInEstData].act_price})`; - estData.joblines.data[indexInEstData].act_price = 0; - estData.joblines.data[indexInEstData].db_price = 0; - }); - }) - }}) + // InstanceRenderManager({executeFunction:true, args:[], promanager: () => { + // const groupedByLineRef = _.groupBy(estData.joblines.data, "line_ref"); + // Object.keys(groupedByLineRef).forEach((lineRef) => { + // let index0ActPrice; + // groupedByLineRef[lineRef].forEach((line, index) => { + // //Let the first one keep it + // if (index === 0){ + // index0ActPrice = line.act_price; + // return;} + // //Web Est seems to have additional costs with UNQ_SEQ 0. Keep them all? + // if (line.unq_seq === 0) return; + // if(index0ActPrice !== line.act_price){ + // line.notes += ` | Price override.`; + // return; + // } + // const indexInEstData = estData.joblines.data.findIndex( + // (l) => l.unq_seq === line.unq_seq + // ); + // estData.joblines.data[ + // indexInEstData + // ].notes += ` | Scrubbed due to the line_ref issue. (prev act price = ${estData.joblines.data[indexInEstData].act_price})`; + // estData.joblines.data[indexInEstData].act_price = 0; + // estData.joblines.data[indexInEstData].db_price = 0; + // }); + // }) + // }}) +InstanceRenderManager({ + executeFunction: true, + args: [], + promanager: null, //Require to prevent auto firing of Rome. + rome: () => { //Generate the list of duplicated UNQ_SEQ that will feed into the next section to scrub the lines. - const unqSeqHash = _.groupBy(estData.joblines.data, "unq_seq"); - const duplicatedUnqSeq = Object.keys(unqSeqHash).filter( - (key) => unqSeqHash[key].length > 1 - ); + const unqSeqHash = _.groupBy(estData.joblines.data, 'unq_seq'); + const duplicatedUnqSeq = Object.keys(unqSeqHash).filter((key) => unqSeqHash[key].length > 1); duplicatedUnqSeq.forEach((unq_seq) => { - //Keys are strings, convert to int. - const int_unq_seq = parseInt(unq_seq); + //Keys are strings, convert to int. + const int_unq_seq = parseInt(unq_seq); - //When line splitting, the first line is always the non-refinish line. We will keep it as is. - //We will cleanse the second line, which is always the next line. - const nonRefLineIndex = estData.joblines.data.findIndex( - (line) => line.unq_seq === int_unq_seq - ); - estData.joblines.data[nonRefLineIndex + 1] = { - ...estData.joblines.data[nonRefLineIndex + 1], - part_type: null, - act_price: 0, - db_price: 0, - prt_dsmk_p: 0, - prt_dsmk_m: 0, - }; + //When line splitting, the first line is always the non-refinish line. We will keep it as is. + //We will cleanse the second line, which is always the next line. + const nonRefLineIndex = estData.joblines.data.findIndex( + (line) => line.unq_seq === int_unq_seq + ); + estData.joblines.data[nonRefLineIndex + 1] = { + ...estData.joblines.data[nonRefLineIndex + 1], + part_type: null, + act_price: 0, + db_price: 0, + prt_dsmk_p: 0, + prt_dsmk_m: 0, + }; }); + }, +}); + + + + } diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index f13ce3546..b8b7f75b5 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -3,6 +3,7 @@ const queries = require("../graphql-client/queries"); const adminClient = require("../graphql-client/graphql-client").client; const _ = require("lodash"); const logger = require("../utils/logger"); +const InstanceMgr = require("../utils/instanceMgr").default; //****************************************************** */ //****************************************************** */ @@ -992,7 +993,7 @@ function CalculateTaxesTotals(job, otherTotals) { ); let taxableAmountInThisThreshold; - if (thresholdAmount === 9999.99) { + if (thresholdAmount === 9999.99 || InstanceMgr({debug:true,imex:false, rome: false, promanager:thresholdAmount === 0 && parseInt(tyCounter) === 1 }) ) { // // THis is the last threshold. Tax the entire remaining amount. taxableAmountInThisThreshold = remainingTaxableAmounts[taxTierKey]; remainingTaxableAmounts[taxTierKey] = Dinero();