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) || "")}`}
-
- {t("general.actions.save")}
-
-
{
- setCourtesyCarReturnModalContext({
- actions: { refetch },
- context: {
- contractId: contract.id,
- courtesyCarId: courtesyCar.id,
- },
- });
- }}
- >
- {t("courtesycars.actions.return")}
-
-
@@ -57,6 +37,43 @@ export function ContractDetailPage({
+
+ {() => {
+ return (
+
+
+ {t("general.actions.save")}
+
+ {
+ setCourtesyCarReturnModalContext({
+ actions: { refetch },
+ context: {
+ contractId: contract.id,
+ courtesyCarId: courtesyCar.id,
+ },
+ });
+ }}
+ >
+ {t("courtesycars.actions.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] &&