Merged release/2025-03-28 into feature/IO-3183-Dependency-Updates-and-maintenance

This commit is contained in:
Dave Richer
2025-03-25 13:42:43 +00:00
19 changed files with 12031 additions and 11766 deletions

View File

@@ -9,6 +9,6 @@ VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4' VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
VITE_APP_AXIOS_BASE_API_URL=/api/ VITE_APP_AXIOS_BASE_API_URL=/api/
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online VITE_APP_REPORTS_SERVER_URL=https://reports.test.imex.online
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
VITE_APP_INSTANCE=IMEX VITE_APP_INSTANCE=IMEX

View File

@@ -10,7 +10,7 @@ VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo' VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
VITE_APP_AXIOS_BASE_API_URL=/api/ VITE_APP_AXIOS_BASE_API_URL=/api/
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
VITE_APP_COUNTRY=USA VITE_APP_COUNTRY=USA
VITE_APP_INSTANCE=ROME VITE_APP_INSTANCE=ROME

View File

@@ -9,7 +9,7 @@ VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo' VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
VITE_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/ VITE_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online VITE_APP_REPORTS_SERVER_URL=https://reports.test.imex.online
VITE_APP_IS_TEST=true VITE_APP_IS_TEST=true
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
VITE_APP_INSTANCE=IMEX VITE_APP_INSTANCE=IMEX

View File

@@ -5,6 +5,7 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors"; import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.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 CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.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"; 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 JobsDetailRatesMaterials from "./jobs-detail-rates.materials.component";
import JobsDetailRatesOther from "./jobs-detail-rates.other.component"; import JobsDetailRatesOther from "./jobs-detail-rates.other.component";
import JobsDetailRatesParts from "./jobs-detail-rates.parts.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 JobsDetailRatesProfileOVerride from "./jobs-detail-rates.profile-override.component";
import InstanceRenderManager from "../../utils/instanceRenderMgr"; import JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly, jobRO: selectJobReadOnly,
@@ -66,14 +66,48 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
</Space> </Space>
)} )}
<Form.Item label={t("jobs.fields.auto_add_ats")} name="auto_add_ats" valuePropName="checked"> <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>
<Form.Item noStyle shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}> <Form.Item noStyle shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}>
{() => { {() => {
if (form.getFieldValue("auto_add_ats")) if (form.getFieldValue("auto_add_ats"))
return ( 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} /> <CurrencyInput disabled={jobRO} />
</Form.Item> </Form.Item>
); );

View File

@@ -1,6 +1,5 @@
import { DeleteFilled } from "@ant-design/icons"; import { DeleteFilled } from "@ant-design/icons";
import { Button, Form, Input } from "antd"; import { Button, Form, Input, Space } from "antd";
import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.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(); const { t } = useTranslation();
return ( return (
<div> <>
<Form.List name={["md_labor_rates"]}> <LayoutFormRow header={t("bodyshop.labels.shoprates")}>
{(fields, { add, remove, move }) => { <Form.Item label={t("jobs.fields.rate_ats")} name={["shoprates", "rate_ats"]}>
return ( <CurrencyInput min={0} />
<div> </Form.Item>
{fields.map((field, index) => ( <Form.Item label={t("jobs.fields.rate_ats_flat")} name={["shoprates", "rate_ats_flat"]}>
<Form.Item key={field.key}> <CurrencyInput min={0} />
<LayoutFormRow> </Form.Item>
<Form.Item </LayoutFormRow>
label={t("jobs.fields.labor_rate_desc")} <LayoutFormRow header={t("bodyshop.labels.laborrates")}>
key={`${index}rate_label`} <Form.List name={["md_labor_rates"]}>
name={[field.name, "rate_label"]} {(fields, { add, remove, move }) => {
rules={[ return (
{ <div>
required: true {fields.map((field, index) => (
//message: t("general.validation.required"), <Form.Item key={field.key}>
} <LayoutFormRow noDivider={index === 0}>
]} <Form.Item
> label={t("jobs.fields.labor_rate_desc")}
<Input /> key={`${index}rate_label`}
</Form.Item> name={[field.name, "rate_label"]}
<Form.Item rules={[
label={t("jobs.fields.rate_laa")} {
key={`${index}rate_laa`} required: true
name={[field.name, "rate_laa"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <Input />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_laa")}
<CurrencyInput min={0} /> key={`${index}rate_laa`}
</Form.Item> name={[field.name, "rate_laa"]}
<Form.Item rules={[
label={t("jobs.fields.rate_lab")} {
key={`${index}rate_lab`} required: true
name={[field.name, "rate_lab"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_lab")}
<CurrencyInput min={0} /> key={`${index}rate_lab`}
</Form.Item> name={[field.name, "rate_lab"]}
<Form.Item rules={[
label={t("jobs.fields.rate_lad")} {
key={`${index}rate_lad`} required: true
name={[field.name, "rate_lad"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_lad")}
<CurrencyInput min={0} /> key={`${index}rate_lad`}
</Form.Item> name={[field.name, "rate_lad"]}
<Form.Item rules={[
label={t("jobs.fields.rate_lae")} {
key={`${index}rate_lae`} required: true
name={[field.name, "rate_lae"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_lae")}
<CurrencyInput min={0} /> key={`${index}rate_lae`}
</Form.Item> name={[field.name, "rate_lae"]}
<Form.Item rules={[
label={t("jobs.fields.rate_laf")} {
key={`${index}rate_laf`} required: true
name={[field.name, "rate_laf"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_laf")}
<CurrencyInput min={0} /> key={`${index}rate_laf`}
</Form.Item> name={[field.name, "rate_laf"]}
<Form.Item rules={[
label={t("jobs.fields.rate_lag")} {
key={`${index}rate_lag`} required: true
name={[field.name, "rate_lag"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_lag")}
<CurrencyInput min={0} /> key={`${index}rate_lag`}
</Form.Item> name={[field.name, "rate_lag"]}
<Form.Item rules={[
label={t("jobs.fields.rate_lam")} {
key={`${index}rate_lam`} required: true
name={[field.name, "rate_lam"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_lam")}
<CurrencyInput min={0} /> key={`${index}rate_lam`}
</Form.Item> name={[field.name, "rate_lam"]}
<Form.Item rules={[
label={t("jobs.fields.rate_lar")} {
key={`${index}rate_lar`} required: true
name={[field.name, "rate_lar"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_lar")}
<CurrencyInput min={0} /> key={`${index}rate_lar`}
</Form.Item> name={[field.name, "rate_lar"]}
<Form.Item rules={[
label={t("jobs.fields.rate_las")} {
key={`${index}rate_las`} required: true
name={[field.name, "rate_las"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_las")}
<CurrencyInput min={0} /> key={`${index}rate_las`}
</Form.Item> name={[field.name, "rate_las"]}
<Form.Item rules={[
label={t("jobs.fields.rate_la1")} {
key={`${index}rate_la1`} required: true
name={[field.name, "rate_la1"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_la1")}
<CurrencyInput min={0} /> key={`${index}rate_la1`}
</Form.Item> name={[field.name, "rate_la1"]}
<Form.Item rules={[
label={t("jobs.fields.rate_la2")} {
key={`${index}rate_la2`} required: true
name={[field.name, "rate_la2"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_la2")}
<CurrencyInput min={0} /> key={`${index}rate_la2`}
</Form.Item> name={[field.name, "rate_la2"]}
<Form.Item rules={[
label={t("jobs.fields.rate_la3")} {
key={`${index}rate_la3`} required: true
name={[field.name, "rate_la3"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_la3")}
<CurrencyInput min={0} /> key={`${index}rate_la3`}
</Form.Item> name={[field.name, "rate_la3"]}
<Form.Item rules={[
label={t("jobs.fields.rate_la4")} {
key={`${index}rate_la4`} required: true
name={[field.name, "rate_la4"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_la4")}
<CurrencyInput min={0} /> key={`${index}rate_la4`}
</Form.Item> name={[field.name, "rate_la4"]}
<Form.Item rules={[
label={t("jobs.fields.rate_mash")} {
key={`${index}rate_mash`} required: true
name={[field.name, "rate_mash"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_mash")}
<CurrencyInput min={0} /> key={`${index}rate_mash`}
</Form.Item> name={[field.name, "rate_mash"]}
<Form.Item rules={[
label={t("jobs.fields.rate_mapa")} {
key={`${index}rate_mapa`} required: true
name={[field.name, "rate_mapa"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_mapa")}
<CurrencyInput min={0} /> key={`${index}rate_mapa`}
</Form.Item> name={[field.name, "rate_mapa"]}
<Form.Item rules={[
label={t("jobs.fields.rate_ma2s")} {
key={`${index}rate_ma2s`} required: true
name={[field.name, "rate_ma2s"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_ma2s")}
<CurrencyInput min={0} /> key={`${index}rate_ma2s`}
</Form.Item> name={[field.name, "rate_ma2s"]}
<Form.Item rules={[
label={t("jobs.fields.rate_ma3s")} {
key={`${index}rate_ma3s`} required: true
name={[field.name, "rate_ma3s"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_ma3s")}
<CurrencyInput min={0} /> key={`${index}rate_ma3s`}
</Form.Item> name={[field.name, "rate_ma3s"]}
{ rules={[
// <Form.Item {
// label={t("jobs.fields.rate_mabl")} required: true
// key={`${index}rate_mabl`} //message: t("general.validation.required"),
// name={[field.name, "rate_mabl"]} }
// rules={[ ]}
// { >
// required: true, <CurrencyInput min={0} />
// //message: t("general.validation.required"), </Form.Item>
// }, {
// ]} // <Form.Item
// > // label={t("jobs.fields.rate_mabl")}
// <CurrencyInput min={0} /> // key={`${index}rate_mabl`}
// </Form.Item> // name={[field.name, "rate_mabl"]}
// <Form.Item // rules={[
// label={t("jobs.fields.rate_macs")} // {
// key={`${index}rate_macs`} // required: true,
// name={[field.name, "rate_macs"]} // //message: t("general.validation.required"),
// rules={[ // },
// { // ]}
// required: true, // >
// //message: t("general.validation.required"), // <CurrencyInput min={0} />
// }, // </Form.Item>
// ]} // <Form.Item
// > // label={t("jobs.fields.rate_macs")}
// <CurrencyInput min={0} /> // key={`${index}rate_macs`}
// </Form.Item> // name={[field.name, "rate_macs"]}
} // rules={[
<Form.Item // {
label={t("jobs.fields.rate_matd")} // required: true,
key={`${index}rate_matd`} // //message: t("general.validation.required"),
name={[field.name, "rate_matd"]} // },
rules={[ // ]}
{ // >
required: true // <CurrencyInput min={0} />
//message: t("general.validation.required"), // </Form.Item>
} }
]} <Form.Item
> label={t("jobs.fields.rate_matd")}
<CurrencyInput min={0} /> key={`${index}rate_matd`}
</Form.Item> name={[field.name, "rate_matd"]}
<Form.Item rules={[
label={t("jobs.fields.rate_mahw")} {
key={`${index}rate_mahw`} required: true
name={[field.name, "rate_mahw"]} //message: t("general.validation.required"),
rules={[ }
{ ]}
required: true >
//message: t("general.validation.required"), <CurrencyInput min={0} />
} </Form.Item>
]} <Form.Item
> label={t("jobs.fields.rate_mahw")}
<CurrencyInput min={0} /> key={`${index}rate_mahw`}
</Form.Item> name={[field.name, "rate_mahw"]}
<DeleteFilled rules={[
onClick={() => { {
remove(field.name); required: true
}} //message: t("general.validation.required"),
/> }
<FormListMoveArrows move={move} index={index} total={fields.rate_length} /> ]}
</LayoutFormRow> >
<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>
))} </div>
<Form.Item> );
<Button }}
type="dashed" </Form.List>
onClick={() => { </LayoutFormRow>
add(); </>
}}
style={{ width: "100%" }}
>
{t("bodyshop.actions.newlaborrate")}
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</div>
); );
} }

View File

@@ -1,11 +1,10 @@
import { Alert, Form, Switch } from "antd"; import { Alert, Form, Select, Switch } from "antd";
import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import {connect} from "react-redux"; import { connect } from "react-redux";
import {createStructuredSelector} from "reselect"; import { createStructuredSelector } from "reselect";
import {selectBodyshop} from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -16,17 +15,17 @@ const mapDispatchToProps = () => ({
export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoIntellipay); export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoIntellipay);
// noinspection JSUnusedLocalSymbols // noinspection JSUnusedLocalSymbols
export function ShopInfoIntellipay({bodyshop, form}) { export function ShopInfoIntellipay({ bodyshop, form }) {
const {t} = useTranslation(); const { t } = useTranslation();
return ( return (
<> <>
<Form.Item dependencies={[["intellipay_config", "enable_cash_discount"]]}> <Form.Item dependencies={[["intellipay_config", "enable_cash_discount"]]}>
{() => { {() => {
const {intellipay_config} = form.getFieldsValue(); const { intellipay_config } = form.getFieldsValue();
if (intellipay_config?.enable_cash_discount) if (intellipay_config?.enable_cash_discount)
return <Alert message={t("bodyshop.labels.intellipay_cash_discount")}/>; return <Alert message={t("bodyshop.labels.intellipay_cash_discount")} />;
}} }}
</Form.Item> </Form.Item>
@@ -36,7 +35,93 @@ export function ShopInfoIntellipay({bodyshop, form}) {
valuePropName="checked" valuePropName="checked"
name={["intellipay_config", "enable_cash_discount"]} name={["intellipay_config", "enable_cash_discount"]}
> >
<Switch/> <Switch />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("bodyshop.fields.intellipay_config.payment_type")}>
<Form.Item
label={t("bodyshop.fields.intellipay_config.payment_map.visa")}
name={["intellipay_config", "payment_map", "visa"]}
>
<Select showSearch>
{bodyshop.md_payment_types.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.intellipay_config.payment_map.mast")}
name={["intellipay_config", "payment_map", "mast"]}
>
<Select showSearch>
{bodyshop.md_payment_types.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.intellipay_config.payment_map.amex")}
name={["intellipay_config", "payment_map", "amex"]}
>
<Select showSearch>
{bodyshop.md_payment_types.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.intellipay_config.payment_map.disc")}
name={["intellipay_config", "payment_map", "disc"]}
>
<Select showSearch>
{bodyshop.md_payment_types.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.intellipay_config.payment_map.dnrs")}
name={["intellipay_config", "payment_map", "dnrs"]}
>
<Select showSearch>
{bodyshop.md_payment_types.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.intellipay_config.payment_map.jcb")}
name={["intellipay_config", "payment_map", "jcb"]}
>
<Select showSearch>
{bodyshop.md_payment_types.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.intellipay_config.payment_map.intr")}
name={["intellipay_config", "payment_map", "intr"]}
>
<Select showSearch>
{bodyshop.md_payment_types.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
</> </>

View File

@@ -509,6 +509,7 @@ export const GET_JOB_BY_PK = gql`
est_ct_ln est_ct_ln
est_ea est_ea
est_ph1 est_ph1
flat_rate_ats
federal_tax_rate federal_tax_rate
id id
inproduction inproduction
@@ -649,6 +650,7 @@ export const GET_JOB_BY_PK = gql`
policy_no policy_no
production_vars production_vars
rate_ats rate_ats
rate_ats_flat
rate_la1 rate_la1
rate_la2 rate_la2
rate_la3 rate_la3

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3695,6 +3695,7 @@
- est_st - est_st
- est_zip - est_zip
- federal_tax_rate - federal_tax_rate
- flat_rate_ats
- g_bett_amt - g_bett_amt
- id - id
- inproduction - inproduction
@@ -3789,6 +3790,7 @@
- qb_multiple_payers - qb_multiple_payers
- queued_for_parts - queued_for_parts
- rate_ats - rate_ats
- rate_ats_flat
- rate_la1 - rate_la1
- rate_la2 - rate_la2
- rate_la3 - rate_la3
@@ -3965,6 +3967,7 @@
- est_st - est_st
- est_zip - est_zip
- federal_tax_rate - federal_tax_rate
- flat_rate_ats
- g_bett_amt - g_bett_amt
- id - id
- inproduction - inproduction
@@ -4060,6 +4063,7 @@
- qb_multiple_payers - qb_multiple_payers
- queued_for_parts - queued_for_parts
- rate_ats - rate_ats
- rate_ats_flat
- rate_la1 - rate_la1
- rate_la2 - rate_la2
- rate_la3 - rate_la3
@@ -4247,6 +4251,7 @@
- est_st - est_st
- est_zip - est_zip
- federal_tax_rate - federal_tax_rate
- flat_rate_ats
- g_bett_amt - g_bett_amt
- id - id
- inproduction - inproduction
@@ -4342,6 +4347,7 @@
- qb_multiple_payers - qb_multiple_payers
- queued_for_parts - queued_for_parts
- rate_ats - rate_ats
- rate_ats_flat
- rate_la1 - rate_la1
- rate_la2 - rate_la2
- rate_la3 - rate_la3

View File

@@ -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';

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "flat_rate_ats" boolean
null default 'false';

View File

@@ -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;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "rate_ats_flat" numeric
null;

View File

@@ -1485,6 +1485,8 @@ exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) {
materials materials
auto_add_ats auto_add_ats
rate_ats rate_ats
flat_rate_ats
rate_ats_flat
joblines(where: { removed: { _eq: false } }){ joblines(where: { removed: { _eq: false } }){
id id
line_no line_no

View File

@@ -371,6 +371,7 @@ exports.postback = async (req, res) => {
iprequest: values, iprequest: values,
decodedComment decodedComment
}; };
const ipMapping = req.body?.bodyshop?.intellipay_config?.payment_map;
logger.log("intellipay-postback-received", "DEBUG", req.user?.email, null, logResponseMeta); logger.log("intellipay-postback-received", "DEBUG", req.user?.email, null, logResponseMeta);
@@ -417,7 +418,7 @@ exports.postback = async (req, res) => {
amount: p.amount, amount: p.amount,
transactionid: values.authcode, transactionid: values.authcode,
payer: "Customer", payer: "Customer",
type: values.cardtype, type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype,
jobid: p.jobid, jobid: p.jobid,
date: moment(Date.now()), date: moment(Date.now()),
payment_responses: { payment_responses: {
@@ -481,7 +482,7 @@ exports.postback = async (req, res) => {
amount: values.total, amount: values.total,
transactionid: values.authcode, transactionid: values.authcode,
payer: "Customer", payer: "Customer",
type: values.cardtype, type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype,
jobid: values.invoice, jobid: values.invoice,
date: moment(Date.now()) date: moment(Date.now())
} }

View File

@@ -1,7 +1,7 @@
const Dinero = require("dinero.js"); const Dinero = require("dinero.js");
const queries = require("../graphql-client/queries"); const queries = require("../graphql-client/queries");
const adminClient = require("../graphql-client/graphql-client").client; // const adminClient = require("../graphql-client/graphql-client").client;
const _ = require("lodash"); // const _ = require("lodash");
const logger = require("../utils/logger"); const logger = require("../utils/logger");
const InstanceMgr = require("../utils/instanceMgr").default; 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) { } catch (error) {
logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, { logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, {
jobid: id, jobid: id,
@@ -59,7 +61,7 @@ exports.totalsSsu = async function (req, res) {
//IMPORTANT*** These two functions MUST be mirrrored. //IMPORTANT*** These two functions MUST be mirrrored.
async function TotalsServerSide(req, res) { async function TotalsServerSide(req, res) {
const { job, client } = req.body; const { job, client } = req.body;
await AutoAddAtsIfRequired({ job: job, client: client }); await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
try { try {
let ret = { let ret = {
@@ -138,10 +140,11 @@ async function Totals(req, res) {
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, job.id, { 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 { try {
let ret = { let ret = {
@@ -153,7 +156,7 @@ async function Totals(req, res) {
res.status(200).json(ret); res.status(200).json(ret);
} catch (error) { } 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, jobid: job.id,
error: error.message, error: error.message,
stack: error.stack stack: error.stack
@@ -162,40 +165,45 @@ async function Totals(req, res) {
} }
} }
async function AutoAddAtsIfRequired({ job, client }) { async function AtsAdjustmentsIfRequired({ job, client, user }) {
//Check if ATS should be automatically added. if (job.auto_add_ats || job.flat_rate_ats) {
if (job.auto_add_ats) { let atsAmount = 0;
//Get the total sum of hours that should be the ATS amount.
//Check to see if an ATS line exists.
let atsLineIndex = null; let atsLineIndex = null;
const atsHours = job.joblines.reduce((acc, val, index) => {
if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") {
atsLineIndex = index;
}
if ( //Check if ATS should be automatically added.
val.mod_lbr_ty !== "LA1" && if (job.auto_add_ats) {
val.mod_lbr_ty !== "LA2" && const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]);
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;
}
return acc; //Get the total sum of hours that should be the ATS amount.
}, 0); //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 (!excludedLaborTypes.has(val.mod_lbr_ty)) {
//If it does, update it in place, and make sure it is updated for local calculations. 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) { if (atsLineIndex === null) {
const newAtsLine = { const newAtsLine = {
jobid: job.id, jobid: job.id,
alt_partm: null, alt_partm: null,
line_no: 35,
unq_seq: 0, unq_seq: 0,
line_ind: "E", line_ind: "E",
line_desc: "ATS Amount", line_desc: "ATS Amount",
@@ -220,19 +228,42 @@ async function AutoAddAtsIfRequired({ job, client }) {
prt_dsmk_m: 0.0 prt_dsmk_m: 0.0
}; };
const result = await client.request(queries.INSERT_NEW_JOB_LINE, { try {
lineInput: [newAtsLine] 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 { else {
const result = await client.request(queries.UPDATE_JOB_LINE, { try {
line: { act_price: atsAmount }, const result = await client.request(queries.UPDATE_JOB_LINE, {
lineId: job.joblines[atsLineIndex].id line: { act_price: atsAmount },
}); lineId: job.joblines[atsLineIndex].id
job.joblines[atsLineIndex].act_price = atsAmount; });
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 hasMashLine = false;
let hasMahwLine = false; let hasMahwLine = false;
let hasCustomMahwLine; 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); let mashOpCodes = ParseCalopCode(job.materials["MASH"]?.cal_opcode);
jobLines.forEach((item) => { 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; if (!value.part_type && value.db_ref !== "900510" && value.db_ref !== "900511") return acc;
const discountAmount = 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 = {}; let adjustments = {};
//Track all adjustments that need to be made. //Track all adjustments that need to be made.
const linesToAdjustForDiscount = []; //const linesToAdjustForDiscount = [];
Object.keys(parts_tax_rates).forEach((key) => { Object.keys(parts_tax_rates).forEach((key) => {
//Check if there's a discount or a mark up. //Check if there's a discount or a mark up.
let disc = Dinero(), let disc = Dinero(),
@@ -1019,7 +1051,9 @@ function CalculateTaxesTotals(job, otherTotals) {
} }
} catch (error) { } catch (error) {
logger.log("job-totals-USA Key with issue", "error", null, job.id, { 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; exports.default = Totals;
//eslint-disable-next-line no-unused-vars
function DiscountNotAlreadyCounted(jobline, joblines) { function DiscountNotAlreadyCounted(jobline, joblines) {
return false; return false;
} }
@@ -1172,27 +1207,35 @@ function IsTrueOrYes(value) {
return value === true || value === "Y" || value === "y"; return value === true || value === "Y" || value === "y";
} }
async function UpdateJobLines(joblinesToUpdate) { // Function not in use from RO to IO Merger 02/05/2024
if (joblinesToUpdate.length === 0) return; // async function UpdateJobLines(joblinesToUpdate) {
const updateQueries = joblinesToUpdate.map((line, index) => // if (joblinesToUpdate.length === 0) return;
generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index) // const updateQueries = joblinesToUpdate.map((line, index) =>
); // generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index)
const query = ` // );
mutation UPDATE_EST_LINES{ // const query = `
${updateQueries} // 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: "${
const generateUpdateQuery = (lineToUpdate, index) => { // lineToUpdate.id
return ` // }" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) {
update_joblines${index}: update_joblines(where: { id: { _eq: "${ // returning {
lineToUpdate.id // id
}" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) { // }
returning { // }`;
id // };
}
}`;
};

View File

@@ -1,7 +1,5 @@
const Dinero = require("dinero.js"); const Dinero = require("dinero.js");
const queries = require("../graphql-client/queries"); const queries = require("../graphql-client/queries");
const adminClient = require("../graphql-client/graphql-client").client;
const _ = require("lodash");
const logger = require("../utils/logger"); 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(); res.status(200).send();
} catch (error) { } catch (error) {
logger.log("job-totals-ssu-error", "ERROR", req.user.email, id, { logger.log("job-totals-ssu-error", "ERROR", req.user.email, id, {
jobid: id, jobid: id,
error error: error.message,
stack: error.stack
}); });
res.status(503).send(); res.status(503).send();
} }
@@ -57,7 +60,7 @@ exports.totalsSsu = async function (req, res) {
//IMPORTANT*** These two functions MUST be mirrrored. //IMPORTANT*** These two functions MUST be mirrrored.
async function TotalsServerSide(req, res) { async function TotalsServerSide(req, res) {
const { job, client } = req.body; const { job, client } = req.body;
await AutoAddAtsIfRequired({ job: job, client: client }); await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
try { try {
let ret = { let ret = {
@@ -71,7 +74,8 @@ async function TotalsServerSide(req, res) {
} catch (error) { } catch (error) {
logger.log("job-totals-ssu-error", "ERROR", req?.user?.email, job.id, { logger.log("job-totals-ssu-error", "ERROR", req?.user?.email, job.id, {
jobid: job.id, jobid: job.id,
error error: error.message,
stack: error.stack
}); });
res.status(400).send(JSON.stringify(error)); res.status(400).send(JSON.stringify(error));
} }
@@ -83,13 +87,12 @@ async function Totals(req, res) {
const logger = req.logger; const logger = req.logger;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("job-totals", "DEBUG", req.user.email, job.id, { logger.log("job-totals-ssu", "DEBUG", req.user.email, job.id, {
jobid: job.id jobid: job.id,
id: id
}); });
logger.log("job-totals-ssu", "DEBUG", req.user.email, id, null); await AtsAdjustmentsIfRequired({ job, client, user: req.user });
await AutoAddAtsIfRequired({ job, client });
try { try {
let ret = { let ret = {
@@ -101,48 +104,54 @@ async function Totals(req, res) {
res.status(200).json(ret); res.status(200).json(ret);
} catch (error) { } 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, jobid: job.id,
error error: error.message,
stack: error.stack
}); });
res.status(400).send(JSON.stringify(error)); res.status(400).send(JSON.stringify(error));
} }
} }
async function AutoAddAtsIfRequired({ job, client }) { async function AtsAdjustmentsIfRequired({ job, client, user }) {
//Check if ATS should be automatically added. if (job.auto_add_ats || job.flat_rate_ats) {
if (job.auto_add_ats) { let atsAmount = 0;
//Get the total sum of hours that should be the ATS amount.
//Check to see if an ATS line exists.
let atsLineIndex = null; let atsLineIndex = null;
const atsHours = job.joblines.reduce((acc, val, index) => {
if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") {
atsLineIndex = index;
}
if ( //Check if ATS should be automatically added.
val.mod_lbr_ty !== "LA1" && if (job.auto_add_ats) {
val.mod_lbr_ty !== "LA2" && const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]);
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;
}
return acc; //Get the total sum of hours that should be the ATS amount.
}, 0); //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 (!excludedLaborTypes.has(val.mod_lbr_ty)) {
//If it does, update it in place, and make sure it is updated for local calculations. 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) { if (atsLineIndex === null) {
const newAtsLine = { const newAtsLine = {
jobid: job.id, jobid: job.id,
alt_partm: null, alt_partm: null,
line_no: 35,
unq_seq: 0, unq_seq: 0,
line_ind: "E", line_ind: "E",
line_desc: "ATS Amount", line_desc: "ATS Amount",
@@ -167,22 +176,43 @@ async function AutoAddAtsIfRequired({ job, client }) {
prt_dsmk_m: 0.0 prt_dsmk_m: 0.0
}; };
const result = await client.request(queries.INSERT_NEW_JOB_LINE, { try {
lineInput: [newAtsLine] 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 { else {
const result = await client.request(queries.UPDATE_JOB_LINE, { try {
line: { act_price: atsAmount }, const result = await client.request(queries.UPDATE_JOB_LINE, {
lineId: job.joblines[atsLineIndex].id line: { act_price: atsAmount },
}); lineId: job.joblines[atsLineIndex].id
job.joblines[atsLineIndex].act_price = atsAmount; });
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);
} }
} }