From 8fcb488b3bb61efa543be010f27dacec5d9523e4 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 2 Feb 2021 09:32:49 -0800 Subject: [PATCH] CC Conversion Corrections IO-463 --- .../contract-convert-to-ro.component.jsx | 68 +++++++++++++++---- .../job-totals-table/job-totals.utility.js | 4 +- .../contract-detail.page.component.jsx | 63 ++++++++++------- .../contract-detail.page.container.jsx | 7 +- .../courtesy-car-create.page.container.jsx | 8 ++- .../1612286825846_run_sql_migration/down.yaml | 1 + .../1612286825846_run_sql_migration/up.yaml | 7 ++ server/job/job-totals.js | 14 ++-- 8 files changed, 123 insertions(+), 49 deletions(-) create mode 100644 hasura/migrations/1612286825846_run_sql_migration/down.yaml create mode 100644 hasura/migrations/1612286825846_run_sql_migration/up.yaml diff --git a/client/src/components/contract-convert-to-ro/contract-convert-to-ro.component.jsx b/client/src/components/contract-convert-to-ro/contract-convert-to-ro.component.jsx index cf580bff5..ebecdf496 100644 --- a/client/src/components/contract-convert-to-ro/contract-convert-to-ro.component.jsx +++ b/client/src/components/contract-convert-to-ro/contract-convert-to-ro.component.jsx @@ -1,5 +1,13 @@ import React, { useState } from "react"; -import { Button, notification, Popover, Radio, Form, InputNumber } from "antd"; +import { + Button, + notification, + Popover, + Radio, + Form, + InputNumber, + Space, +} from "antd"; import { useTranslation } from "react-i18next"; import { useMutation } from "react-apollo"; import { INSERT_NEW_JOB } from "../../graphql/jobs.queries"; @@ -11,6 +19,8 @@ import { selectCurrentUser, } from "../../redux/user/user.selectors"; import { useHistory } from "react-router-dom"; +import axios from "axios"; + const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -20,7 +30,12 @@ const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); -export function ContractConvertToRo({ bodyshop, currentUser, contract }) { +export function ContractConvertToRo({ + bodyshop, + currentUser, + contract, + disabled, +}) { const { t } = useTranslation(); const [visible, setVisible] = useState(false); const [loading, setLoading] = useState(false); @@ -46,6 +61,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { part_type: "CCDR", tax_part: true, mod_lb_hrs: 0, + db_ref: "io-ccdr", // mod_lbr_ty: "PAL", }, ]; @@ -63,6 +79,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { part_type: "CCM", part_qty: mileageDiff, tax_part: true, + db_ref: "io-ccm", mod_lb_hrs: 0, }); } @@ -78,6 +95,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { part_qty: values.refuelqty, part_type: "CCF", tax_part: true, + db_ref: "io-ccf", mod_lb_hrs: 0, }); } @@ -92,6 +110,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { part_qty: 1, part_type: "CCC", tax_part: true, + db_ref: "io-ccc", mod_lb_hrs: 0, }); } @@ -107,6 +126,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { part_type: "CCD", part_qty: 1, tax_part: true, + db_ref: "io-ccd", mod_lb_hrs: 0, }); } @@ -119,8 +139,8 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { federal_tax_rate: bodyshop.bill_tax_rates.federal_tax_rate / 100, state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate / 100, local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate / 100, + converted: true, clm_no: `${contract.job.clm_no}-CC`, - clm_total: 1234, ownr_fn: contract.job.owner.ownr_fn, ownr_ln: contract.job.owner.ownr_ln, ownr_co_nm: contract.job.owner.ownr_co_nm, @@ -151,7 +171,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { prt_mktyp: false, prt_mkupp: 0, prt_tax_in: true, - prt_tax_rt: 0.07, + prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100, }, CCF: { prt_type: "CCF", @@ -159,7 +179,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { prt_mktyp: false, prt_mkupp: 0, prt_tax_in: true, - prt_tax_rt: 0.07, + prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100, }, CCM: { prt_type: "CCM", @@ -167,7 +187,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { prt_mktyp: false, prt_mkupp: 0, prt_tax_in: true, - prt_tax_rt: 0.07, + prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100, }, CCC: { prt_type: "CCC", @@ -175,7 +195,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { prt_mktyp: false, prt_mkupp: 0, prt_tax_in: true, - prt_tax_rt: 0.07, + prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100, }, CCD: { prt_type: "CCD", @@ -183,10 +203,22 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { prt_mktyp: false, prt_mkupp: 0, prt_tax_in: true, - prt_tax_rt: 0.07, + prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100, }, }, }; + + //Calcualte the new job totals. + + const newTotals = ( + await axios.post("/job/totals", { + job: { ...newJob, joblines: billingLines }, + }) + ).data; + + newJob.clm_total = newTotals.totals.total_repairs.amount / 100; + newJob.job_totals = newTotals; + const result = await insertJob({ variables: { job: [newJob] }, // refetchQueries: ["GET_JOB_BY_PK"], @@ -244,12 +276,14 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { > - - + + + + ); @@ -257,7 +291,11 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) { return (
- diff --git a/client/src/components/job-totals-table/job-totals.utility.js b/client/src/components/job-totals-table/job-totals.utility.js index ee9c0ce98..f1ee73cdf 100644 --- a/client/src/components/job-totals-table/job-totals.utility.js +++ b/client/src/components/job-totals-table/job-totals.utility.js @@ -253,13 +253,13 @@ // total: acc.parts.list[value.part_type].total.add( // Dinero({ // amount: Math.round((value.act_price || 0) * 100), -// }).multiply(value.part_qty || 1) +// }).multiply(value.part_qty || 0) // ), // } // : { // total: Dinero({ // amount: Math.round((value.act_price || 0) * 100), -// }).multiply(value.part_qty || 1), +// }).multiply(value.part_qty || 0), // }, // }, // subtotal: acc.parts.subtotal.add( diff --git a/client/src/pages/contract-detail/contract-detail.page.component.jsx b/client/src/pages/contract-detail/contract-detail.page.component.jsx index 0e4665c00..558b8ef74 100644 --- a/client/src/pages/contract-detail/contract-detail.page.component.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.component.jsx @@ -1,12 +1,12 @@ -import { Button, Typography, Row, Col } from "antd"; +import { Button, Col, Row, Space, Typography, Form } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; +import ContractConvertToRo from "../../components/contract-convert-to-ro/contract-convert-to-ro.component"; import ContractCourtesyCarBlock from "../../components/contract-courtesy-car-block/contract-courtesy-car-block.component"; import ContractFormComponent from "../../components/contract-form/contract-form.component"; import ContractJobBlock from "../../components/contract-job-block/contract-job-block.component"; import { setModalContext } from "../../redux/modals/modals.actions"; -import ContractConvertToRo from "../../components/contract-convert-to-ro/contract-convert-to-ro.component"; const mapDispatchToProps = (dispatch) => ({ setCourtesyCarReturnModalContext: (context) => @@ -20,6 +20,7 @@ export function ContractDetailPage({ setCourtesyCarReturnModalContext, refetch, form, + saveLoading, }) { const { t } = useTranslation(); return ( @@ -28,27 +29,6 @@ export function ContractDetailPage({ {`Agreement ${ (contract && contract.agreementnumber) || "" } - ${t((contract && contract.status) || "")}`} - - - @@ -57,6 +37,43 @@ export function ContractDetailPage({ + + {() => { + return ( + + + + + + + ); + }} + diff --git a/client/src/pages/contract-detail/contract-detail.page.container.jsx b/client/src/pages/contract-detail/contract-detail.page.container.jsx index f6ae8d356..94d181fe4 100644 --- a/client/src/pages/contract-detail/contract-detail.page.container.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.container.jsx @@ -1,7 +1,7 @@ import { useMutation, useQuery } from "@apollo/react-hooks"; import { Form, notification } from "antd"; import moment from "moment"; -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { useParams } from "react-router-dom"; @@ -35,6 +35,7 @@ export function ContractDetailPageContainer({ }) { const { t } = useTranslation(); const [updateContract] = useMutation(UPDATE_CONTRACT); + const [saveLoading, setsaveLoading] = useState(false); const [form] = Form.useForm(); const { contractId } = useParams(); @@ -95,6 +96,7 @@ export function ContractDetailPageContainer({ ]); const handleFinish = async (values) => { + setsaveLoading(true); const result = await updateContract({ variables: { cccontract: { ...values }, contractId: contractId }, }); @@ -108,6 +110,8 @@ export function ContractDetailPageContainer({ } notification["success"]({ message: t("contracts.successes.saved") }); if (refetch) await refetch(); + setsaveLoading(false); + form.resetFields(); form.resetFields(); }; @@ -160,6 +164,7 @@ export function ContractDetailPageContainer({ courtesyCar={data ? data.cccontracts_by_pk.courtesycar : null} refetch={refetch} form={form} + saveLoading={saveLoading} />
diff --git a/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx b/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx index a83f9348b..e02c167e4 100644 --- a/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx +++ b/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx @@ -1,6 +1,6 @@ import { useMutation } from "@apollo/react-hooks"; import { Form, notification } from "antd"; -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { useHistory } from "react-router-dom"; @@ -27,11 +27,13 @@ export function CourtesyCarCreateContainer({ setSelectedHeader, }) { const [form] = Form.useForm(); + const [loading, setLoading] = useState(false); const [insertCourtesyCar] = useMutation(INSERT_NEW_COURTESY_CAR); const { t } = useTranslation(); const history = useHistory(); const handleFinish = async (values) => { + setLoading(true); const result = await insertCourtesyCar({ variables: { courtesycar: { ...values, bodyshopid: bodyshop.id } }, }); @@ -42,7 +44,9 @@ export function CourtesyCarCreateContainer({ message: JSON.stringify(result.errors), }), }); + setLoading(false); } else { + setLoading(false); form.resetFields(); form.resetFields(); notification["success"]({ message: t("courtesycars.successes.saved") }); @@ -67,7 +71,7 @@ export function CourtesyCarCreateContainer({ return (
- +
); diff --git a/hasura/migrations/1612286825846_run_sql_migration/down.yaml b/hasura/migrations/1612286825846_run_sql_migration/down.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/hasura/migrations/1612286825846_run_sql_migration/down.yaml @@ -0,0 +1 @@ +[] diff --git a/hasura/migrations/1612286825846_run_sql_migration/up.yaml b/hasura/migrations/1612286825846_run_sql_migration/up.yaml new file mode 100644 index 000000000..5ca74c861 --- /dev/null +++ b/hasura/migrations/1612286825846_run_sql_migration/up.yaml @@ -0,0 +1,7 @@ +- args: + cascade: false + read_only: false + sql: |- + create trigger jobs_assign_RO_insert before insert on jobs for + each row execute function assign_ro_number(); + type: run_sql diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 11a50a749..46f6b3f42 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -131,7 +131,9 @@ function CalculatePartsTotals(jobLines) { sublets: { ...acc.sublets, subtotal: acc.sublets.subtotal.add( - Dinero({ amount: Math.round(value.act_price * 100) }) + Dinero({ + amount: Math.round(value.act_price * 100), + }).multiply(value.part_qty || 0) ), }, }; @@ -151,19 +153,19 @@ function CalculatePartsTotals(jobLines) { total: acc.parts.list[value.part_type].total.add( Dinero({ amount: Math.round((value.act_price || 0) * 100), - }).multiply(value.part_qty || 1) + }).multiply(value.part_qty || 0) ), } : { total: Dinero({ amount: Math.round((value.act_price || 0) * 100), - }).multiply(value.part_qty || 1), + }).multiply(value.part_qty || 0), }, }, subtotal: acc.parts.subtotal.add( Dinero({ amount: Math.round(value.act_price * 100), - }).multiply(value.part_qty) + }).multiply(value.part_qty || 0) ), }, }; @@ -233,7 +235,7 @@ function CalculateTaxesTotals(job, otherTotals) { if (!!!val.tax_part || !!!val.part_type || IsAdditionalCost(val)) { additionalItemsTax = additionalItemsTax.add( Dinero({ amount: Math.round((val.act_price || 0) * 100) }) - .multiply(val.part_qty || 1) + .multiply(val.value.part_qty || 0) .percentage( (job.parts_tax_rates && job.parts_tax_rates["PAN"] && @@ -243,7 +245,7 @@ function CalculateTaxesTotals(job, otherTotals) { } else { statePartsTax = statePartsTax.add( Dinero({ amount: Math.round((val.act_price || 0) * 100) }) - .multiply(val.part_qty || 1) + .multiply(val.part_qty || 0) .percentage( (job.parts_tax_rates && job.parts_tax_rates[val.part_type] &&