Merged in feature/IO-3178-Flat-Rate-ATS (pull request #2221)
IO-3178 Flat Rate ATS Approved-by: Dave Richer
This commit is contained in:
@@ -5,6 +5,7 @@ import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component";
|
||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
|
||||
@@ -14,9 +15,8 @@ import JobsDetailRatesLabor from "./jobs-detail-rates.labor.component";
|
||||
import JobsDetailRatesMaterials from "./jobs-detail-rates.materials.component";
|
||||
import JobsDetailRatesOther from "./jobs-detail-rates.other.component";
|
||||
import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
|
||||
import JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
|
||||
import JobsDetailRatesProfileOVerride from "./jobs-detail-rates.profile-override.component";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
@@ -66,14 +66,48 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
||||
</Space>
|
||||
)}
|
||||
<Form.Item label={t("jobs.fields.auto_add_ats")} name="auto_add_ats" valuePropName="checked">
|
||||
<Switch disabled={jobRO} />
|
||||
<Switch
|
||||
disabled={jobRO}
|
||||
onChange={(checked) => {
|
||||
if (checked) {
|
||||
form.setFieldsValue({ flat_rate_ats: false });
|
||||
form.setFieldsValue({ rate_ats: form.getFieldValue('rate_ats') || bodyshop.shoprates.rate_ats });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item noStyle shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}>
|
||||
{() => {
|
||||
if (form.getFieldValue("auto_add_ats"))
|
||||
return (
|
||||
<Form.Item label={t("jobs.fields.rate_ats")} name="rate_ats" initialValue={bodyshop.shoprates.rate_atp}>
|
||||
<Form.Item label={t("jobs.fields.rate_ats")} name="rate_ats">
|
||||
<CurrencyInput disabled={jobRO} />
|
||||
</Form.Item>
|
||||
);
|
||||
|
||||
return null;
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.flat_rate_ats")} name="flat_rate_ats" valuePropName="checked">
|
||||
<Switch
|
||||
disabled={jobRO}
|
||||
onChange={(checked) => {
|
||||
if (checked) {
|
||||
form.setFieldsValue({ auto_add_ats: false });
|
||||
form.setFieldsValue({ rate_ats_flat: form.getFieldValue('rate_ats_flat') || bodyshop.shoprates.rate_ats_flat });
|
||||
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item noStyle shouldUpdate={(prev, cur) => prev.flat_rate_ats !== cur.flat_rate_ats}>
|
||||
{() => {
|
||||
if (form.getFieldValue("flat_rate_ats"))
|
||||
return (
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_ats_flat")}
|
||||
name="rate_ats_flat"
|
||||
>
|
||||
<CurrencyInput disabled={jobRO} />
|
||||
</Form.Item>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DeleteFilled } from "@ant-design/icons";
|
||||
import { Button, Form, Input } from "antd";
|
||||
import React from "react";
|
||||
import { Button, Form, Input, Space } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||
@@ -10,326 +9,338 @@ export default function ShopInfoLaborRates({ form }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form.List name={["md_labor_rates"]}>
|
||||
{(fields, { add, remove, move }) => {
|
||||
return (
|
||||
<div>
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item key={field.key}>
|
||||
<LayoutFormRow>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.labor_rate_desc")}
|
||||
key={`${index}rate_label`}
|
||||
name={[field.name, "rate_label"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_laa")}
|
||||
key={`${index}rate_laa`}
|
||||
name={[field.name, "rate_laa"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lab")}
|
||||
key={`${index}rate_lab`}
|
||||
name={[field.name, "rate_lab"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lad")}
|
||||
key={`${index}rate_lad`}
|
||||
name={[field.name, "rate_lad"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lae")}
|
||||
key={`${index}rate_lae`}
|
||||
name={[field.name, "rate_lae"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_laf")}
|
||||
key={`${index}rate_laf`}
|
||||
name={[field.name, "rate_laf"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lag")}
|
||||
key={`${index}rate_lag`}
|
||||
name={[field.name, "rate_lag"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lam")}
|
||||
key={`${index}rate_lam`}
|
||||
name={[field.name, "rate_lam"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lar")}
|
||||
key={`${index}rate_lar`}
|
||||
name={[field.name, "rate_lar"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_las")}
|
||||
key={`${index}rate_las`}
|
||||
name={[field.name, "rate_las"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la1")}
|
||||
key={`${index}rate_la1`}
|
||||
name={[field.name, "rate_la1"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la2")}
|
||||
key={`${index}rate_la2`}
|
||||
name={[field.name, "rate_la2"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la3")}
|
||||
key={`${index}rate_la3`}
|
||||
name={[field.name, "rate_la3"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la4")}
|
||||
key={`${index}rate_la4`}
|
||||
name={[field.name, "rate_la4"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_mash")}
|
||||
key={`${index}rate_mash`}
|
||||
name={[field.name, "rate_mash"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_mapa")}
|
||||
key={`${index}rate_mapa`}
|
||||
name={[field.name, "rate_mapa"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_ma2s")}
|
||||
key={`${index}rate_ma2s`}
|
||||
name={[field.name, "rate_ma2s"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_ma3s")}
|
||||
key={`${index}rate_ma3s`}
|
||||
name={[field.name, "rate_ma3s"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
{
|
||||
// <Form.Item
|
||||
// label={t("jobs.fields.rate_mabl")}
|
||||
// key={`${index}rate_mabl`}
|
||||
// name={[field.name, "rate_mabl"]}
|
||||
// rules={[
|
||||
// {
|
||||
// required: true,
|
||||
// //message: t("general.validation.required"),
|
||||
// },
|
||||
// ]}
|
||||
// >
|
||||
// <CurrencyInput min={0} />
|
||||
// </Form.Item>
|
||||
// <Form.Item
|
||||
// label={t("jobs.fields.rate_macs")}
|
||||
// key={`${index}rate_macs`}
|
||||
// name={[field.name, "rate_macs"]}
|
||||
// rules={[
|
||||
// {
|
||||
// required: true,
|
||||
// //message: t("general.validation.required"),
|
||||
// },
|
||||
// ]}
|
||||
// >
|
||||
// <CurrencyInput min={0} />
|
||||
// </Form.Item>
|
||||
}
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_matd")}
|
||||
key={`${index}rate_matd`}
|
||||
name={[field.name, "rate_matd"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_mahw")}
|
||||
key={`${index}rate_mahw`}
|
||||
name={[field.name, "rate_mahw"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<DeleteFilled
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
<FormListMoveArrows move={move} index={index} total={fields.rate_length} />
|
||||
</LayoutFormRow>
|
||||
<>
|
||||
<LayoutFormRow header={t("bodyshop.labels.shoprates")}>
|
||||
<Form.Item label={t("jobs.fields.rate_ats")} name={["shoprates", "rate_ats"]}>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_ats_flat")} name={["shoprates", "rate_ats_flat"]}>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("bodyshop.labels.laborrates")}>
|
||||
<Form.List name={["md_labor_rates"]}>
|
||||
{(fields, { add, remove, move }) => {
|
||||
return (
|
||||
<div>
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item key={field.key}>
|
||||
<LayoutFormRow noDivider={index === 0}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.labor_rate_desc")}
|
||||
key={`${index}rate_label`}
|
||||
name={[field.name, "rate_label"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_laa")}
|
||||
key={`${index}rate_laa`}
|
||||
name={[field.name, "rate_laa"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lab")}
|
||||
key={`${index}rate_lab`}
|
||||
name={[field.name, "rate_lab"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lad")}
|
||||
key={`${index}rate_lad`}
|
||||
name={[field.name, "rate_lad"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lae")}
|
||||
key={`${index}rate_lae`}
|
||||
name={[field.name, "rate_lae"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_laf")}
|
||||
key={`${index}rate_laf`}
|
||||
name={[field.name, "rate_laf"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lag")}
|
||||
key={`${index}rate_lag`}
|
||||
name={[field.name, "rate_lag"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lam")}
|
||||
key={`${index}rate_lam`}
|
||||
name={[field.name, "rate_lam"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_lar")}
|
||||
key={`${index}rate_lar`}
|
||||
name={[field.name, "rate_lar"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_las")}
|
||||
key={`${index}rate_las`}
|
||||
name={[field.name, "rate_las"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la1")}
|
||||
key={`${index}rate_la1`}
|
||||
name={[field.name, "rate_la1"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la2")}
|
||||
key={`${index}rate_la2`}
|
||||
name={[field.name, "rate_la2"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la3")}
|
||||
key={`${index}rate_la3`}
|
||||
name={[field.name, "rate_la3"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_la4")}
|
||||
key={`${index}rate_la4`}
|
||||
name={[field.name, "rate_la4"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_mash")}
|
||||
key={`${index}rate_mash`}
|
||||
name={[field.name, "rate_mash"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_mapa")}
|
||||
key={`${index}rate_mapa`}
|
||||
name={[field.name, "rate_mapa"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_ma2s")}
|
||||
key={`${index}rate_ma2s`}
|
||||
name={[field.name, "rate_ma2s"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_ma3s")}
|
||||
key={`${index}rate_ma3s`}
|
||||
name={[field.name, "rate_ma3s"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
{
|
||||
// <Form.Item
|
||||
// label={t("jobs.fields.rate_mabl")}
|
||||
// key={`${index}rate_mabl`}
|
||||
// name={[field.name, "rate_mabl"]}
|
||||
// rules={[
|
||||
// {
|
||||
// required: true,
|
||||
// //message: t("general.validation.required"),
|
||||
// },
|
||||
// ]}
|
||||
// >
|
||||
// <CurrencyInput min={0} />
|
||||
// </Form.Item>
|
||||
// <Form.Item
|
||||
// label={t("jobs.fields.rate_macs")}
|
||||
// key={`${index}rate_macs`}
|
||||
// name={[field.name, "rate_macs"]}
|
||||
// rules={[
|
||||
// {
|
||||
// required: true,
|
||||
// //message: t("general.validation.required"),
|
||||
// },
|
||||
// ]}
|
||||
// >
|
||||
// <CurrencyInput min={0} />
|
||||
// </Form.Item>
|
||||
}
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_matd")}
|
||||
key={`${index}rate_matd`}
|
||||
name={[field.name, "rate_matd"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_mahw")}
|
||||
key={`${index}rate_mahw`}
|
||||
name={[field.name, "rate_mahw"]}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
<Space>
|
||||
<DeleteFilled
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
<FormListMoveArrows move={move} index={index} total={fields.rate_length} />
|
||||
</Space>
|
||||
</LayoutFormRow>
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => {
|
||||
add();
|
||||
}}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{t("bodyshop.actions.newlaborrate")}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => {
|
||||
add();
|
||||
}}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{t("bodyshop.actions.newlaborrate")}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
</LayoutFormRow>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -509,6 +509,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
est_ct_ln
|
||||
est_ea
|
||||
est_ph1
|
||||
flat_rate_ats
|
||||
federal_tax_rate
|
||||
id
|
||||
inproduction
|
||||
@@ -649,6 +650,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
policy_no
|
||||
production_vars
|
||||
rate_ats
|
||||
rate_ats_flat
|
||||
rate_la1
|
||||
rate_la2
|
||||
rate_la3
|
||||
|
||||
@@ -722,6 +722,7 @@
|
||||
"scoreboardsetup": "Scoreboard Setup",
|
||||
"shop_enabled_features": "Shop Enabled Features",
|
||||
"shopinfo": "Shop Information",
|
||||
"shoprates": "Shop Rates",
|
||||
"speedprint": "Speed Print Configuration",
|
||||
"ssbuckets": "Job Size Definitions",
|
||||
"systemsettings": "System Settings",
|
||||
@@ -1658,7 +1659,7 @@
|
||||
"08": "Left Rear Side",
|
||||
"09": "Left Side"
|
||||
},
|
||||
"auto_add_ats": "Automatically Add/Update ATS",
|
||||
"auto_add_ats": "Automatically Add/Update ATS?",
|
||||
"ca_bc_pvrt": "PVRT",
|
||||
"ca_customer_gst": "Customer Portion of GST",
|
||||
"ca_gst_registrant": "GST Registrant",
|
||||
@@ -1757,6 +1758,7 @@
|
||||
"est_ct_ln": "Estimator Last Name",
|
||||
"est_ea": "Estimator Email",
|
||||
"est_ph1": "Estimator Phone #",
|
||||
"flat_rate_ats": "Flat Rate ATS?",
|
||||
"federal_tax_payable": "Federal Tax Payable",
|
||||
"federal_tax_rate": "Federal Tax Rate",
|
||||
"ins_addr1": "Insurance Co. Address",
|
||||
@@ -1868,6 +1870,7 @@
|
||||
},
|
||||
"queued_for_parts": "Queued for Parts",
|
||||
"rate_ats": "ATS Rate",
|
||||
"rate_ats_flat": "ATS Flat Rate",
|
||||
"rate_la1": "LA1",
|
||||
"rate_la2": "LA2",
|
||||
"rate_la3": "LA3",
|
||||
|
||||
@@ -722,6 +722,7 @@
|
||||
"scoreboardsetup": "",
|
||||
"shop_enabled_features": "",
|
||||
"shopinfo": "",
|
||||
"shoprates": "",
|
||||
"speedprint": "",
|
||||
"ssbuckets": "",
|
||||
"systemsettings": "",
|
||||
@@ -1757,6 +1758,7 @@
|
||||
"est_ct_ln": "Apellido del tasador",
|
||||
"est_ea": "Correo electrónico del tasador",
|
||||
"est_ph1": "Número de teléfono del tasador",
|
||||
"flat_rate_ats": "",
|
||||
"federal_tax_payable": "Impuesto federal por pagar",
|
||||
"federal_tax_rate": "",
|
||||
"ins_addr1": "Dirección de Insurance Co.",
|
||||
@@ -1868,6 +1870,7 @@
|
||||
},
|
||||
"queued_for_parts": "",
|
||||
"rate_ats": "",
|
||||
"rate_ats_flat": "",
|
||||
"rate_la1": "Tarifa LA1",
|
||||
"rate_la2": "Tarifa LA2",
|
||||
"rate_la3": "Tarifa LA3",
|
||||
|
||||
@@ -722,6 +722,7 @@
|
||||
"scoreboardsetup": "",
|
||||
"shop_enabled_features": "",
|
||||
"shopinfo": "",
|
||||
"shoprates": "",
|
||||
"speedprint": "",
|
||||
"ssbuckets": "",
|
||||
"systemsettings": "",
|
||||
@@ -1757,6 +1758,7 @@
|
||||
"est_ct_ln": "Nom de l'évaluateur",
|
||||
"est_ea": "Courriel de l'évaluateur",
|
||||
"est_ph1": "Numéro de téléphone de l'évaluateur",
|
||||
"flat_rate_ats": "",
|
||||
"federal_tax_payable": "Impôt fédéral à payer",
|
||||
"federal_tax_rate": "",
|
||||
"ins_addr1": "Adresse Insurance Co.",
|
||||
@@ -1868,6 +1870,7 @@
|
||||
},
|
||||
"queued_for_parts": "",
|
||||
"rate_ats": "",
|
||||
"rate_ats_flat": "",
|
||||
"rate_la1": "Taux LA1",
|
||||
"rate_la2": "Taux LA2",
|
||||
"rate_la3": "Taux LA3",
|
||||
|
||||
@@ -3695,6 +3695,7 @@
|
||||
- est_st
|
||||
- est_zip
|
||||
- federal_tax_rate
|
||||
- flat_rate_ats
|
||||
- g_bett_amt
|
||||
- id
|
||||
- inproduction
|
||||
@@ -3789,6 +3790,7 @@
|
||||
- qb_multiple_payers
|
||||
- queued_for_parts
|
||||
- rate_ats
|
||||
- rate_ats_flat
|
||||
- rate_la1
|
||||
- rate_la2
|
||||
- rate_la3
|
||||
@@ -3965,6 +3967,7 @@
|
||||
- est_st
|
||||
- est_zip
|
||||
- federal_tax_rate
|
||||
- flat_rate_ats
|
||||
- g_bett_amt
|
||||
- id
|
||||
- inproduction
|
||||
@@ -4060,6 +4063,7 @@
|
||||
- qb_multiple_payers
|
||||
- queued_for_parts
|
||||
- rate_ats
|
||||
- rate_ats_flat
|
||||
- rate_la1
|
||||
- rate_la2
|
||||
- rate_la3
|
||||
@@ -4247,6 +4251,7 @@
|
||||
- est_st
|
||||
- est_zip
|
||||
- federal_tax_rate
|
||||
- flat_rate_ats
|
||||
- g_bett_amt
|
||||
- id
|
||||
- inproduction
|
||||
@@ -4342,6 +4347,7 @@
|
||||
- qb_multiple_payers
|
||||
- queued_for_parts
|
||||
- rate_ats
|
||||
- rate_ats_flat
|
||||
- rate_la1
|
||||
- rate_la2
|
||||
- rate_la3
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."jobs" add column "flat_rate_ats" boolean
|
||||
-- null default 'false';
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" add column "flat_rate_ats" boolean
|
||||
null default 'false';
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."jobs" add column "rate_ats_flat" numeric
|
||||
-- null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" add column "rate_ats_flat" numeric
|
||||
null;
|
||||
@@ -1485,6 +1485,8 @@ exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) {
|
||||
materials
|
||||
auto_add_ats
|
||||
rate_ats
|
||||
flat_rate_ats
|
||||
rate_ats_flat
|
||||
joblines(where: { removed: { _eq: false } }){
|
||||
id
|
||||
line_no
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const Dinero = require("dinero.js");
|
||||
const queries = require("../graphql-client/queries");
|
||||
const adminClient = require("../graphql-client/graphql-client").client;
|
||||
const _ = require("lodash");
|
||||
// const adminClient = require("../graphql-client/graphql-client").client;
|
||||
// const _ = require("lodash");
|
||||
const logger = require("../utils/logger");
|
||||
const InstanceMgr = require("../utils/instanceMgr").default;
|
||||
|
||||
@@ -45,7 +45,9 @@ exports.totalsSsu = async function (req, res) {
|
||||
}
|
||||
});
|
||||
|
||||
res.status(200).send();
|
||||
if (result) {
|
||||
res.status(200).send();
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, {
|
||||
jobid: id,
|
||||
@@ -59,7 +61,7 @@ exports.totalsSsu = async function (req, res) {
|
||||
//IMPORTANT*** These two functions MUST be mirrrored.
|
||||
async function TotalsServerSide(req, res) {
|
||||
const { job, client } = req.body;
|
||||
await AutoAddAtsIfRequired({ job: job, client: client });
|
||||
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
||||
|
||||
try {
|
||||
let ret = {
|
||||
@@ -138,10 +140,11 @@ async function Totals(req, res) {
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, job.id, {
|
||||
jobid: job.id
|
||||
jobid: job.id,
|
||||
id: id
|
||||
});
|
||||
|
||||
await AutoAddAtsIfRequired({ job, client });
|
||||
await AtsAdjustmentsIfRequired({ job, client, user: req.user });
|
||||
|
||||
try {
|
||||
let ret = {
|
||||
@@ -153,7 +156,7 @@ async function Totals(req, res) {
|
||||
|
||||
res.status(200).json(ret);
|
||||
} catch (error) {
|
||||
logger.log("job-totals-USA-error", "ERROR", req.user.email, job.id, {
|
||||
logger.log("job-totals-ssu-USA-error", "ERROR", req.user.email, job.id, {
|
||||
jobid: job.id,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
@@ -162,40 +165,45 @@ async function Totals(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
async function AutoAddAtsIfRequired({ job, client }) {
|
||||
//Check if ATS should be automatically added.
|
||||
if (job.auto_add_ats) {
|
||||
//Get the total sum of hours that should be the ATS amount.
|
||||
//Check to see if an ATS line exists.
|
||||
async function AtsAdjustmentsIfRequired({ job, client, user }) {
|
||||
if (job.auto_add_ats || job.flat_rate_ats) {
|
||||
let atsAmount = 0;
|
||||
let atsLineIndex = null;
|
||||
const atsHours = job.joblines.reduce((acc, val, index) => {
|
||||
if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") {
|
||||
atsLineIndex = index;
|
||||
}
|
||||
|
||||
if (
|
||||
val.mod_lbr_ty !== "LA1" &&
|
||||
val.mod_lbr_ty !== "LA2" &&
|
||||
val.mod_lbr_ty !== "LA3" &&
|
||||
val.mod_lbr_ty !== "LA4" &&
|
||||
val.mod_lbr_ty !== "LAU" &&
|
||||
val.mod_lbr_ty !== "LAG" &&
|
||||
val.mod_lbr_ty !== "LAS" &&
|
||||
val.mod_lbr_ty !== "LAA"
|
||||
) {
|
||||
acc = acc + val.mod_lb_hrs;
|
||||
}
|
||||
//Check if ATS should be automatically added.
|
||||
if (job.auto_add_ats) {
|
||||
const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]);
|
||||
|
||||
return acc;
|
||||
}, 0);
|
||||
//Get the total sum of hours that should be the ATS amount.
|
||||
//Check to see if an ATS line exists.
|
||||
const atsHours = job.joblines.reduce((acc, val, index) => {
|
||||
if (val.line_desc?.toLowerCase() === "ats amount") {
|
||||
atsLineIndex = index;
|
||||
}
|
||||
|
||||
const atsAmount = atsHours * (job.rate_ats || 0);
|
||||
//If it does, update it in place, and make sure it is updated for local calculations.
|
||||
if (!excludedLaborTypes.has(val.mod_lbr_ty)) {
|
||||
acc = acc + val.mod_lb_hrs;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
atsAmount = atsHours * (job.rate_ats || 0);
|
||||
}
|
||||
|
||||
//Check if a Flat Rate ATS should be added.
|
||||
if (job.flat_rate_ats) {
|
||||
atsLineIndex = ((i) => (i === -1 ? null : i))(
|
||||
job.joblines.findIndex((line) => line.line_desc?.toLowerCase() === "ats amount")
|
||||
);
|
||||
atsAmount = job.rate_ats_flat || 0;
|
||||
}
|
||||
|
||||
//If it does not, create one for local calculations and insert it.
|
||||
if (atsLineIndex === null) {
|
||||
const newAtsLine = {
|
||||
jobid: job.id,
|
||||
alt_partm: null,
|
||||
line_no: 35,
|
||||
unq_seq: 0,
|
||||
line_ind: "E",
|
||||
line_desc: "ATS Amount",
|
||||
@@ -220,19 +228,42 @@ async function AutoAddAtsIfRequired({ job, client }) {
|
||||
prt_dsmk_m: 0.0
|
||||
};
|
||||
|
||||
const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
|
||||
lineInput: [newAtsLine]
|
||||
});
|
||||
try {
|
||||
const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
|
||||
lineInput: [newAtsLine]
|
||||
});
|
||||
|
||||
job.joblines.push(newAtsLine);
|
||||
if (result) {
|
||||
job.joblines.push(newAtsLine);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
|
||||
jobid: job.id,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
}
|
||||
}
|
||||
//If it does not, create one for local calculations and insert it.
|
||||
//If it does, update it in place, and make sure it is updated for local calculations.
|
||||
else {
|
||||
const result = await client.request(queries.UPDATE_JOB_LINE, {
|
||||
line: { act_price: atsAmount },
|
||||
lineId: job.joblines[atsLineIndex].id
|
||||
});
|
||||
job.joblines[atsLineIndex].act_price = atsAmount;
|
||||
try {
|
||||
const result = await client.request(queries.UPDATE_JOB_LINE, {
|
||||
line: { act_price: atsAmount },
|
||||
lineId: job.joblines[atsLineIndex].id
|
||||
});
|
||||
if (result) {
|
||||
job.joblines[atsLineIndex].act_price = atsAmount;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
|
||||
jobid: job.id,
|
||||
atsLineIndex: atsLineIndex,
|
||||
atsAmount: atsAmount,
|
||||
jobline: job.joblines[atsLineIndex],
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,7 +345,7 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
let hasMashLine = false;
|
||||
let hasMahwLine = false;
|
||||
let hasCustomMahwLine;
|
||||
let mapaOpCodes = ParseCalopCode(job.materials["MAPA"]?.cal_opcode);
|
||||
// let mapaOpCodes = ParseCalopCode(job.materials["MAPA"]?.cal_opcode);
|
||||
let mashOpCodes = ParseCalopCode(job.materials["MASH"]?.cal_opcode);
|
||||
|
||||
jobLines.forEach((item) => {
|
||||
@@ -564,7 +595,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) {
|
||||
}
|
||||
};
|
||||
|
||||
default:
|
||||
default: {
|
||||
if (!value.part_type && value.db_ref !== "900510" && value.db_ref !== "900511") return acc;
|
||||
|
||||
const discountAmount =
|
||||
@@ -631,6 +662,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) {
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -652,7 +684,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) {
|
||||
let adjustments = {};
|
||||
//Track all adjustments that need to be made.
|
||||
|
||||
const linesToAdjustForDiscount = [];
|
||||
//const linesToAdjustForDiscount = [];
|
||||
Object.keys(parts_tax_rates).forEach((key) => {
|
||||
//Check if there's a discount or a mark up.
|
||||
let disc = Dinero(),
|
||||
@@ -1019,7 +1051,9 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("job-totals-USA Key with issue", "error", null, job.id, {
|
||||
key
|
||||
key: key,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1157,6 +1191,7 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
|
||||
exports.default = Totals;
|
||||
|
||||
//eslint-disable-next-line no-unused-vars
|
||||
function DiscountNotAlreadyCounted(jobline, joblines) {
|
||||
return false;
|
||||
}
|
||||
@@ -1172,27 +1207,35 @@ function IsTrueOrYes(value) {
|
||||
return value === true || value === "Y" || value === "y";
|
||||
}
|
||||
|
||||
async function UpdateJobLines(joblinesToUpdate) {
|
||||
if (joblinesToUpdate.length === 0) return;
|
||||
const updateQueries = joblinesToUpdate.map((line, index) =>
|
||||
generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index)
|
||||
);
|
||||
const query = `
|
||||
mutation UPDATE_EST_LINES{
|
||||
${updateQueries}
|
||||
}
|
||||
`;
|
||||
// Function not in use from RO to IO Merger 02/05/2024
|
||||
// async function UpdateJobLines(joblinesToUpdate) {
|
||||
// if (joblinesToUpdate.length === 0) return;
|
||||
// const updateQueries = joblinesToUpdate.map((line, index) =>
|
||||
// generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index)
|
||||
// );
|
||||
// const query = `
|
||||
// mutation UPDATE_EST_LINES{
|
||||
// ${updateQueries}
|
||||
// }
|
||||
// `;
|
||||
// try {
|
||||
// const result = await adminClient.request(query);
|
||||
// void result;
|
||||
// } catch (error) {
|
||||
// logger.log("update-job-lines", "error", null, null, {
|
||||
// error: error.message,
|
||||
// stack: error.stack
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
const result = await adminClient.request(query);
|
||||
}
|
||||
|
||||
const generateUpdateQuery = (lineToUpdate, index) => {
|
||||
return `
|
||||
update_joblines${index}: update_joblines(where: { id: { _eq: "${
|
||||
lineToUpdate.id
|
||||
}" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) {
|
||||
returning {
|
||||
id
|
||||
}
|
||||
}`;
|
||||
};
|
||||
// const generateUpdateQuery = (lineToUpdate, index) => {
|
||||
// return `
|
||||
// update_joblines${index}: update_joblines(where: { id: { _eq: "${
|
||||
// lineToUpdate.id
|
||||
// }" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) {
|
||||
// returning {
|
||||
// id
|
||||
// }
|
||||
// }`;
|
||||
// };
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
const Dinero = require("dinero.js");
|
||||
const queries = require("../graphql-client/queries");
|
||||
const adminClient = require("../graphql-client/graphql-client").client;
|
||||
const _ = require("lodash");
|
||||
const logger = require("../utils/logger");
|
||||
|
||||
//****************************************************** */
|
||||
@@ -44,11 +42,16 @@ exports.totalsSsu = async function (req, res) {
|
||||
}
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
throw new Error("Failed to update job totals");
|
||||
}
|
||||
|
||||
res.status(200).send();
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-error", "ERROR", req.user.email, id, {
|
||||
jobid: id,
|
||||
error
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
res.status(503).send();
|
||||
}
|
||||
@@ -57,7 +60,7 @@ exports.totalsSsu = async function (req, res) {
|
||||
//IMPORTANT*** These two functions MUST be mirrrored.
|
||||
async function TotalsServerSide(req, res) {
|
||||
const { job, client } = req.body;
|
||||
await AutoAddAtsIfRequired({ job: job, client: client });
|
||||
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
||||
|
||||
try {
|
||||
let ret = {
|
||||
@@ -71,7 +74,8 @@ async function TotalsServerSide(req, res) {
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-error", "ERROR", req?.user?.email, job.id, {
|
||||
jobid: job.id,
|
||||
error
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
res.status(400).send(JSON.stringify(error));
|
||||
}
|
||||
@@ -83,13 +87,12 @@ async function Totals(req, res) {
|
||||
const logger = req.logger;
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
logger.log("job-totals", "DEBUG", req.user.email, job.id, {
|
||||
jobid: job.id
|
||||
logger.log("job-totals-ssu", "DEBUG", req.user.email, job.id, {
|
||||
jobid: job.id,
|
||||
id: id
|
||||
});
|
||||
|
||||
logger.log("job-totals-ssu", "DEBUG", req.user.email, id, null);
|
||||
|
||||
await AutoAddAtsIfRequired({ job, client });
|
||||
await AtsAdjustmentsIfRequired({ job, client, user: req.user });
|
||||
|
||||
try {
|
||||
let ret = {
|
||||
@@ -101,48 +104,54 @@ async function Totals(req, res) {
|
||||
|
||||
res.status(200).json(ret);
|
||||
} catch (error) {
|
||||
logger.log("job-totals-error", "ERROR", req.user.email, job.id, {
|
||||
logger.log("job-totals-ssu-error", "ERROR", req.user.email, job.id, {
|
||||
jobid: job.id,
|
||||
error
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
res.status(400).send(JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
async function AutoAddAtsIfRequired({ job, client }) {
|
||||
//Check if ATS should be automatically added.
|
||||
if (job.auto_add_ats) {
|
||||
//Get the total sum of hours that should be the ATS amount.
|
||||
//Check to see if an ATS line exists.
|
||||
async function AtsAdjustmentsIfRequired({ job, client, user }) {
|
||||
if (job.auto_add_ats || job.flat_rate_ats) {
|
||||
let atsAmount = 0;
|
||||
let atsLineIndex = null;
|
||||
const atsHours = job.joblines.reduce((acc, val, index) => {
|
||||
if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") {
|
||||
atsLineIndex = index;
|
||||
}
|
||||
|
||||
if (
|
||||
val.mod_lbr_ty !== "LA1" &&
|
||||
val.mod_lbr_ty !== "LA2" &&
|
||||
val.mod_lbr_ty !== "LA3" &&
|
||||
val.mod_lbr_ty !== "LA4" &&
|
||||
val.mod_lbr_ty !== "LAU" &&
|
||||
val.mod_lbr_ty !== "LAG" &&
|
||||
val.mod_lbr_ty !== "LAS" &&
|
||||
val.mod_lbr_ty !== "LAA"
|
||||
) {
|
||||
acc = acc + val.mod_lb_hrs;
|
||||
}
|
||||
//Check if ATS should be automatically added.
|
||||
if (job.auto_add_ats) {
|
||||
const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]);
|
||||
|
||||
return acc;
|
||||
}, 0);
|
||||
//Get the total sum of hours that should be the ATS amount.
|
||||
//Check to see if an ATS line exists.
|
||||
const atsHours = job.joblines.reduce((acc, val, index) => {
|
||||
if (val.line_desc?.toLowerCase() === "ats amount") {
|
||||
atsLineIndex = index;
|
||||
}
|
||||
|
||||
const atsAmount = atsHours * (job.rate_ats || 0);
|
||||
//If it does, update it in place, and make sure it is updated for local calculations.
|
||||
if (!excludedLaborTypes.has(val.mod_lbr_ty)) {
|
||||
acc = acc + val.mod_lb_hrs;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
atsAmount = atsHours * (job.rate_ats || 0);
|
||||
}
|
||||
|
||||
//Check if a Flat Rate ATS should be added.
|
||||
if (job.flat_rate_ats) {
|
||||
atsLineIndex = ((i) => (i === -1 ? null : i))(
|
||||
job.joblines.findIndex((line) => line.line_desc?.toLowerCase() === "ats amount")
|
||||
);
|
||||
atsAmount = job.rate_ats_flat || 0;
|
||||
}
|
||||
|
||||
//If it does not, create one for local calculations and insert it.
|
||||
if (atsLineIndex === null) {
|
||||
const newAtsLine = {
|
||||
jobid: job.id,
|
||||
alt_partm: null,
|
||||
line_no: 35,
|
||||
unq_seq: 0,
|
||||
line_ind: "E",
|
||||
line_desc: "ATS Amount",
|
||||
@@ -167,22 +176,43 @@ async function AutoAddAtsIfRequired({ job, client }) {
|
||||
prt_dsmk_m: 0.0
|
||||
};
|
||||
|
||||
const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
|
||||
lineInput: [newAtsLine]
|
||||
});
|
||||
try {
|
||||
const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
|
||||
lineInput: [newAtsLine]
|
||||
});
|
||||
|
||||
job.joblines.push(newAtsLine);
|
||||
if (result) {
|
||||
job.joblines.push(newAtsLine);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
|
||||
jobid: job.id,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
}
|
||||
}
|
||||
//If it does not, create one for local calculations and insert it.
|
||||
//If it does, update it in place, and make sure it is updated for local calculations.
|
||||
else {
|
||||
const result = await client.request(queries.UPDATE_JOB_LINE, {
|
||||
line: { act_price: atsAmount },
|
||||
lineId: job.joblines[atsLineIndex].id
|
||||
});
|
||||
job.joblines[atsLineIndex].act_price = atsAmount;
|
||||
try {
|
||||
const result = await client.request(queries.UPDATE_JOB_LINE, {
|
||||
line: { act_price: atsAmount },
|
||||
lineId: job.joblines[atsLineIndex].id
|
||||
});
|
||||
if (result) {
|
||||
job.joblines[atsLineIndex].act_price = atsAmount;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
|
||||
jobid: job.id,
|
||||
atsLineIndex: atsLineIndex,
|
||||
atsAmount: atsAmount,
|
||||
jobline: job.joblines[atsLineIndex],
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//console.log(job.jobLines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user