File diff suppressed because it is too large
Load Diff
@@ -123,10 +123,10 @@ export default function JobTotalsTableLabor({ job }) {
|
||||
<Space>
|
||||
{t("jobs.labels.mapa")}
|
||||
{job.materials &&
|
||||
job.materials.mapa &&
|
||||
job.materials.mapa.cal_maxdlr !== undefined &&
|
||||
job.materials.MAPA &&
|
||||
job.materials.MAPA.cal_maxdlr !== undefined &&
|
||||
t("jobs.labels.threshhold", {
|
||||
amount: job.materials.mapa.cal_maxdlr,
|
||||
amount: job.materials.MAPA.cal_maxdlr,
|
||||
})}
|
||||
</Space>
|
||||
</Table.Summary.Cell>
|
||||
@@ -147,10 +147,10 @@ export default function JobTotalsTableLabor({ job }) {
|
||||
<Space wrap>
|
||||
{t("jobs.labels.mash")}
|
||||
{job.materials &&
|
||||
job.materials.mash &&
|
||||
job.materials.mash.cal_maxdlr !== undefined &&
|
||||
job.materials.MASH &&
|
||||
job.materials.MASH.cal_maxdlr !== undefined &&
|
||||
t("jobs.labels.threshhold", {
|
||||
amount: job.materials.mash.cal_maxdlr,
|
||||
amount: job.materials.MASH.cal_maxdlr,
|
||||
})}
|
||||
</Space>
|
||||
</Table.Summary.Cell>
|
||||
|
||||
@@ -28,26 +28,36 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
|
||||
total: job.job_totals.totals.subtotal,
|
||||
bold: true,
|
||||
},
|
||||
{
|
||||
key: t("jobs.labels.local_tax_amt"),
|
||||
total: job.job_totals.totals.local_tax,
|
||||
},
|
||||
{
|
||||
key: t("jobs.labels.state_tax_amt"),
|
||||
total: job.job_totals.totals.state_tax,
|
||||
},
|
||||
...(bodyshop.region_config === "CA_BC"
|
||||
|
||||
...(job.job_totals.totals.us_sales_tax_breakdown
|
||||
? [
|
||||
{
|
||||
key: t("jobs.fields.ca_bc_pvrt"),
|
||||
total: job.job_totals.additional.pvrt,
|
||||
key: bodyshop.md_responsibility_centers.taxes.tax_ty1.tax_type1,
|
||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty1Tax,
|
||||
},
|
||||
{
|
||||
key: bodyshop.md_responsibility_centers.taxes.tax_ty2.tax_type2,
|
||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty2Tax,
|
||||
},
|
||||
{
|
||||
key: bodyshop.md_responsibility_centers.taxes.tax_ty3.tax_type3,
|
||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty3Tax,
|
||||
},
|
||||
{
|
||||
key: bodyshop.md_responsibility_centers.taxes.tax_ty4.tax_type4,
|
||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty4Tax,
|
||||
},
|
||||
{
|
||||
key: bodyshop.md_responsibility_centers.taxes.tax_ty5.tax_type5,
|
||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty5Tax,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
key: t("jobs.labels.federal_tax_amt"),
|
||||
total: job.job_totals.totals.federal_tax,
|
||||
},
|
||||
: [
|
||||
{
|
||||
key: t("jobs.labels.state_tax_amt"),
|
||||
total: job.job_totals.totals.state_tax,
|
||||
},
|
||||
]),
|
||||
{
|
||||
key: t("jobs.labels.total_repairs"),
|
||||
total: job.job_totals.totals.total_repairs,
|
||||
@@ -81,7 +91,7 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
|
||||
bold: true,
|
||||
},
|
||||
];
|
||||
}, [job.job_totals, t, bodyshop.region_config]);
|
||||
}, [job.job_totals, t, bodyshop.md_responsibility_centers]);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
useQuery,
|
||||
} from "@apollo/client";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import { Col, Row, notification } from "antd";
|
||||
import { Button, Col, Row, notification } from "antd";
|
||||
import Axios from "axios";
|
||||
import _ from "lodash";
|
||||
import moment from "moment";
|
||||
@@ -31,7 +31,6 @@ import {
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import confirmDialog from "../../utils/asyncConfirm";
|
||||
import CriticalPartsScan from "../../utils/criticalPartsScan";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import JobsAvailableScan from "../jobs-available-scan/jobs-available-scan.component";
|
||||
@@ -90,13 +89,14 @@ export function JobsAvailableContainer({
|
||||
const modalSearchState = useState("");
|
||||
|
||||
//Import Scenario
|
||||
const onOwnerFindModalOk = async () => {
|
||||
const onOwnerFindModalOk = async (lazyData) => {
|
||||
logImEXEvent("job_import_new");
|
||||
|
||||
setOwnerModalVisible(false);
|
||||
setInsertLoading(true);
|
||||
|
||||
const estData = replaceEmpty(estDataRaw.data.available_jobs_by_pk);
|
||||
const estData = replaceEmpty(
|
||||
lazyData?.available_jobs_by_pk || estDataRaw.data.available_jobs_by_pk
|
||||
);
|
||||
|
||||
if (!(estData && estData.est_data)) {
|
||||
//We don't have the right data. Error!
|
||||
@@ -165,47 +165,46 @@ export function JobsAvailableContainer({
|
||||
newJob.kmin = null;
|
||||
}
|
||||
|
||||
insertNewJob({
|
||||
variables: {
|
||||
job: newJob,
|
||||
},
|
||||
})
|
||||
.then((r) => {
|
||||
Axios.post("/job/totalsssu", {
|
||||
id: r.data.insert_jobs.returning[0].id,
|
||||
});
|
||||
try {
|
||||
const r = await insertNewJob({
|
||||
variables: {
|
||||
job: newJob,
|
||||
},
|
||||
});
|
||||
await Axios.post("/job/totalsssu", {
|
||||
id: r.data.insert_jobs.returning[0].id,
|
||||
});
|
||||
|
||||
if (CriticalPartsScanning.treatment === "on") {
|
||||
CriticalPartsScan(r.data.insert_jobs.returning[0].id);
|
||||
}
|
||||
notification["success"]({
|
||||
message: t("jobs.successes.created"),
|
||||
onClick: () => {
|
||||
history.push(`/manage/jobs/${r.data.insert_jobs.returning[0].id}`);
|
||||
},
|
||||
});
|
||||
//Job has been inserted. Clean up the available jobs record.
|
||||
if (CriticalPartsScanning.treatment === "on") {
|
||||
CriticalPartsScan(r.data.insert_jobs.returning[0].id);
|
||||
}
|
||||
notification["success"]({
|
||||
message: t("jobs.successes.created"),
|
||||
onClick: () => {
|
||||
history.push(`/manage/jobs/${r.data.insert_jobs.returning[0].id}`);
|
||||
},
|
||||
});
|
||||
//Job has been inserted. Clean up the available jobs record.
|
||||
|
||||
insertAuditTrail({
|
||||
jobid: r.data.insert_jobs.returning[0].id,
|
||||
operation: AuditTrailMapping.jobimported(),
|
||||
});
|
||||
insertAuditTrail({
|
||||
jobid: r.data.insert_jobs.returning[0].id,
|
||||
operation: AuditTrailMapping.jobimported(),
|
||||
});
|
||||
|
||||
deleteJob({
|
||||
variables: { id: estData.id },
|
||||
}).then((r) => {
|
||||
refetch();
|
||||
setInsertLoading(false);
|
||||
});
|
||||
})
|
||||
.catch((r) => {
|
||||
//error while inserting
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.creating", { error: r.message }),
|
||||
});
|
||||
await deleteJob({
|
||||
variables: { id: estData.id },
|
||||
}).then((r) => {
|
||||
refetch();
|
||||
setInsertLoading(false);
|
||||
});
|
||||
} catch (r) {
|
||||
//error while inserting
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.creating", { error: r.message }),
|
||||
});
|
||||
refetch();
|
||||
setInsertLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
//Suplement scenario
|
||||
@@ -392,6 +391,25 @@ export function JobsAvailableContainer({
|
||||
onCancel={onJobModalCancel}
|
||||
modalSearchState={modalSearchState}
|
||||
/>
|
||||
{currentUser.email.includes("@rome.") ||
|
||||
currentUser.email.includes("@imex.") ? (
|
||||
<Button
|
||||
onClick={async () => {
|
||||
for (const record of data.available_jobs) {
|
||||
//Query the data
|
||||
console.log("Start Job", record.id);
|
||||
const { data } = await loadEstData({
|
||||
variables: { id: record.id },
|
||||
});
|
||||
console.log("Query has been awaited and is complete");
|
||||
await onOwnerFindModalOk(data);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Add all jobs as new.
|
||||
</Button>
|
||||
) : null}
|
||||
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<JobsAvailableTableComponent
|
||||
@@ -423,98 +441,104 @@ function replaceEmpty(someObj, replaceValue = null) {
|
||||
}
|
||||
|
||||
async function CheckTaxRates(estData, bodyshop) {
|
||||
//LKQ Check
|
||||
if (
|
||||
!estData.parts_tax_rates?.PAL ||
|
||||
estData.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`Rome Online has detected that there is a missing tax rate for LKQ parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.parts_tax_rates.PAL) {
|
||||
estData.parts_tax_rates.PAL = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAL",
|
||||
};
|
||||
}
|
||||
estData.parts_tax_rates.PAL.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.parts_tax_rates.PAL.prt_tax_in = true;
|
||||
}
|
||||
}
|
||||
//PAC Check
|
||||
if (
|
||||
!estData.parts_tax_rates?.PAC ||
|
||||
estData.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`Rome Online has detected that there is a missing tax rate for rechromed parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.parts_tax_rates.PAC) {
|
||||
estData.parts_tax_rates.PAC = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAC",
|
||||
};
|
||||
}
|
||||
estData.parts_tax_rates.PAC.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.parts_tax_rates.PAC.prt_tax_in = true;
|
||||
}
|
||||
}
|
||||
// //LKQ Check
|
||||
// if (
|
||||
// !estData.parts_tax_rates?.PAL ||
|
||||
// estData.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
||||
// estData.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
||||
// ) {
|
||||
// const res = await confirmDialog(
|
||||
// `Rome Online has detected that there is a missing tax rate for LKQ parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
// );
|
||||
// if (res) {
|
||||
// if (!estData.parts_tax_rates.PAL) {
|
||||
// estData.parts_tax_rates.PAL = {
|
||||
// prt_discp: 0,
|
||||
// prt_mktyp: true,
|
||||
// prt_mkupp: 0,
|
||||
// prt_type: "PAL",
|
||||
// };
|
||||
// }
|
||||
// estData.parts_tax_rates.PAL.prt_tax_rt =
|
||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
// estData.parts_tax_rates.PAL.prt_tax_in = true;
|
||||
// }
|
||||
// }
|
||||
// //PAC Check
|
||||
// if (
|
||||
// !estData.parts_tax_rates?.PAC ||
|
||||
// estData.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
||||
// estData.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
||||
// ) {
|
||||
// const res = await confirmDialog(
|
||||
// `Rome Online has detected that there is a missing tax rate for rechromed parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
// );
|
||||
// if (res) {
|
||||
// if (!estData.parts_tax_rates.PAC) {
|
||||
// estData.parts_tax_rates.PAC = {
|
||||
// prt_discp: 0,
|
||||
// prt_mktyp: true,
|
||||
// prt_mkupp: 0,
|
||||
// prt_type: "PAC",
|
||||
// };
|
||||
// }
|
||||
// estData.parts_tax_rates.PAC.prt_tax_rt =
|
||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
// estData.parts_tax_rates.PAC.prt_tax_in = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
//PAM Check
|
||||
if (
|
||||
!estData.parts_tax_rates?.PAM ||
|
||||
estData.parts_tax_rates?.PAM?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAM?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`Rome Online has detected that there is a missing tax rate for remanufactured parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.parts_tax_rates.PAM) {
|
||||
estData.parts_tax_rates.PAM = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAM",
|
||||
};
|
||||
}
|
||||
estData.parts_tax_rates.PAM.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.parts_tax_rates.PAM.prt_tax_in = true;
|
||||
}
|
||||
if (!estData.parts_tax_rates?.PAM) {
|
||||
estData.parts_tax_rates.PAM = estData.parts_tax_rates.PAC;
|
||||
}
|
||||
|
||||
if (
|
||||
!estData.parts_tax_rates?.PAR ||
|
||||
estData.parts_tax_rates?.PAR?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAR?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`Rome Online has detected that there is a missing tax rate for recored parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.parts_tax_rates.PAR) {
|
||||
estData.parts_tax_rates.PAR = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAR",
|
||||
};
|
||||
}
|
||||
estData.parts_tax_rates.PAR.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.parts_tax_rates.PAR.prt_tax_in = true;
|
||||
}
|
||||
}
|
||||
// //PAM Check
|
||||
// if (
|
||||
// !estData.parts_tax_rates?.PAM ||
|
||||
// estData.parts_tax_rates?.PAM?.prt_tax_rt === null ||
|
||||
// estData.parts_tax_rates?.PAM?.prt_tax_rt === 0
|
||||
// ) {
|
||||
// const res = await confirmDialog(
|
||||
// `Rome Online has detected that there is a missing tax rate for remanufactured parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
// );
|
||||
// if (res) {
|
||||
// if (!estData.parts_tax_rates.PAM) {
|
||||
// estData.parts_tax_rates.PAM = {
|
||||
// prt_discp: 0,
|
||||
// prt_mktyp: true,
|
||||
// prt_mkupp: 0,
|
||||
// prt_type: "PAM",
|
||||
// };
|
||||
// }
|
||||
// estData.parts_tax_rates.PAM.prt_tax_rt =
|
||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
// estData.parts_tax_rates.PAM.prt_tax_in = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (
|
||||
// !estData.parts_tax_rates?.PAR ||
|
||||
// estData.parts_tax_rates?.PAR?.prt_tax_rt === null ||
|
||||
// estData.parts_tax_rates?.PAR?.prt_tax_rt === 0
|
||||
// ) {
|
||||
// const res = await confirmDialog(
|
||||
// `Rome Online has detected that there is a missing tax rate for recored parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
// );
|
||||
// if (res) {
|
||||
// if (!estData.parts_tax_rates.PAR) {
|
||||
// estData.parts_tax_rates.PAR = {
|
||||
// prt_discp: 0,
|
||||
// prt_mktyp: true,
|
||||
// prt_mkupp: 0,
|
||||
// prt_type: "PAR",
|
||||
// };
|
||||
// }
|
||||
// estData.parts_tax_rates.PAR.prt_tax_rt =
|
||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
// estData.parts_tax_rates.PAR.prt_tax_in = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
//IO-1387 If a sublet line is NOT R&R, use the labor tax. If it is, use the sublet tax rate.
|
||||
//Currently limited to SK shops only.
|
||||
@@ -542,8 +566,7 @@ async function ResolveCCCLineIssues(estData, bodyshop) {
|
||||
//This needs to be done before cleansing unq_seq since some misc prices could move over.
|
||||
estData.joblines.data.forEach((line) => {
|
||||
if (line.misc_amt && line.misc_amt !== 0) {
|
||||
line.act_price = line.misc_amt;
|
||||
line.part_type = "PAS";
|
||||
line.act_price = line.act_price + line.misc_amt;
|
||||
line.tax_part = !!line.misc_tax;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,6 +36,8 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
||||
ret.profitcenter_part = defaults.profits["MAPA"];
|
||||
} else if (lineDesc.includes("ats amount")) {
|
||||
ret.profitcenter_part = defaults.profits["ATS"];
|
||||
} else if (jl.act_price > 0) {
|
||||
ret.profitcenter_part = defaults.profits["PAO"];
|
||||
} else {
|
||||
ret.profitcenter_part = null;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs
|
||||
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
|
||||
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||
import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
|
||||
import JobsDetailRatesLabor from "./jobs-detail-rates.labor.component";
|
||||
import JobsDetailRatesMaterials from "./jobs-detail-rates.materials.component";
|
||||
import JobsDetailRatesOther from "./jobs-detail-rates.other.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
@@ -243,6 +246,9 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
<JobsDetailRatesParts form={form} />
|
||||
<JobsDetailRatesLabor form={form} />
|
||||
<JobsDetailRatesMaterials form={form} />
|
||||
<JobsDetailRatesOther form={form} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
import { Collapse, Form, Switch } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
});
|
||||
|
||||
export function JobsDetailRatesLabor({
|
||||
jobRO,
|
||||
expanded,
|
||||
required = true,
|
||||
form,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
||||
<Collapse.Panel
|
||||
forceRender
|
||||
header={t("jobs.labels.cieca_pfl")}
|
||||
key="cieca_pfl"
|
||||
>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAB")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAB", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAB", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAB", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAB", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAB", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAB", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAD")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAD", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAD", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAD", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAD", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAD", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAD", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAE")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAE", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAE", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAE", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAE", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAE", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAE", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAF")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAF", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAF", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAF", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAF", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAF", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAF", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAG")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAG", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAG", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAG", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAG", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAG", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAG", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAM")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAM", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAM", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAM", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAM", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAM", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAM", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAR")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAR", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAR", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAR", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAR", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAR", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAR", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAS")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAS", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAS", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAS", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAS", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAS", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAS", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAU")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
||||
name={["cieca_pfl", "LAU", "lbr_tax_in"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
||||
name={["cieca_pfl", "LAU", "lbr_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
||||
name={["cieca_pfl", "LAU", "lbr_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
||||
name={["cieca_pfl", "LAU", "lbr_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
||||
name={["cieca_pfl", "LAU", "lbr_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
||||
name={["cieca_pfl", "LAU", "lbr_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
</Collapse.Panel>
|
||||
</Collapse>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(JobsDetailRatesLabor);
|
||||
@@ -0,0 +1,145 @@
|
||||
import { Collapse, Form, Input, InputNumber, Switch } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
});
|
||||
|
||||
export function JobsDetailRatesMaterials({
|
||||
jobRO,
|
||||
expanded,
|
||||
required = true,
|
||||
form,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
||||
<Collapse.Panel
|
||||
forceRender
|
||||
header={t("jobs.labels.materials.materials")}
|
||||
key="materials"
|
||||
>
|
||||
<LayoutFormRow header={t("job.fields.materials.MAPA")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.cal_maxdlr")}
|
||||
name={["materials", "MAPA", "cal_maxdlr"]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.cal_opcode")}
|
||||
name={["materials", "MAPA", "cal_opcode"]}
|
||||
>
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.tax_ind")}
|
||||
name={["materials", "MAPA", "tax_ind"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in1")}
|
||||
name={["materials", "MAPA", "mat_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in2")}
|
||||
name={["materials", "MAPA", "mat_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in3")}
|
||||
name={["materials", "MAPA", "mat_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in4")}
|
||||
name={["materials", "MAPA", "mat_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in5")}
|
||||
name={["materials", "MAPA", "mat_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("job.fields.materials.MASH")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.cal_maxdlr")}
|
||||
name={["materials", "MASH", "cal_maxdlr"]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.cal_opcode")}
|
||||
name={["materials", "MASH", "cal_opcode"]}
|
||||
>
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.tax_ind")}
|
||||
name={["materials", "MASH", "tax_ind"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in1")}
|
||||
name={["materials", "MASH", "mat_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in2")}
|
||||
name={["materials", "MASH", "mat_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in3")}
|
||||
name={["materials", "MASH", "mat_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in4")}
|
||||
name={["materials", "MASH", "mat_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.materials.mat_tx_in5")}
|
||||
name={["materials", "MASH", "mat_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
</Collapse.Panel>
|
||||
</Collapse>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(JobsDetailRatesMaterials);
|
||||
@@ -0,0 +1,104 @@
|
||||
import { Collapse, Form, Switch } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
});
|
||||
|
||||
export function JobsDetailRatesOther({
|
||||
jobRO,
|
||||
expanded,
|
||||
required = true,
|
||||
form,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
||||
<Collapse.Panel
|
||||
forceRender
|
||||
header={t("jobs.labels.cieca_pfo")}
|
||||
key="cieca_pfo"
|
||||
>
|
||||
<LayoutFormRow header={t("jobs.fields.cieca_pfo")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.tow_t_in1")}
|
||||
name={["cieca_pfo", "tow_t_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.tow_t_in2")}
|
||||
name={["cieca_pfo", "tow_t_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.tow_t_in3")}
|
||||
name={["cieca_pfo", "tow_t_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.tow_t_in4")}
|
||||
name={["cieca_pfo", "tow_t_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.tow_t_in5")}
|
||||
name={["cieca_pfo", "tow_t_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.stor_t_in1")}
|
||||
name={["cieca_pfo", "stor_t_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.stor_t_in2")}
|
||||
name={["cieca_pfo", "stor_t_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.stor_t_in3")}
|
||||
name={["cieca_pfo", "stor_t_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.stor_t_in4")}
|
||||
name={["cieca_pfo", "stor_t_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.cieca_pfo.stor_t_in5")}
|
||||
name={["cieca_pfo", "stor_t_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
</Collapse.Panel>
|
||||
</Collapse>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(JobsDetailRatesOther);
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Collapse, Form, InputNumber, Switch } from "antd";
|
||||
import { Collapse, Form, Input, InputNumber, Switch } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -68,11 +68,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAA", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAA", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAA", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAA", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAA", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAC")}>
|
||||
<Form.Item
|
||||
@@ -118,11 +158,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAC", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAC", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAC", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAC", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAC", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAL")}>
|
||||
<Form.Item
|
||||
@@ -168,11 +248,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAL", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAL", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAL", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAL", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAL", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAG")}>
|
||||
<Form.Item
|
||||
@@ -218,11 +338,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAG", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAG", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAG", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAG", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAG", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAM")}>
|
||||
<Form.Item
|
||||
@@ -268,11 +428,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAM", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAM", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAM", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAM", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAM", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAN")}>
|
||||
<Form.Item
|
||||
@@ -318,11 +518,58 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAN", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAN", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAN", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAN", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAN", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ display: "none" }}
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_ty1")}
|
||||
name={["parts_tax_rates", "PAN", "prt_tx_ty1"]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAO")}>
|
||||
<Form.Item
|
||||
@@ -368,11 +615,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAO", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAO", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAO", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAO", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAO", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAP")}>
|
||||
<Form.Item
|
||||
@@ -418,11 +705,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAP", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAP", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAP", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAP", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAP", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAR")}>
|
||||
<Form.Item
|
||||
@@ -468,11 +795,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAR", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAR", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAR", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAR", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAR", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAS")}>
|
||||
<Form.Item
|
||||
@@ -518,11 +885,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PAS", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PAS", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PAS", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PAS", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PAS", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PASL")}>
|
||||
<Form.Item
|
||||
@@ -568,11 +975,51 @@ export function JobsDetailRatesParts({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
precision={4}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
||||
name={["parts_tax_rates", "PASL", "prt_tx_in1"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
||||
name={["parts_tax_rates", "PASL", "prt_tx_in2"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
||||
name={["parts_tax_rates", "PASL", "prt_tx_in3"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
||||
name={["parts_tax_rates", "PASL", "prt_tx_in4"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
||||
name={["parts_tax_rates", "PASL", "prt_tx_in5"]}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.CCDR")}>
|
||||
<Form.Item
|
||||
|
||||
@@ -17,6 +17,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import ShopInfoResponsibilitycentersTaxesComponent from "./shop-info.responsibilitycenters.taxes.component";
|
||||
|
||||
const SelectorDiv = styled.div`
|
||||
.ant-form-item .ant-select {
|
||||
@@ -4445,6 +4446,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
||||
<InputNumber precision={2} />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<ShopInfoResponsibilitycentersTaxesComponent />
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenters.itemexemptcode")}
|
||||
rules={[
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
import { Divider, Form, Input, InputNumber, Space } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ShopInfoResponsibilityCenters);
|
||||
|
||||
export function ShopInfoResponsibilityCenters({ bodyshop }) {
|
||||
//Iteratively build the form items.
|
||||
const formItems = [];
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
const section = [];
|
||||
|
||||
section.push(
|
||||
TaxFormItems({
|
||||
typeNum: tyCounter,
|
||||
rootElements: true,
|
||||
bodyshop,
|
||||
})
|
||||
);
|
||||
for (let iterator = 1; iterator <= 5; iterator++) {
|
||||
section.push(
|
||||
TaxFormItems({
|
||||
typeNum: tyCounter,
|
||||
typeNumIterator: iterator,
|
||||
rootElements: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
formItems.push(Space({ children: section, wrap: true }));
|
||||
formItems.push(<Divider />);
|
||||
}
|
||||
return formItems;
|
||||
}
|
||||
|
||||
function TaxFormItems({ typeNum, typeNumIterator, rootElements, bodyshop }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (rootElements)
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenter_tax_type", {
|
||||
typeNum,
|
||||
typeNumIterator,
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
`tax_type${typeNum}`,
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenters.state_tax")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
"name",
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenter_accountdesc")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
"accountdesc",
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenter_accountitem")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
"accountitem",
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.dms.dms_acctnumber")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
"dms_acctnumber",
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenter_tax_tier", {
|
||||
typeNum,
|
||||
typeNumIterator,
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
`ty${typeNum}_tier${typeNumIterator}`,
|
||||
]}
|
||||
>
|
||||
<InputNumber precision={0} min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenter_tax_thres", {
|
||||
typeNum,
|
||||
typeNumIterator,
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
`ty${typeNum}_thres${typeNumIterator}`,
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenter_tax_rate", {
|
||||
typeNum,
|
||||
typeNumIterator,
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
`ty${typeNum}_rate${typeNumIterator}`,
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.responsibilitycenter_tax_sur", {
|
||||
typeNum,
|
||||
typeNumIterator,
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[
|
||||
"md_responsibility_centers",
|
||||
"taxes",
|
||||
`tax_ty${typeNum}`,
|
||||
`ty${typeNum}_sur${typeNumIterator}`,
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -779,6 +779,9 @@ export const GET_JOB_BY_PK = gql`
|
||||
}
|
||||
}
|
||||
cieca_ttl
|
||||
cieca_pfo
|
||||
cieca_pfl
|
||||
materials
|
||||
csiinvites {
|
||||
id
|
||||
completedon
|
||||
|
||||
@@ -53,6 +53,7 @@ import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import JobsDocumentsLocalGallery from "../../components/jobs-documents-local-gallery/jobs-documents-local-gallery.container";
|
||||
import UndefinedToNull from "../../utils/undefinedtonull";
|
||||
import NoteUpsertModalComponent from "../../components/note-upsert-modal/note-upsert-modal.container";
|
||||
import _ from "lodash";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -103,13 +104,42 @@ export function JobsDetailPage({
|
||||
"category",
|
||||
"referral_source",
|
||||
]),
|
||||
parts_tax_rates: {
|
||||
...job.parts_tax_rates,
|
||||
...values.parts_tax_rates,
|
||||
},
|
||||
// The union and spread is required to keep values coming in from the estimating system that aren't displayed.
|
||||
parts_tax_rates: _.union(
|
||||
Object.keys(job.parts_tax_rates),
|
||||
Object.keys(values.parts_tax_rates)
|
||||
).reduce((acc, val) => {
|
||||
acc[val] = {
|
||||
...job.parts_tax_rates[val],
|
||||
...values.parts_tax_rates[val],
|
||||
};
|
||||
return acc;
|
||||
}, {}),
|
||||
materials: _.union(
|
||||
Object.keys(job.materials),
|
||||
Object.keys(values.materials)
|
||||
).reduce((acc, val) => {
|
||||
acc[val] = {
|
||||
...job.materials[val],
|
||||
...values.materials[val],
|
||||
};
|
||||
return acc;
|
||||
}, {}),
|
||||
cieca_pfl: _.union(
|
||||
Object.keys(job.cieca_pfl),
|
||||
Object.keys(values.cieca_pfl)
|
||||
).reduce((acc, val) => {
|
||||
acc[val] = {
|
||||
...job.cieca_pfl[val],
|
||||
...values.cieca_pfl[val],
|
||||
};
|
||||
return acc;
|
||||
}, {}),
|
||||
cieca_pfo: { ...job.cieca_pfo, ...values.cieca_pfo },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const newTotals = await Axios.post("/job/totalsssu", {
|
||||
id: job.id,
|
||||
});
|
||||
@@ -389,6 +419,21 @@ export function JobsDetailPage({
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailPage);
|
||||
|
||||
const transormJobToForm = (job) => {
|
||||
Object.keys(job.parts_tax_rates).forEach((parttype) => {
|
||||
Object.keys(job.parts_tax_rates[parttype]).forEach((key) => {
|
||||
if (key.includes("tx_in")) {
|
||||
if (
|
||||
job.parts_tax_rates[parttype][key] === "Y" ||
|
||||
job.parts_tax_rates[parttype][key] === true
|
||||
) {
|
||||
job.parts_tax_rates[parttype][key] = true;
|
||||
} else {
|
||||
job.parts_tax_rates[parttype][key] = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
...job,
|
||||
loss_date: job.loss_date ? moment(job.loss_date) : null,
|
||||
|
||||
@@ -473,6 +473,11 @@
|
||||
"responsibilitycenter_accountname": "Account Name",
|
||||
"responsibilitycenter_accountnumber": "Account Number",
|
||||
"responsibilitycenter_rate": "Rate",
|
||||
"responsibilitycenter_tax_rate": "Tax {{typeNum}} Tier {{typeNumIterator}} Rate",
|
||||
"responsibilitycenter_tax_sur": "Tax {{typeNum}} Tier {{typeNumIterator}} Surcharge",
|
||||
"responsibilitycenter_tax_thres": "Tax {{typeNum}} Tier {{typeNumIterator}} Threshold",
|
||||
"responsibilitycenter_tax_tier": "Tax {{typeNum}} Tier {{typeNumIterator}}",
|
||||
"responsibilitycenter_tax_type": "Tax {{typeNum}} Type",
|
||||
"responsibilitycenters": {
|
||||
"ap": "Accounts Payable",
|
||||
"ar": "Accounts Receivable",
|
||||
@@ -613,8 +618,8 @@
|
||||
"jobstatuses": "Job Statuses",
|
||||
"laborrates": "Labor Rates",
|
||||
"licensing": "Licensing",
|
||||
"md_tasks_presets": "Tasks Presets",
|
||||
"md_parts_scan": "Parts Scan Rules",
|
||||
"md_tasks_presets": "Tasks Presets",
|
||||
"md_to_emails": "Preset To Emails",
|
||||
"md_to_emails_emails": "Emails",
|
||||
"messagingpresets": "Messaging Presets",
|
||||
@@ -1439,6 +1444,26 @@
|
||||
"ccf": "CC Refuel",
|
||||
"ccm": "CC Mileage",
|
||||
"cieca_id": "CIECA ID",
|
||||
"cieca_pfl": {
|
||||
"lbr_tax_in": "Tax Labor Indicator",
|
||||
"lbr_tx_in1": "Tax 1 Indicator",
|
||||
"lbr_tx_in2": "Tax 2 Indicator",
|
||||
"lbr_tx_in3": "Tax 3 Indicator",
|
||||
"lbr_tx_in4": "Tax 4 Indicator",
|
||||
"lbr_tx_in5": "Tax 5 Indicator"
|
||||
},
|
||||
"cieca_pfo": {
|
||||
"stor_t_in1": "Storage Tax 1 Indicator",
|
||||
"stor_t_in2": "Storage Tax 2 Indicator",
|
||||
"stor_t_in3": "Storage Tax 3 Indicator",
|
||||
"stor_t_in4": "Storage Tax 4 Indicator",
|
||||
"stor_t_in5": "Storage Tax 5 Indicator",
|
||||
"tow_t_in1": "Tow Tax 1 Indicator",
|
||||
"tow_t_in2": "Tow Tax 2 Indicator",
|
||||
"tow_t_in3": "Tow Tax 3 Indicator",
|
||||
"tow_t_in4": "Tow Tax 4 Indicator",
|
||||
"tow_t_in5": "Tow Tax 5 Indicator"
|
||||
},
|
||||
"claim_total": "Claim Total",
|
||||
"class": "Class",
|
||||
"clm_no": "Claim #",
|
||||
@@ -1552,6 +1577,19 @@
|
||||
"mapa": "Paint Materials",
|
||||
"mash": "Shop Materials",
|
||||
"matd": "Tire Disposal",
|
||||
"materials": {
|
||||
"MAPA": "Paint Materials",
|
||||
"MASH": "Shop Materials",
|
||||
"cal_maxdlr": "Threshhold",
|
||||
"cal_opcode": "OP Codes",
|
||||
"mat_tx_in1": "Tax 1 Indicator",
|
||||
"mat_tx_in2": "Tax 2 Indicator",
|
||||
"mat_tx_in3": "Tax 3 Indicator",
|
||||
"mat_tx_in4": "Tax 4 Indicator",
|
||||
"mat_tx_in5": "Tax 5 Indicator",
|
||||
"materials": "Profile - Materials",
|
||||
"tax_ind": "Tax Indicator"
|
||||
},
|
||||
"other_amount_payable": "Other Amount Payable",
|
||||
"owner": "Owner",
|
||||
"owner_owing": "Cust. Owes",
|
||||
@@ -1574,6 +1612,11 @@
|
||||
"prt_mkupp": "Markup %",
|
||||
"prt_tax_in": "Tax Indicator",
|
||||
"prt_tax_rt": "Part Tax Rate",
|
||||
"prt_tx_in1": "Tax 1 Indicator",
|
||||
"prt_tx_in2": "Tax 2 Indicator",
|
||||
"prt_tx_in3": "Tax 3 Indicator",
|
||||
"prt_tx_in4": "Tax 4 Indicator",
|
||||
"prt_tx_in5": "Tax 5 Indicator",
|
||||
"prt_type": "Part Type"
|
||||
},
|
||||
"partsstatus": "Parts Status",
|
||||
@@ -1701,6 +1744,7 @@
|
||||
"checklistcompletedby": "Checklist completed by {{by}} at {{at}}",
|
||||
"checklistdocuments": "Checklist Documents",
|
||||
"checklists": "Checklists",
|
||||
"cieca_pfl": "Profile - Labor",
|
||||
"closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.",
|
||||
"closejob": "Close Job {{ro_number}}",
|
||||
"closingperiod": "This Invoice Date is outside of the Closing Period.",
|
||||
@@ -1773,6 +1817,9 @@
|
||||
"mapa": "Paint Materials",
|
||||
"markforreexport": "Mark for Re-export",
|
||||
"mash": "Shop Materials",
|
||||
"materials": {
|
||||
"mapa": ""
|
||||
},
|
||||
"multipayers": "Additional Payers",
|
||||
"net_repairs": "Net Repairs",
|
||||
"notes": "Notes",
|
||||
@@ -1799,7 +1846,7 @@
|
||||
"totalreturns": "The total <b>retail</b> amount of returns created for this job."
|
||||
},
|
||||
"ppc": "This line contains a part price change.",
|
||||
"profileadjustments": "Profile Disc./Mkup (Already included above)",
|
||||
"profileadjustments": "Profile Disc./Mkup",
|
||||
"prt_dsmk_total": "Line Item Adjustment",
|
||||
"rates": "Rates",
|
||||
"rates_subtotal": "All Rates Subtotal",
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"scheduledfor": "Cita programada para:",
|
||||
"severalerrorsfound": "",
|
||||
"smartscheduling": "",
|
||||
"smspaymentreminder": "",
|
||||
"suggesteddates": ""
|
||||
},
|
||||
"successes": {
|
||||
@@ -472,6 +473,11 @@
|
||||
"responsibilitycenter_accountname": "",
|
||||
"responsibilitycenter_accountnumber": "",
|
||||
"responsibilitycenter_rate": "",
|
||||
"responsibilitycenter_tax_rate": "",
|
||||
"responsibilitycenter_tax_sur": "",
|
||||
"responsibilitycenter_tax_thres": "",
|
||||
"responsibilitycenter_tax_tier": "",
|
||||
"responsibilitycenter_tax_type": "",
|
||||
"responsibilitycenters": {
|
||||
"ap": "",
|
||||
"ar": "",
|
||||
@@ -1438,6 +1444,26 @@
|
||||
"ccf": "",
|
||||
"ccm": "",
|
||||
"cieca_id": "CIECA ID",
|
||||
"cieca_pfl": {
|
||||
"lbr_tax_in": "",
|
||||
"lbr_tx_in1": "",
|
||||
"lbr_tx_in2": "",
|
||||
"lbr_tx_in3": "",
|
||||
"lbr_tx_in4": "",
|
||||
"lbr_tx_in5": ""
|
||||
},
|
||||
"cieca_pfo": {
|
||||
"stor_t_in1": "",
|
||||
"stor_t_in2": "",
|
||||
"stor_t_in3": "",
|
||||
"stor_t_in4": "",
|
||||
"stor_t_in5": "",
|
||||
"tow_t_in1": "",
|
||||
"tow_t_in2": "",
|
||||
"tow_t_in3": "",
|
||||
"tow_t_in4": "",
|
||||
"tow_t_in5": ""
|
||||
},
|
||||
"claim_total": "Reclamar total",
|
||||
"class": "",
|
||||
"clm_no": "Reclamación #",
|
||||
@@ -1551,6 +1577,19 @@
|
||||
"mapa": "",
|
||||
"mash": "",
|
||||
"matd": "",
|
||||
"materials": {
|
||||
"MAPA": "",
|
||||
"MASH": "",
|
||||
"cal_maxdlr": "",
|
||||
"cal_opcode": "",
|
||||
"mat_tx_in1": "",
|
||||
"mat_tx_in2": "",
|
||||
"mat_tx_in3": "",
|
||||
"mat_tx_in4": "",
|
||||
"mat_tx_in5": "",
|
||||
"materials": "",
|
||||
"tax_ind": ""
|
||||
},
|
||||
"other_amount_payable": "Otra cantidad a pagar",
|
||||
"owner": "Propietario",
|
||||
"owner_owing": "Cust. Debe",
|
||||
@@ -1573,6 +1612,11 @@
|
||||
"prt_mkupp": "",
|
||||
"prt_tax_in": "",
|
||||
"prt_tax_rt": "",
|
||||
"prt_tx_in1": "",
|
||||
"prt_tx_in2": "",
|
||||
"prt_tx_in3": "",
|
||||
"prt_tx_in4": "",
|
||||
"prt_tx_in5": "",
|
||||
"prt_type": ""
|
||||
},
|
||||
"partsstatus": "",
|
||||
@@ -1700,6 +1744,7 @@
|
||||
"checklistcompletedby": "",
|
||||
"checklistdocuments": "",
|
||||
"checklists": "",
|
||||
"cieca_pfl": "",
|
||||
"closeconfirm": "",
|
||||
"closejob": "",
|
||||
"closingperiod": "",
|
||||
@@ -1772,6 +1817,9 @@
|
||||
"mapa": "",
|
||||
"markforreexport": "",
|
||||
"mash": "",
|
||||
"materials": {
|
||||
"mapa": ""
|
||||
},
|
||||
"multipayers": "",
|
||||
"net_repairs": "",
|
||||
"notes": "Notas",
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"scheduledfor": "Rendez-vous prévu pour:",
|
||||
"severalerrorsfound": "",
|
||||
"smartscheduling": "",
|
||||
"smspaymentreminder": "",
|
||||
"suggesteddates": ""
|
||||
},
|
||||
"successes": {
|
||||
@@ -472,6 +473,11 @@
|
||||
"responsibilitycenter_accountname": "",
|
||||
"responsibilitycenter_accountnumber": "",
|
||||
"responsibilitycenter_rate": "",
|
||||
"responsibilitycenter_tax_rate": "",
|
||||
"responsibilitycenter_tax_sur": "",
|
||||
"responsibilitycenter_tax_thres": "",
|
||||
"responsibilitycenter_tax_tier": "",
|
||||
"responsibilitycenter_tax_type": "",
|
||||
"responsibilitycenters": {
|
||||
"ap": "",
|
||||
"ar": "",
|
||||
@@ -1438,6 +1444,26 @@
|
||||
"ccf": "",
|
||||
"ccm": "",
|
||||
"cieca_id": "CIECA ID",
|
||||
"cieca_pfl": {
|
||||
"lbr_tax_in": "",
|
||||
"lbr_tx_in1": "",
|
||||
"lbr_tx_in2": "",
|
||||
"lbr_tx_in3": "",
|
||||
"lbr_tx_in4": "",
|
||||
"lbr_tx_in5": ""
|
||||
},
|
||||
"cieca_pfo": {
|
||||
"stor_t_in1": "",
|
||||
"stor_t_in2": "",
|
||||
"stor_t_in3": "",
|
||||
"stor_t_in4": "",
|
||||
"stor_t_in5": "",
|
||||
"tow_t_in1": "",
|
||||
"tow_t_in2": "",
|
||||
"tow_t_in3": "",
|
||||
"tow_t_in4": "",
|
||||
"tow_t_in5": ""
|
||||
},
|
||||
"claim_total": "Total réclamation",
|
||||
"class": "",
|
||||
"clm_no": "Prétendre #",
|
||||
@@ -1551,6 +1577,19 @@
|
||||
"mapa": "",
|
||||
"mash": "",
|
||||
"matd": "",
|
||||
"materials": {
|
||||
"MAPA": "",
|
||||
"MASH": "",
|
||||
"cal_maxdlr": "",
|
||||
"cal_opcode": "",
|
||||
"mat_tx_in1": "",
|
||||
"mat_tx_in2": "",
|
||||
"mat_tx_in3": "",
|
||||
"mat_tx_in4": "",
|
||||
"mat_tx_in5": "",
|
||||
"materials": "",
|
||||
"tax_ind": ""
|
||||
},
|
||||
"other_amount_payable": "Autre montant à payer",
|
||||
"owner": "Propriétaire",
|
||||
"owner_owing": "Cust. Owes",
|
||||
@@ -1573,6 +1612,11 @@
|
||||
"prt_mkupp": "",
|
||||
"prt_tax_in": "",
|
||||
"prt_tax_rt": "",
|
||||
"prt_tx_in1": "",
|
||||
"prt_tx_in2": "",
|
||||
"prt_tx_in3": "",
|
||||
"prt_tx_in4": "",
|
||||
"prt_tx_in5": "",
|
||||
"prt_type": ""
|
||||
},
|
||||
"partsstatus": "",
|
||||
@@ -1700,6 +1744,7 @@
|
||||
"checklistcompletedby": "",
|
||||
"checklistdocuments": "",
|
||||
"checklists": "",
|
||||
"cieca_pfl": "",
|
||||
"closeconfirm": "",
|
||||
"closejob": "",
|
||||
"closingperiod": "",
|
||||
@@ -1772,6 +1817,9 @@
|
||||
"mapa": "",
|
||||
"markforreexport": "",
|
||||
"mash": "",
|
||||
"materials": {
|
||||
"mapa": ""
|
||||
},
|
||||
"multipayers": "",
|
||||
"net_repairs": "",
|
||||
"notes": "Remarques",
|
||||
|
||||
@@ -3274,6 +3274,7 @@
|
||||
- cat_no
|
||||
- category
|
||||
- cieca_pfl
|
||||
- cieca_pfo
|
||||
- cieca_pft
|
||||
- cieca_stl
|
||||
- cieca_ttl
|
||||
@@ -3542,6 +3543,7 @@
|
||||
- cat_no
|
||||
- category
|
||||
- cieca_pfl
|
||||
- cieca_pfo
|
||||
- cieca_pft
|
||||
- cieca_stl
|
||||
- cieca_ttl
|
||||
@@ -3821,6 +3823,7 @@
|
||||
- cat_no
|
||||
- category
|
||||
- cieca_pfl
|
||||
- cieca_pfo
|
||||
- cieca_pft
|
||||
- cieca_stl
|
||||
- cieca_ttl
|
||||
|
||||
@@ -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 "cieca_pfo" jsonb
|
||||
-- null default jsonb_build_object();
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" add column "cieca_pfo" jsonb
|
||||
null default jsonb_build_object();
|
||||
@@ -19,8 +19,8 @@ require("dotenv").config({
|
||||
});
|
||||
|
||||
async function RunTheTest() {
|
||||
const bodyshopids = ["6c63a820-542c-497e-8c82-0cc38fb2bbca"];
|
||||
const bearerToken = `Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImM2MGI5ZGUwODBmZmFmYmZjMTgzMzllY2Q0NGFjNzdmN2ZhNGU4ZDMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiUm9tZSBEZXZlbG9wbWVudCIsImh0dHBzOi8vaGFzdXJhLmlvL2p3dC9jbGFpbXMiOnsieC1oYXN1cmEtZGVmYXVsdC1yb2xlIjoiYWRtaW4iLCJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbImFkbWluIl0sIngtaGFzdXJhLXVzZXItaWQiOiJ0NlltMU5EbENET1BacjNGOWJndVdINExoU1gyIn0sImlvYWRtaW4iOnRydWUsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9yb21lLXByb2QtMSIsImF1ZCI6InJvbWUtcHJvZC0xIiwiYXV0aF90aW1lIjoxNjkyODk5ODE2LCJ1c2VyX2lkIjoidDZZbTFORGxDRE9QWnIzRjliZ3VXSDRMaFNYMiIsInN1YiI6InQ2WW0xTkRsQ0RPUFpyM0Y5Ymd1V0g0TGhTWDIiLCJpYXQiOjE2OTMyNTA1NjIsImV4cCI6MTY5MzI1NDE2MiwiZW1haWwiOiJwYXRyaWNrQHJvbWUuZGV2IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7ImVtYWlsIjpbInBhdHJpY2tAcm9tZS5kZXYiXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.POr8U2pP4XtTJEDRJ_BveRkCs92CIfDDdfU24OYe_aZh6LFPN0bQukNHXrLt3gaD30SUcg5mgmI2VUphgmwviMEGY-zizPC9o6GUKEEppZWQXfrfTyJNa1VKKH9h5zZPPFFW8UJRMi131pCc0ev26GS8Do-FJAgwHLJd6Jp2RbbqiCIeafNMhQCEoXohOk-VArNe7tPAb6-IjxqGVyNqvVyIo6niSXYvmgNjyF1WnnIw0CsnPoJlc5kVMtRdYeshJI7V117MOlUwZicF62vsm32eCunjn3qhN5XsujI7gy9us3vzwhdR1lxISZCLhLOXEYHPL373HJh7I_KN1C3NuA`;
|
||||
const bodyshopids = ["a7ee1503-ee05-4a02-b80e-bdb11d1cc8ac"];
|
||||
const bearerToken = `Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkNWM1ZTlmNTdjOWI2NDYzYzg1ODQ1YTA4OTlhOWQ0MTI5MmM4YzMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiUm9tZSBEZXZlbG9wbWVudCIsImh0dHBzOi8vaGFzdXJhLmlvL2p3dC9jbGFpbXMiOnsieC1oYXN1cmEtZGVmYXVsdC1yb2xlIjoidXNlciIsIngtaGFzdXJhLWFsbG93ZWQtcm9sZXMiOlsidXNlciJdLCJ4LWhhc3VyYS11c2VyLWlkIjoidDZZbTFORGxDRE9QWnIzRjliZ3VXSDRMaFNYMiJ9LCJpb2FkbWluIjp0cnVlLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vcm9tZS1wcm9kLTEiLCJhdWQiOiJyb21lLXByb2QtMSIsImF1dGhfdGltZSI6MTY5NTE1MDU0NywidXNlcl9pZCI6InQ2WW0xTkRsQ0RPUFpyM0Y5Ymd1V0g0TGhTWDIiLCJzdWIiOiJ0NlltMU5EbENET1BacjNGOWJndVdINExoU1gyIiwiaWF0IjoxNjk1ODUzNTI5LCJleHAiOjE2OTU4NTcxMjksImVtYWlsIjoicGF0cmlja0Byb21lLmRldiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJwYXRyaWNrQHJvbWUuZGV2Il19LCJzaWduX2luX3Byb3ZpZGVyIjoicGFzc3dvcmQifX0.cLDqjTy7dyo3MYwRuWaDxFz0faqDqK5elCFy78qgr4IMhWQEZKdO1FIJoBmxuGn7qbJUfgSRettkYx5YcY3AzrzlTu7UbL6yz7yMyCUjIOF189OLhN-IZH8sHbyb4xvpP4GvYLkaEoBjTCvMaSW-9ycpM3uvYbjgCO81p2gGjo56E2TGoT8tfWE-NGO2nGv_-UacTrZWh_8CGijeZrC9QXeY3DSXTykRV1_xWA7UQNi8IeKphgXsVkOsQI6xC5fXCBWThOfx2RN5af36fU-b3aVXCq21M5y3tJg1IZbzlcYyyBw8Gc71wfp5bjKU92EPH8yCnbic7B5c5Yzk2ikWZg`;
|
||||
const { jobs } = await client.request(
|
||||
gql`
|
||||
query GET_JOBS($bodyshopids: [uuid!]!) {
|
||||
@@ -42,7 +42,10 @@ async function RunTheTest() {
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const job of jobs) {
|
||||
for (const [index, job] of jobs.entries()) {
|
||||
process.stdout.cursorTo(0);
|
||||
process.stdout.write(`Processing job ${index + 1} of ${jobs.length}`);
|
||||
|
||||
try {
|
||||
await axios.post(
|
||||
`http://localhost:4000/job/totalsssu`,
|
||||
@@ -61,6 +64,7 @@ async function RunTheTest() {
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ins_co_nm
|
||||
comment
|
||||
}
|
||||
}
|
||||
`,
|
||||
@@ -73,19 +77,20 @@ async function RunTheTest() {
|
||||
id: newjob.id,
|
||||
owner: `${newjob.ownr_fn} ${newjob.ownr_ln} ${job.ownr_co_nm || ""}`,
|
||||
ins_co: newjob.ins_co_nm,
|
||||
comment: newjob.comment,
|
||||
};
|
||||
|
||||
const calcTotal = newjob.job_totals.totals.total_repairs.amount;
|
||||
const ttlTotal = newjob.cieca_ttl.data.g_ttl_amt * 100;
|
||||
result.difference = (calcTotal - ttlTotal) / 100;
|
||||
|
||||
if (Math.abs(calcTotal - ttlTotal) > 5) {
|
||||
if (Math.abs(calcTotal - ttlTotal) > 3) {
|
||||
//Diff is greater than 5 cents. Fail it.
|
||||
result.result = "***FAIL***";
|
||||
} else {
|
||||
result.result = "PASS";
|
||||
}
|
||||
console.log(`${result.result} => RO ${job.ro_number}`);
|
||||
// console.log(`${result.result} => RO ${job.ro_number} - ${job.id} `);
|
||||
|
||||
results.push(result);
|
||||
} catch (error) {
|
||||
@@ -97,7 +102,7 @@ async function RunTheTest() {
|
||||
}
|
||||
}
|
||||
|
||||
console.table(results);
|
||||
console.table(results.filter((r) => r.result !== "PASS"));
|
||||
const summary = results.reduce(
|
||||
(acc, val) => {
|
||||
if (val.result === "PASS") {
|
||||
@@ -115,3 +120,15 @@ async function RunTheTest() {
|
||||
}
|
||||
|
||||
RunTheTest();
|
||||
|
||||
// mutation {
|
||||
// delete_jobs(where: {shopid: {_eq: "a7ee1503-ee05-4a02-b80e-bdb11d1cc8ac"}}) {
|
||||
// affected_rows
|
||||
// }
|
||||
// delete_owners(where: {shopid: {_eq: "a7ee1503-ee05-4a02-b80e-bdb11d1cc8ac"}}) {
|
||||
// affected_rows
|
||||
// }
|
||||
// delete_vehicles(where: {shopid: {_eq: "a7ee1503-ee05-4a02-b80e-bdb11d1cc8ac"}}) {
|
||||
// affected_rows
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -34,15 +34,10 @@ exports.default = function ({
|
||||
}
|
||||
//Parts Lines Mappings.
|
||||
if (jobline.profitcenter_part) {
|
||||
let DineroAmount = Dinero({
|
||||
amount: Math.round((jobline.act_price || 0) * 100),
|
||||
}).multiply(jobline.part_qty || 1);
|
||||
|
||||
// console.log("Have a part discount", jobline);
|
||||
DineroAmount = DineroAmount.add(
|
||||
const discountAmount =
|
||||
((jobline.prt_dsmk_m && jobline.prt_dsmk_m !== 0) ||
|
||||
(jobline.prt_dsmk_p && jobline.prt_dsmk_p !== 0)) &&
|
||||
DiscountNotAlreadyCounted(jobline, jobs_by_pk.joblines)
|
||||
DiscountNotAlreadyCounted(jobline, jobs_by_pk.joblines)
|
||||
? jobline.prt_dsmk_m
|
||||
? Dinero({ amount: Math.round(jobline.prt_dsmk_m * 100) })
|
||||
: Dinero({
|
||||
@@ -51,8 +46,13 @@ exports.default = function ({
|
||||
.multiply(jobline.part_qty || 0)
|
||||
.percentage(Math.abs(jobline.prt_dsmk_p || 0))
|
||||
.multiply(jobline.prt_dsmk_p > 0 ? 1 : -1)
|
||||
: Dinero()
|
||||
);
|
||||
: Dinero();
|
||||
|
||||
let DineroAmount = Dinero({
|
||||
amount: Math.round((jobline.act_price || 0) * 100),
|
||||
})
|
||||
.multiply(jobline.part_qty || 0)
|
||||
.add(discountAmount);
|
||||
|
||||
const account = responsibilityCenters.profits.find(
|
||||
(i) => jobline.profitcenter_part.toLowerCase() === i.name.toLowerCase()
|
||||
@@ -393,7 +393,7 @@ exports.default = function ({
|
||||
|
||||
//Add Towing, storage and adjustment lines.
|
||||
|
||||
if (jobs_by_pk.towing_payable && jobs_by_pk.towing_payable !== 0) {
|
||||
if (jobs_by_pk.job_totals.additional.towing.amount > 0) {
|
||||
if (qbo) {
|
||||
//Going to always assume that we need to apply GST and PST for labor.
|
||||
const taxAccountCode = findTaxCode(
|
||||
@@ -417,9 +417,9 @@ exports.default = function ({
|
||||
: taxCodes[taxAccountCode];
|
||||
InvoiceLineAdd.push({
|
||||
DetailType: "SalesItemLineDetail",
|
||||
Amount: Dinero({
|
||||
amount: Math.round((jobs_by_pk.towing_payable || 0) * 100),
|
||||
}).toFormat(DineroQbFormat),
|
||||
Amount: Dinero(jobs_by_pk.job_totals.additional.towing).toFormat(
|
||||
DineroQbFormat
|
||||
),
|
||||
SalesItemLineDetail: {
|
||||
...(jobs_by_pk.class
|
||||
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||
@@ -442,9 +442,9 @@ exports.default = function ({
|
||||
},
|
||||
Desc: "Towing",
|
||||
Quantity: 1,
|
||||
Amount: Dinero({
|
||||
amount: Math.round((jobs_by_pk.towing_payable || 0) * 100),
|
||||
}).toFormat(DineroQbFormat),
|
||||
Amount: Dinero(jobs_by_pk.job_totals.additional.towing).toFormat(
|
||||
DineroQbFormat
|
||||
),
|
||||
SalesTaxCodeRef: {
|
||||
FullName:
|
||||
bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON",
|
||||
@@ -452,7 +452,7 @@ exports.default = function ({
|
||||
});
|
||||
}
|
||||
}
|
||||
if (jobs_by_pk.storage_payable && jobs_by_pk.storage_payable !== 0) {
|
||||
if (jobs_by_pk.job_totals.additional.storage.amount > 0) {
|
||||
if (qbo) {
|
||||
//Going to always assume that we need to apply GST and PST for labor.
|
||||
const taxAccountCode = findTaxCode(
|
||||
@@ -476,9 +476,9 @@ exports.default = function ({
|
||||
: taxCodes[taxAccountCode];
|
||||
InvoiceLineAdd.push({
|
||||
DetailType: "SalesItemLineDetail",
|
||||
Amount: Dinero({
|
||||
amount: Math.round((jobs_by_pk.storage_payable || 0) * 100),
|
||||
}).toFormat(DineroQbFormat),
|
||||
Amount: Dinero(
|
||||
jobs_by_pk.job_totals.additional.storage.amount
|
||||
).toFormat(DineroQbFormat),
|
||||
SalesItemLineDetail: {
|
||||
...(jobs_by_pk.class
|
||||
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||
@@ -501,9 +501,9 @@ exports.default = function ({
|
||||
},
|
||||
Desc: "Storage",
|
||||
Quantity: 1,
|
||||
Amount: Dinero({
|
||||
amount: Math.round((jobs_by_pk.storage_payable || 0) * 100),
|
||||
}).toFormat(DineroQbFormat),
|
||||
Amount: Dinero(
|
||||
jobs_by_pk.job_totals.additional.storage.amount
|
||||
).toFormat(DineroQbFormat),
|
||||
SalesTaxCodeRef: {
|
||||
FullName:
|
||||
bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON",
|
||||
@@ -574,123 +574,55 @@ exports.default = function ({
|
||||
const job_totals = jobs_by_pk.job_totals;
|
||||
|
||||
const federal_tax = Dinero(job_totals.totals.federal_tax);
|
||||
const state_tax = Dinero(job_totals.totals.state_tax);
|
||||
const local_tax = Dinero(job_totals.totals.local_tax);
|
||||
|
||||
if (federal_tax.getAmount() > 0) {
|
||||
if (qbo) {
|
||||
// do qbo
|
||||
} else {
|
||||
InvoiceLineAdd.push({
|
||||
ItemRef: {
|
||||
FullName:
|
||||
bodyshop.md_responsibility_centers.taxes.federal.accountitem,
|
||||
},
|
||||
Desc: bodyshop.md_responsibility_centers.taxes.federal.accountdesc,
|
||||
Amount: federal_tax.toFormat(DineroQbFormat),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (state_tax.getAmount() > 0) {
|
||||
if (qbo) {
|
||||
// do qbo
|
||||
} else {
|
||||
InvoiceLineAdd.push({
|
||||
ItemRef: {
|
||||
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
|
||||
},
|
||||
Desc: bodyshop.md_responsibility_centers.taxes.state.accountdesc,
|
||||
Amount: state_tax.toFormat(DineroQbFormat),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (local_tax.getAmount() > 0) {
|
||||
if (qbo) {
|
||||
// do qbo
|
||||
} else {
|
||||
InvoiceLineAdd.push({
|
||||
ItemRef: {
|
||||
FullName: bodyshop.md_responsibility_centers.taxes.local.accountitem,
|
||||
},
|
||||
Desc: bodyshop.md_responsibility_centers.taxes.local.accountdesc,
|
||||
Amount: local_tax.toFormat(DineroQbFormat),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//Region Specific
|
||||
const { ca_bc_pvrt } = jobs_by_pk;
|
||||
if (ca_bc_pvrt) {
|
||||
if (qbo) {
|
||||
InvoiceLineAdd.push({
|
||||
DetailType: "SalesItemLineDetail",
|
||||
Amount: Dinero({ amount: (ca_bc_pvrt || 0) * 100 }).toFormat(
|
||||
DineroQbFormat
|
||||
),
|
||||
SalesItemLineDetail: {
|
||||
...(jobs_by_pk.class
|
||||
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||
: {}),
|
||||
const QboTaxId =
|
||||
process.env.COUNTRY === "USA"
|
||||
? CheckQBOUSATaxID({
|
||||
// jobline: jobline,
|
||||
type: "adjustment",
|
||||
job: jobs_by_pk,
|
||||
})
|
||||
: taxCodes[taxAccountCode];
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
const taxAmount = Dinero(
|
||||
job_totals.totals.us_sales_tax_breakdown[`ty${tyCounter}Tax`]
|
||||
);
|
||||
console.log(`Tax ${tyCounter}`, taxAmount.toFormat());
|
||||
if (taxAmount.getAmount() > 0) {
|
||||
if (qbo) {
|
||||
InvoiceLineAdd.push({
|
||||
DetailType: "SalesItemLineDetail",
|
||||
Amount: taxAmount.toFormat(DineroQbFormat),
|
||||
SalesItemLineDetail: {
|
||||
...(jobs_by_pk.class
|
||||
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||
: {}),
|
||||
ItemRef: {
|
||||
value:
|
||||
items[
|
||||
responsibilityCenters.taxes[`tax_ty${tyCounter}`].accountitem
|
||||
],
|
||||
},
|
||||
TaxCodeRef: {
|
||||
value: QboTaxId,
|
||||
},
|
||||
Qty: 1,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
InvoiceLineAdd.push({
|
||||
ItemRef: {
|
||||
value: items["PVRT"],
|
||||
FullName:
|
||||
bodyshop.md_responsibility_centers.taxes[`tax_ty${tyCounter}`]
|
||||
.accountitem,
|
||||
},
|
||||
Qty: 1,
|
||||
TaxCodeRef: {
|
||||
value:
|
||||
taxCodes[
|
||||
findTaxCode(
|
||||
{
|
||||
local: false,
|
||||
federal: process.env.COUNTRY === "USA" ? false : true,
|
||||
state: false,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
)
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
InvoiceLineAdd.push({
|
||||
ItemRef: {
|
||||
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
|
||||
},
|
||||
Desc: "PVRT",
|
||||
Amount: Dinero({ amount: (ca_bc_pvrt || 0) * 100 }).toFormat(
|
||||
DineroQbFormat
|
||||
),
|
||||
});
|
||||
Desc: bodyshop.md_responsibility_centers.taxes[`tax_ty${tyCounter}`]
|
||||
.accountdesc,
|
||||
Amount: taxAmount.toFormat(DineroQbFormat),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//QB USA with GST
|
||||
//This was required for the No. 1 Collision Group.
|
||||
// if (
|
||||
// bodyshop.accountingconfig &&
|
||||
// bodyshop.accountingconfig.qbo &&
|
||||
// bodyshop.accountingconfig.qbo_usa &&
|
||||
// bodyshop.region_config.includes("CA_")
|
||||
// ) {
|
||||
// InvoiceLineAdd.push({
|
||||
// DetailType: "SalesItemLineDetail",
|
||||
// Amount: Dinero(jobs_by_pk.job_totals.totals.federal_tax).toFormat(
|
||||
// DineroQbFormat
|
||||
// ),
|
||||
// SalesItemLineDetail: {
|
||||
// ...(jobs_by_pk.class
|
||||
// ? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||
// : {}),
|
||||
// ItemRef: {
|
||||
// value:
|
||||
// items[bodyshop.md_responsibility_centers.taxes.federal.accountitem],
|
||||
// },
|
||||
// Qty: 1,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
|
||||
if (!qbo && InvoiceLineAdd.length === 0) {
|
||||
//Handle the scenario where there is a $0 sale invoice.
|
||||
InvoiceLineAdd.push({
|
||||
@@ -832,17 +764,19 @@ exports.createMultiQbPayerLines = function ({
|
||||
};
|
||||
|
||||
function CheckQBOUSATaxID({ jobline, job, type }) {
|
||||
if (type === "labor") {
|
||||
return jobline.lbr_tax ? "TAX" : "NON";
|
||||
} else if (type === "part") {
|
||||
return jobline.tax_part ? "TAX" : "NON";
|
||||
} else if (type === "materials") {
|
||||
return job.tax_paint_mat_rt > 0 ? "TAX" : "NON";
|
||||
} else if (type === " towing") {
|
||||
return true ? "TAX" : "NON";
|
||||
} else if (type === "adjustment") {
|
||||
return false ? "TAX" : "NON";
|
||||
} else {
|
||||
throw new Error(`Unknown type to calculate tax id: ${type} `);
|
||||
}
|
||||
//Replacing this to be all non-taxable items with the refactor of parts tax rates.
|
||||
return "NON";
|
||||
// if (type === "labor") {
|
||||
// return jobline.lbr_tax ? "TAX" : "NON";
|
||||
// } else if (type === "part") {
|
||||
// return jobline.tax_part ? "TAX" : "NON";
|
||||
// } else if (type === "materials") {
|
||||
// return job.tax_paint_mat_rt > 0 ? "TAX" : "NON";
|
||||
// } else if (type === " towing") {
|
||||
// return true ? "TAX" : "NON";
|
||||
// } else if (type === "adjustment") {
|
||||
// return false ? "TAX" : "NON";
|
||||
// } else {
|
||||
// throw new Error(`Unknown type to calculate tax id: ${type} `);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -25,26 +25,61 @@ exports.default = async function (socket, jobid) {
|
||||
const { bodyshop } = job;
|
||||
|
||||
const taxAllocations = {
|
||||
local: {
|
||||
center: bodyshop.md_responsibility_centers.taxes.local.name,
|
||||
sale: Dinero(job.job_totals.totals.local_tax),
|
||||
// local: {
|
||||
// center: bodyshop.md_responsibility_centers.taxes.local.name,
|
||||
// sale: Dinero(job.job_totals.totals.local_tax),
|
||||
// cost: Dinero(),
|
||||
// profitCenter: bodyshop.md_responsibility_centers.taxes.local,
|
||||
// costCenter: bodyshop.md_responsibility_centers.taxes.local,
|
||||
// },
|
||||
// state: {
|
||||
// center: bodyshop.md_responsibility_centers.taxes.state.name,
|
||||
// sale: Dinero(job.job_totals.totals.state_tax),
|
||||
// cost: Dinero(),
|
||||
// profitCenter: bodyshop.md_responsibility_centers.taxes.state,
|
||||
// costCenter: bodyshop.md_responsibility_centers.taxes.state,
|
||||
// },
|
||||
// federal: {
|
||||
// center: bodyshop.md_responsibility_centers.taxes.federal.name,
|
||||
// sale: Dinero(job.job_totals.totals.federal_tax),
|
||||
// cost: Dinero(),
|
||||
// profitCenter: bodyshop.md_responsibility_centers.taxes.federal,
|
||||
// costCenter: bodyshop.md_responsibility_centers.taxes.federal,
|
||||
// },
|
||||
tax_ty1: {
|
||||
center: bodyshop.md_responsibility_centers.taxes[`tax_ty1`].name,
|
||||
sale: Dinero(job_totals.totals.us_sales_tax_breakdown[`ty1Tax`]),
|
||||
cost: Dinero(),
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes.local,
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes.local,
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty1`],
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty1`],
|
||||
},
|
||||
state: {
|
||||
center: bodyshop.md_responsibility_centers.taxes.state.name,
|
||||
sale: Dinero(job.job_totals.totals.state_tax),
|
||||
tax_ty2: {
|
||||
center: bodyshop.md_responsibility_centers.taxes[`tax_ty2`].name,
|
||||
sale: Dinero(job_totals.totals.us_sales_tax_breakdown[`ty2Tax`]),
|
||||
cost: Dinero(),
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes.state,
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes.state,
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty2`],
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty2`],
|
||||
},
|
||||
federal: {
|
||||
center: bodyshop.md_responsibility_centers.taxes.federal.name,
|
||||
sale: Dinero(job.job_totals.totals.federal_tax),
|
||||
tax_ty3: {
|
||||
center: bodyshop.md_responsibility_centers.taxes[`tax_ty3`].name,
|
||||
sale: Dinero(job_totals.totals.us_sales_tax_breakdown[`ty3Tax`]),
|
||||
cost: Dinero(),
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes.federal,
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes.federal,
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty3`],
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty3`],
|
||||
},
|
||||
tax_ty4: {
|
||||
center: bodyshop.md_responsibility_centers.taxes[`tax_ty4`].name,
|
||||
sale: Dinero(job_totals.totals.us_sales_tax_breakdown[`ty4Tax`]),
|
||||
cost: Dinero(),
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty4`],
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty4`],
|
||||
},
|
||||
tax_ty5: {
|
||||
center: bodyshop.md_responsibility_centers.taxes[`tax_ty5`].name,
|
||||
sale: Dinero(job_totals.totals.us_sales_tax_breakdown[`ty5Tax`]),
|
||||
cost: Dinero(),
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty5`],
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty5`],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1168,10 +1168,8 @@ exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) {
|
||||
shopid
|
||||
est_ct_ln
|
||||
cieca_pfl
|
||||
vehicle{
|
||||
id
|
||||
notes
|
||||
}
|
||||
cieca_pft
|
||||
cieca_pfo
|
||||
est_ph1
|
||||
est_ea
|
||||
selling_dealer
|
||||
@@ -1292,19 +1290,6 @@ vehicle{
|
||||
prt_dsmk_m
|
||||
misc_amt
|
||||
misc_tax
|
||||
parts_order_lines {
|
||||
id
|
||||
parts_order {
|
||||
id
|
||||
order_number
|
||||
order_date
|
||||
user_email
|
||||
vendor {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
@@ -972,6 +972,8 @@ const getAdditionalCostCenter = (jl, profitCenters) => {
|
||||
return profitCenters["ATS"];
|
||||
} else if (lineDesc.includes("towing")) {
|
||||
return profitCenters["TOW"];
|
||||
} else if (jl.act_price > 0) {
|
||||
ret.profitcenter_part = defaults.profits["PAO"];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
const Dinero = require("dinero.js");
|
||||
const queries = require("../graphql-client/queries");
|
||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||
const adminClient = require("../graphql-client/graphql-client").client;
|
||||
const _ = require("lodash");
|
||||
const logger = require("../utils/logger");
|
||||
// Dinero.defaultCurrency = "USD";
|
||||
// Dinero.globalLocale = "en-CA";
|
||||
@@ -59,9 +61,9 @@ async function TotalsServerSide(req, res) {
|
||||
try {
|
||||
let ret = {
|
||||
rates: await CalculateRatesTotals({ job, client }),
|
||||
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates),
|
||||
additional: CalculateAdditional(job),
|
||||
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates, job),
|
||||
};
|
||||
ret.additional = CalculateAdditional(job);
|
||||
ret.totals = CalculateTaxesTotals(job, ret);
|
||||
|
||||
return ret;
|
||||
@@ -93,9 +95,9 @@ async function Totals(req, res) {
|
||||
try {
|
||||
let ret = {
|
||||
rates: await CalculateRatesTotals({ job, client }),
|
||||
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates),
|
||||
additional: CalculateAdditional(job),
|
||||
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates, job),
|
||||
};
|
||||
ret.additional = CalculateAdditional(job);
|
||||
ret.totals = CalculateTaxesTotals(job, ret);
|
||||
|
||||
res.status(200).json(ret);
|
||||
@@ -259,8 +261,9 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
let hasMapaLine = false;
|
||||
let hasMashLine = false;
|
||||
let hasMahwLine = false;
|
||||
let mapaOpCodes = ParseCalopCode(job.materials["mapa"]?.cal_opcode);
|
||||
let mashOpCodes = ParseCalopCode(job.materials["mash"]?.cal_opcode);
|
||||
let hasCustomMahwLine;
|
||||
let mapaOpCodes = ParseCalopCode(job.materials["MAPA"]?.cal_opcode);
|
||||
let mashOpCodes = ParseCalopCode(job.materials["MASH"]?.cal_opcode);
|
||||
|
||||
jobLines.forEach((item) => {
|
||||
//IO-1317 Use the lines on the estimate if they exist instead.
|
||||
@@ -277,9 +280,21 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
amount: Math.round((item.act_price || 0) * 100),
|
||||
});
|
||||
}
|
||||
if (item.line_desc?.toLowerCase().includes("hazardous waste")) {
|
||||
//We might add a hazardous waste line. So we'll need to make sure we only pick up the CCC one.
|
||||
if (
|
||||
item.line_desc?.toLowerCase().includes("hazardous waste") &&
|
||||
!item.manual_line &&
|
||||
item.part_type === null &&
|
||||
item.lbr_op !== "OP16" //Seems to be that it is OP16 for sublet lines.
|
||||
) {
|
||||
hasMahwLine = item;
|
||||
}
|
||||
if (
|
||||
item.line_desc?.toLowerCase().includes("hazardous waste") &&
|
||||
item.manual_line
|
||||
) {
|
||||
hasCustomMahwLine = item;
|
||||
}
|
||||
|
||||
if (item.mod_lbr_ty) {
|
||||
//Check to see if it has 0 hours and a price instead.
|
||||
@@ -337,16 +352,18 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
}
|
||||
let threshold;
|
||||
//Check if there is a max for this type.
|
||||
if (job.materials && job.materials[property]) {
|
||||
if (job.materials && job.materials[property.toUpperCase()]) {
|
||||
//
|
||||
|
||||
if (
|
||||
job.materials[property].cal_maxdlr !== undefined &&
|
||||
job.materials[property].cal_maxdlr >= 0
|
||||
job.materials[property.toUpperCase()].cal_maxdlr !== undefined &&
|
||||
job.materials[property.toUpperCase()].cal_maxdlr >= 0
|
||||
) {
|
||||
//It has an upper threshhold.
|
||||
threshold = Dinero({
|
||||
amount: Math.round(job.materials[property].cal_maxdlr * 100),
|
||||
amount: Math.round(
|
||||
job.materials[property.toUpperCase()].cal_maxdlr * 100
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -375,29 +392,51 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
stlMahw.ttl_amt !== 0 &&
|
||||
(!hasMahwLine || hasMahwLine.act_price !== stlMahw.ttl_amt)
|
||||
) {
|
||||
//The Mahw line that has been added doesn't match with what we have in the STL. Add/update the adjusting line so that the balance is correct.
|
||||
|
||||
//Add a hazardous waste material line in case there isn't one on the estimate.
|
||||
const newMahwLine = {
|
||||
line_desc: "Hazardous Waste Removal*",
|
||||
part_type: "PAS",
|
||||
oem_partno: null,
|
||||
db_price: 0,
|
||||
act_price: stlMahw.ttl_amt,
|
||||
part_qty: 1,
|
||||
//mod_lbr_ty: "LAB",
|
||||
db_hrs: 0,
|
||||
mod_lb_hrs: 0,
|
||||
lbr_op: "OP11",
|
||||
lbr_amt: 0,
|
||||
op_code_desc: "REMOVE / REPLACE",
|
||||
tax_part: hasMahwLine.tax_amt > 0 ? true : false,
|
||||
db_ref: null,
|
||||
manual_line: true,
|
||||
jobid: job.id,
|
||||
};
|
||||
job.joblines.push(newMahwLine);
|
||||
await client.request(queries.INSERT_NEW_JOB_LINE, {
|
||||
lineInput: [newMahwLine],
|
||||
});
|
||||
let newPrice = stlMahw.ttl_amt;
|
||||
if (hasCustomMahwLine) {
|
||||
//Update it
|
||||
job.joblines.forEach((jl) => {
|
||||
if (jl.id === hasCustomMahwLine.id) {
|
||||
jl.act_price = newPrice;
|
||||
jl.manual_line = true;
|
||||
jl.tax_part = stlMahw.tax_amt > 0 ? true : false;
|
||||
}
|
||||
});
|
||||
await client.request(queries.UPDATE_JOB_LINE, {
|
||||
lineId: hasCustomMahwLine.id,
|
||||
line: {
|
||||
act_price: newPrice,
|
||||
manual_line: true,
|
||||
tax_part: stlMahw.tax_amt > 0 ? true : false,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const newMahwLine = {
|
||||
line_desc: "Hazardous Waste Removal*",
|
||||
part_type: null,
|
||||
oem_partno: null,
|
||||
db_price: 0,
|
||||
act_price: newPrice,
|
||||
part_qty: 1,
|
||||
mod_lbr_ty: "LAB",
|
||||
db_hrs: 0,
|
||||
mod_lb_hrs: 0,
|
||||
lbr_op: "OP0",
|
||||
lbr_amt: 0,
|
||||
op_code_desc: "REMOVE / REPLACE",
|
||||
tax_part: stlMahw.tax_amt > 0 ? true : false,
|
||||
db_ref: null,
|
||||
manual_line: true,
|
||||
jobid: job.id,
|
||||
};
|
||||
job.joblines.push(newMahwLine);
|
||||
await client.request(queries.INSERT_NEW_JOB_LINE, {
|
||||
lineInput: [newMahwLine],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//Materials Scrubbing as required by CCC.
|
||||
@@ -427,57 +466,8 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
function CalculatePartsTotals(jobLines, parts_tax_rates) {
|
||||
function CalculatePartsTotals(jobLines, parts_tax_rates, job) {
|
||||
const jl = jobLines.filter((jl) => !jl.removed);
|
||||
// jl.forEach((line) => {
|
||||
// //Some profile based estimates don't automatically add the discount to the line, some do.
|
||||
// //Clean up the ones that don't to add it in.
|
||||
|
||||
// //Apply a discount to the line if there is a profile discount, but it isn't added to the line itself.
|
||||
// const partTax = parts_tax_rates[line.part_type];
|
||||
// if (
|
||||
// line.act_price > 0 &&
|
||||
// partTax &&
|
||||
// partTax.prt_discp &&
|
||||
// partTax.prt_discp > 0
|
||||
// ) {
|
||||
// //apply a discount
|
||||
// const discount = Dinero({
|
||||
// amount: Math.round(line.act_price * 100),
|
||||
// }).percentage(
|
||||
// Math.abs(partTax.prt_discp) > 1
|
||||
// ? partTax.prt_discp
|
||||
// : partTax.prt_discp * 100
|
||||
// );
|
||||
// line.prt_dsmk_m = discount.toFormat("0.0");
|
||||
// line.prt_dsmk_p = partTax.prt_discp;
|
||||
// line.act_price = Dinero({
|
||||
// amount: Math.round(line.act_price * 100),
|
||||
// })
|
||||
// .subtract(discount)
|
||||
// .toFormat("0.0");
|
||||
// } else if (
|
||||
// line.act_price > 0 &&
|
||||
// partTax &&
|
||||
// partTax.prt_mkupp &&
|
||||
// partTax.prt_mkupp > 0
|
||||
// ) {
|
||||
// //apply a mark up
|
||||
// const markup = Dinero({
|
||||
// amount: Math.round(line.act_price * 100),
|
||||
// }).percentage(
|
||||
// Math.abs(partTax.prt_mkupp) > 1
|
||||
// ? partTax.prt_mkupp
|
||||
// : partTax.prt_mkupp * 100
|
||||
// );
|
||||
// line.prt_dsmk_m = markup.toFormat("0.0");
|
||||
// line.prt_dsmk_p = partTax.prt_mkupp;
|
||||
// line.act_price = Dinero({ amount: Math.round(line.act_price * 100) })
|
||||
// .add(markup)
|
||||
// .toFormat("0.0");
|
||||
// }
|
||||
// });
|
||||
|
||||
const ret = jl.reduce(
|
||||
(acc, value) => {
|
||||
switch (value.part_type) {
|
||||
@@ -517,24 +507,25 @@ function CalculatePartsTotals(jobLines, parts_tax_rates) {
|
||||
value.db_ref !== "900511"
|
||||
)
|
||||
return acc;
|
||||
|
||||
const discountAmount =
|
||||
((value.prt_dsmk_m && value.prt_dsmk_m !== 0) ||
|
||||
(value.prt_dsmk_p && value.prt_dsmk_p !== 0)) &&
|
||||
DiscountNotAlreadyCounted(value, jl)
|
||||
? value.prt_dsmk_m
|
||||
? Dinero({ amount: Math.round(value.prt_dsmk_m * 100) })
|
||||
: Dinero({
|
||||
amount: Math.round(value.act_price * 100),
|
||||
})
|
||||
.multiply(value.part_qty || 0)
|
||||
.percentage(Math.abs(value.prt_dsmk_p || 0))
|
||||
.multiply(value.prt_dsmk_p > 0 ? 1 : -1)
|
||||
: Dinero();
|
||||
return {
|
||||
...acc,
|
||||
parts: {
|
||||
...acc.parts,
|
||||
prt_dsmk_total: acc.parts.prt_dsmk_total.add(
|
||||
((value.prt_dsmk_m && value.prt_dsmk_m !== 0) ||
|
||||
(value.prt_dsmk_p && value.prt_dsmk_p !== 0)) &&
|
||||
DiscountNotAlreadyCounted(value, jl)
|
||||
? value.prt_dsmk_m
|
||||
? Dinero({ amount: Math.round(value.prt_dsmk_m * 100) })
|
||||
: Dinero({
|
||||
amount: Math.round(value.act_price * 100),
|
||||
})
|
||||
.multiply(value.part_qty || 0)
|
||||
.percentage(Math.abs(value.prt_dsmk_p || 0))
|
||||
.multiply(value.prt_dsmk_p > 0 ? 1 : -1)
|
||||
: Dinero()
|
||||
),
|
||||
prt_dsmk_total: acc.parts.prt_dsmk_total.add(discountAmount),
|
||||
...(value.part_type
|
||||
? {
|
||||
list: {
|
||||
@@ -543,20 +534,24 @@ function CalculatePartsTotals(jobLines, parts_tax_rates) {
|
||||
acc.parts.list[value.part_type] &&
|
||||
acc.parts.list[value.part_type].total
|
||||
? {
|
||||
total: acc.parts.list[value.part_type].total.add(
|
||||
Dinero({
|
||||
amount: Math.round(
|
||||
(value.act_price || 0) * 100
|
||||
),
|
||||
}).multiply(value.part_qty || 0)
|
||||
),
|
||||
total: acc.parts.list[value.part_type].total
|
||||
.add(
|
||||
Dinero({
|
||||
amount: Math.round(
|
||||
(value.act_price || 0) * 100
|
||||
),
|
||||
}).multiply(value.part_qty || 0)
|
||||
)
|
||||
.add(discountAmount),
|
||||
}
|
||||
: {
|
||||
total: Dinero({
|
||||
amount: Math.round(
|
||||
(value.act_price || 0) * 100
|
||||
),
|
||||
}).multiply(value.part_qty || 0),
|
||||
})
|
||||
.multiply(value.part_qty || 0)
|
||||
.add(discountAmount),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -613,23 +608,27 @@ function CalculatePartsTotals(jobLines, parts_tax_rates) {
|
||||
PAS: Dinero(),
|
||||
PAT: Dinero(),
|
||||
};
|
||||
//Track all adjustments that need to be made.
|
||||
|
||||
const linesToAdjustForDiscount = [];
|
||||
Object.keys(parts_tax_rates).forEach((key) => {
|
||||
//Check if there's a discount or a mark up.
|
||||
let disc = Dinero(),
|
||||
markup = Dinero();
|
||||
|
||||
let discountRate, markupRate;
|
||||
if (
|
||||
parts_tax_rates[key].prt_discp !== undefined &&
|
||||
parts_tax_rates[key].prt_discp >= 0
|
||||
) {
|
||||
//Check if there's any parts in this part type.
|
||||
if (ret.parts.list[key] !== undefined) {
|
||||
disc = ret.parts.list[key].total
|
||||
.percentage(
|
||||
Math.abs(parts_tax_rates[key].prt_discp) > 1
|
||||
? parts_tax_rates[key].prt_discp
|
||||
: parts_tax_rates[key].prt_discp * 100
|
||||
)
|
||||
.multiply(-1);
|
||||
discountRate =
|
||||
Math.abs(parts_tax_rates[key].prt_discp) > 1
|
||||
? parts_tax_rates[key].prt_discp
|
||||
: parts_tax_rates[key].prt_discp * 100;
|
||||
|
||||
disc = ret.parts.list[key].total.percentage(discountRate).multiply(-1);
|
||||
}
|
||||
}
|
||||
if (
|
||||
@@ -638,26 +637,70 @@ function CalculatePartsTotals(jobLines, parts_tax_rates) {
|
||||
) {
|
||||
//Check if there's any parts in this part type.
|
||||
if (ret.parts.list[key] !== undefined) {
|
||||
markup = ret.parts.list[key].total.percentage(
|
||||
markupRate =
|
||||
Math.abs(parts_tax_rates[key].prt_mkupp) > 1
|
||||
? parts_tax_rates[key].prt_mkupp
|
||||
: parts_tax_rates[key].prt_mkupp * 100 //Seems that mark up is written as decimal not %.
|
||||
);
|
||||
: parts_tax_rates[key].prt_mkupp * 100; //Seems that mark up is written as decimal not %.
|
||||
|
||||
markup = ret.parts.list[key].total.percentage(markupRate);
|
||||
}
|
||||
}
|
||||
let adjustment = disc.add(markup);
|
||||
adjustments[key] = adjustment;
|
||||
|
||||
const correspondingCiecaStlTotalLine = job.cieca_stl?.data.find(
|
||||
(c) => c.ttl_typecd === key
|
||||
);
|
||||
|
||||
//If the difference is greater than a penny, fix it.
|
||||
//This usually ties into whether or not the profile has part type discounts overall in the PFP.
|
||||
if (
|
||||
correspondingCiecaStlTotalLine &&
|
||||
Math.abs(
|
||||
ret.parts.list[key]?.total.getAmount() -
|
||||
correspondingCiecaStlTotalLine.ttl_amt * 100
|
||||
) > 1
|
||||
) {
|
||||
// Update the total.
|
||||
console.log(
|
||||
key,
|
||||
ret.parts.list[key]?.total.getAmount(),
|
||||
correspondingCiecaStlTotalLine?.ttl_amt
|
||||
);
|
||||
//Find the corresponding lines. Update the discount/markup for them.
|
||||
|
||||
console.warn("There's a difference! Type: ", key);
|
||||
let totalDiscountToAdjustBy = Dinero();
|
||||
job.joblines.forEach((jobline) => {
|
||||
//Modify the line in place to add the mark up/discount.
|
||||
if (jobline.part_type === key) {
|
||||
const discountAmountDinero = Dinero({
|
||||
amount: Math.round(jobline.act_price * 100),
|
||||
}).percentage(discountRate);
|
||||
|
||||
const discountAmount = parseFloat(
|
||||
discountAmountDinero.toFormat("0.00")
|
||||
);
|
||||
totalDiscountToAdjustBy =
|
||||
totalDiscountToAdjustBy.add(discountAmountDinero);
|
||||
jobline.prt_dsmk_m = discountAmount * -1;
|
||||
jobline.prt_dsmk_p = discountRate * -1;
|
||||
|
||||
linesToAdjustForDiscount.push(jobline);
|
||||
}
|
||||
});
|
||||
// ret.parts.list[key].total = ret.parts.list[key]?.total.subtract(
|
||||
// totalDiscountToAdjustBy
|
||||
// );
|
||||
ret.parts.prt_dsmk_total = ret.parts.prt_dsmk_total.subtract(
|
||||
totalDiscountToAdjustBy
|
||||
);
|
||||
ret.parts.subtotal = ret.parts.subtotal.subtract(totalDiscountToAdjustBy);
|
||||
ret.parts.total = ret.parts.total.subtract(totalDiscountToAdjustBy);
|
||||
}
|
||||
});
|
||||
|
||||
//Temporarily commenting this out since these totals appear to be already included in the calculation.
|
||||
// Object.keys(adjustments).forEach((key) => {
|
||||
// if (ret.parts.list[key] !== undefined) {
|
||||
// ret.parts.list[key].total = ret.parts.list[key].total.add(
|
||||
// adjustments[key]
|
||||
// );
|
||||
// ret.parts.subtotal = ret.parts.subtotal.add(adjustments[key]);
|
||||
// }
|
||||
// });
|
||||
UpdateJobLines(linesToAdjustForDiscount.filter((l) => l.prt_dsmk_m !== 0));
|
||||
|
||||
return {
|
||||
adjustments,
|
||||
@@ -691,6 +734,9 @@ function IsAdditionalCost(jobLine) {
|
||||
}
|
||||
|
||||
function CalculateAdditional(job) {
|
||||
const stlTowing = job.cieca_stl?.data.find((c) => c.ttl_type === "OTTW");
|
||||
const stlStorage = job.cieca_stl?.data.find((c) => c.ttl_type === "OTST");
|
||||
|
||||
let ret = {
|
||||
additionalCosts: null,
|
||||
additionalCostItems: [],
|
||||
@@ -701,9 +747,11 @@ function CalculateAdditional(job) {
|
||||
pvrt: null,
|
||||
total: null,
|
||||
};
|
||||
ret.towing = Dinero({
|
||||
amount: Math.round((job.towing_payable || 0) * 100),
|
||||
});
|
||||
ret.towing = stlTowing
|
||||
? Dinero({ amount: Math.round(stlTowing.ttl_amt * 100) })
|
||||
: Dinero({
|
||||
amount: Math.round((job.towing_payable || 0) * 100),
|
||||
});
|
||||
|
||||
ret.additionalCosts = job.joblines
|
||||
.filter((jl) => !jl.removed && IsAdditionalCost(jl))
|
||||
@@ -728,9 +776,11 @@ function CalculateAdditional(job) {
|
||||
ret.adjustments = Dinero({
|
||||
amount: Math.round((job.adjustment_bottom_line || 0) * 100),
|
||||
});
|
||||
ret.storage = Dinero({
|
||||
amount: Math.round((job.storage_payable || 0) * 100),
|
||||
});
|
||||
ret.storage = stlStorage
|
||||
? Dinero({ amount: Math.round(stlStorage.ttl_amt * 100) })
|
||||
: Dinero({
|
||||
amount: Math.round((job.storage_payable || 0) * 100),
|
||||
});
|
||||
ret.pvrt = Dinero({
|
||||
amount: Math.round((job.ca_bc_pvrt || 0) * 100),
|
||||
});
|
||||
@@ -738,7 +788,6 @@ function CalculateAdditional(job) {
|
||||
.add(ret.adjustments) //IO-813 Adjustment takes care of GST & PST at labor rate.
|
||||
.add(ret.towing)
|
||||
.add(ret.storage);
|
||||
//.add(ret.pvrt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -749,14 +798,12 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
.add(otherTotals.rates.subtotal) //No longer using just rates subtotal to include mapa/mash.
|
||||
.add(otherTotals.additional.total);
|
||||
|
||||
// .add(Dinero({ amount: (job.towing_payable || 0) * 100 }))
|
||||
// .add(Dinero({ amount: (job.storage_payable || 0) * 100 }));
|
||||
|
||||
//Potential issue here with Sublet Calculation. Sublets are calculated under labor in Mitchell, but it's done in IO
|
||||
//Under the parts rates.
|
||||
|
||||
let statePartsTax = Dinero();
|
||||
let additionalItemsTax = Dinero();
|
||||
let us_sales_tax_breakdown;
|
||||
|
||||
//Audatex sends additional glass part types. IO-774
|
||||
const BackupGlassTax =
|
||||
@@ -767,92 +814,334 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
job.parts_tax_rates.PAGQ ||
|
||||
job.parts_tax_rates.PAGR);
|
||||
|
||||
job.joblines
|
||||
.filter((jl) => !jl.removed)
|
||||
.forEach((val) => {
|
||||
if (!val.tax_part) return;
|
||||
if (!val.part_type && IsAdditionalCost(val)) {
|
||||
additionalItemsTax = additionalItemsTax.add(
|
||||
Dinero({ amount: Math.round((val.act_price || 0) * 100) })
|
||||
.multiply(val.part_qty || 0)
|
||||
.percentage(
|
||||
((job.parts_tax_rates &&
|
||||
job.parts_tax_rates["PAN"] &&
|
||||
job.parts_tax_rates["PAN"].prt_tax_rt) ||
|
||||
0) * 100
|
||||
const taxableAmounts = {
|
||||
PAA: Dinero(),
|
||||
PAN: Dinero(),
|
||||
PAL: Dinero(),
|
||||
PAR: Dinero(),
|
||||
PAC: Dinero(),
|
||||
PAG: Dinero(),
|
||||
PAO: Dinero(),
|
||||
PAS: Dinero(),
|
||||
PAP: Dinero(),
|
||||
PAM: Dinero(),
|
||||
|
||||
LA1: Dinero(),
|
||||
LA2: Dinero(),
|
||||
LA3: Dinero(),
|
||||
LA4: Dinero(),
|
||||
LAU: Dinero(),
|
||||
LAA: Dinero(),
|
||||
LAB: Dinero(),
|
||||
LAD: Dinero(),
|
||||
LAE: Dinero(),
|
||||
LAF: Dinero(),
|
||||
LAG: Dinero(),
|
||||
LAM: Dinero(),
|
||||
LAR: Dinero(),
|
||||
LAS: Dinero(),
|
||||
|
||||
MAPA: Dinero(),
|
||||
MASH: Dinero(),
|
||||
TOW: Dinero(),
|
||||
STOR: Dinero(),
|
||||
};
|
||||
|
||||
if (
|
||||
job.parts_tax_rates.PAN.prt_tx_ty1 &&
|
||||
job.parts_tax_rates.PAN.prt_tx_ty1 !== ""
|
||||
) {
|
||||
//For each line, determine if it's taxable, and if it is, add the line amount to the taxable amounts total.
|
||||
job.joblines
|
||||
.filter((jl) => !jl.removed)
|
||||
.forEach((val) => {
|
||||
if (!val.tax_part) return;
|
||||
if (!val.part_type && IsAdditionalCost(val)) {
|
||||
taxableAmounts.PAO = taxableAmounts.PAO.add(
|
||||
Dinero({ amount: Math.round((val.act_price || 0) * 100) }).multiply(
|
||||
val.part_qty || 0
|
||||
)
|
||||
);
|
||||
} else {
|
||||
statePartsTax = statePartsTax.add(
|
||||
Dinero({ amount: Math.round((val.act_price || 0) * 100) })
|
||||
.multiply(val.part_qty || 0)
|
||||
.add(
|
||||
val.prt_dsmk_m &&
|
||||
val.prt_dsmk_m !== 0 &&
|
||||
DiscountNotAlreadyCounted(val, job.joblines)
|
||||
? val.prt_dsmk_m
|
||||
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
||||
: Dinero({
|
||||
amount: Math.round(val.act_price * 100),
|
||||
})
|
||||
.multiply(val.part_qty || 0)
|
||||
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||
: Dinero()
|
||||
)
|
||||
.percentage(
|
||||
((job.parts_tax_rates &&
|
||||
job.parts_tax_rates[val.part_type] &&
|
||||
job.parts_tax_rates[val.part_type].prt_tax_rt) ||
|
||||
(val.part_type &&
|
||||
val.part_type.startsWith("PAG") &&
|
||||
BackupGlassTax &&
|
||||
BackupGlassTax.prt_tax_rt) ||
|
||||
(!val.part_type &&
|
||||
val.db_ref === "900510" &&
|
||||
job.parts_tax_rates["PAN"] &&
|
||||
job.parts_tax_rates["PAN"].prt_tax_rt) ||
|
||||
0) * 100
|
||||
)
|
||||
);
|
||||
);
|
||||
} else if (!val.part_type) {
|
||||
//Do nothing for now.
|
||||
} else {
|
||||
const typeOfPart = val.part_type;
|
||||
taxableAmounts[typeOfPart] = taxableAmounts[typeOfPart].add(
|
||||
Dinero({ amount: Math.round((val.act_price || 0) * 100) })
|
||||
.multiply(val.part_qty || 0)
|
||||
.add(
|
||||
val.prt_dsmk_m &&
|
||||
val.prt_dsmk_m !== 0 &&
|
||||
DiscountNotAlreadyCounted(val, job.joblines) // DO WE NEED TO COUNT PFP DISCOUNT HERE?
|
||||
? val.prt_dsmk_m
|
||||
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
||||
: Dinero({
|
||||
amount: Math.round(val.act_price * 100),
|
||||
})
|
||||
.multiply(val.part_qty || 0)
|
||||
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||
: Dinero()
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
//Check in the PFL file which types of labor are taxable. Add the amount that is considered taxable to the taxable amounts total.
|
||||
Object.keys(taxableAmounts)
|
||||
.filter((key) => key.startsWith("LA"))
|
||||
.map((key) => {
|
||||
const isLaborTypeTaxable = job.cieca_pfl[key]?.lbr_tax_in;
|
||||
if (isLaborTypeTaxable) {
|
||||
taxableAmounts[key] = taxableAmounts[key].add(
|
||||
otherTotals.rates[key.toLowerCase()].total
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(taxableAmounts)
|
||||
.filter((key) => key.startsWith("MA"))
|
||||
.map((key) => {
|
||||
const isTypeTaxable = job.materials[key]?.tax_ind;
|
||||
if (isTypeTaxable) {
|
||||
taxableAmounts[key] = taxableAmounts[key].add(
|
||||
otherTotals.rates[key.toLowerCase()].total
|
||||
);
|
||||
}
|
||||
});
|
||||
//Add towing and storage taxable amounts
|
||||
const stlTowing = job.cieca_stl?.data.find((c) => c.ttl_typecd === "OTTW");
|
||||
const stlStorage = job.cieca_stl?.data.find((c) => c.ttl_typecd === "OTST");
|
||||
|
||||
if (stlTowing)
|
||||
taxableAmounts.TOW = Dinero({
|
||||
amount: Math.round(stlTowing.t_amt * 100),
|
||||
});
|
||||
if (stlStorage)
|
||||
taxableAmounts.TOW = Dinero({
|
||||
amount: Math.round(stlStorage.t_amt * 100),
|
||||
});
|
||||
|
||||
// console.log("*** Taxable Amounts***");
|
||||
// console.table(JSON.parse(JSON.stringify(taxableAmounts)));
|
||||
|
||||
//For the taxable amounts, figure out which tax type applies.
|
||||
//Then sum up the total of that tax type and then calculate the thresholds.
|
||||
|
||||
const taxableAmountsByTier = {
|
||||
ty1Tax: Dinero(),
|
||||
ty2Tax: Dinero(),
|
||||
ty3Tax: Dinero(),
|
||||
ty4Tax: Dinero(),
|
||||
ty5Tax: Dinero(),
|
||||
ty6Tax: Dinero(),
|
||||
};
|
||||
const totalTaxByTier = {
|
||||
ty1Tax: Dinero(),
|
||||
ty2Tax: Dinero(),
|
||||
ty3Tax: Dinero(),
|
||||
ty4Tax: Dinero(),
|
||||
ty5Tax: Dinero(),
|
||||
ty6Tax: Dinero(),
|
||||
};
|
||||
|
||||
const pfp = job.parts_tax_rates;
|
||||
const pfl = job.cieca_pfl;
|
||||
const pfm = job.materials;
|
||||
const pfo = job.cieca_pfo;
|
||||
Object.keys(taxableAmounts).map((key) => {
|
||||
try {
|
||||
if (key.startsWith("PA")) {
|
||||
const typeOfPart = key; // === "PAM" ? "PAC" : key;
|
||||
//At least one of these scenarios must be taxable.
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
if (IsTrueOrYes(pfp[typeOfPart][`prt_tx_in${tyCounter}`])) {
|
||||
//This amount is taxable for this type.
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[
|
||||
`ty${tyCounter}Tax`
|
||||
].add(taxableAmounts[typeOfPart]);
|
||||
}
|
||||
}
|
||||
} else if (key.startsWith("MA")) {
|
||||
//Materials Handling
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
if (IsTrueOrYes(pfm[key][`mat_tx_in${tyCounter}`])) {
|
||||
//This amount is taxable for this type.
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[
|
||||
`ty${tyCounter}Tax`
|
||||
].add(taxableAmounts[key]);
|
||||
}
|
||||
}
|
||||
} else if (key.startsWith("LA")) {
|
||||
//Labor.
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
if (IsTrueOrYes(pfl[key][`lbr_tx_in${tyCounter}`])) {
|
||||
//This amount is taxable for this type.
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[
|
||||
`ty${tyCounter}Tax`
|
||||
].add(taxableAmounts[key]);
|
||||
}
|
||||
}
|
||||
} else if (key === "TOW") {
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
if (IsTrueOrYes(pfo[`tow_t_in${tyCounter}`])) {
|
||||
//This amount is taxable for this type.
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[
|
||||
`ty${tyCounter}Tax`
|
||||
].add(taxableAmounts[key]);
|
||||
}
|
||||
}
|
||||
} else if (key === "STOR") {
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
if (IsTrueOrYes(pfo[`stor_t_in${tyCounter}`])) {
|
||||
//This amount is taxable for this type.
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[
|
||||
`ty${tyCounter}Tax`
|
||||
].add(taxableAmounts[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Key with issue", key);
|
||||
}
|
||||
});
|
||||
|
||||
const remainingTaxableAmounts = taxableAmountsByTier;
|
||||
// console.log("*** Taxable Amounts by Tier***");
|
||||
// console.table(JSON.parse(JSON.stringify(taxableAmountsByTier)));
|
||||
|
||||
Object.keys(taxableAmountsByTier).forEach((taxTierKey) => {
|
||||
try {
|
||||
let tyCounter = taxTierKey[2]; //Get the number from the key.
|
||||
//i represents the tax number. If we got here, this type of tax is applicable. Now we need to add based on the thresholds.
|
||||
for (let threshCounter = 1; threshCounter <= 5; threshCounter++) {
|
||||
const thresholdAmount = parseFloat(
|
||||
job.cieca_pft[`ty${tyCounter}_thres${threshCounter}`]
|
||||
);
|
||||
const thresholdTaxRate = parseFloat(
|
||||
job.cieca_pft[`ty${tyCounter}_rate${threshCounter}`]
|
||||
);
|
||||
|
||||
let taxableAmountInThisThreshold;
|
||||
if (thresholdAmount === 9999.99) {
|
||||
// THis is the last threshold. Tax the entire remaining amount.
|
||||
taxableAmountInThisThreshold = remainingTaxableAmounts[taxTierKey];
|
||||
remainingTaxableAmounts[taxTierKey] = Dinero();
|
||||
} else {
|
||||
if (
|
||||
thresholdAmount >=
|
||||
remainingTaxableAmounts[taxTierKey].getAmount() / 100
|
||||
) {
|
||||
//This threshold is bigger than the remaining taxable balance. Add it all.
|
||||
taxableAmountInThisThreshold =
|
||||
remainingTaxableAmounts[taxTierKey];
|
||||
remainingTaxableAmounts[taxTierKey] = Dinero();
|
||||
} else {
|
||||
//Take the size of the threshold from the remaining amount, tax it, and do it all over.
|
||||
taxableAmountInThisThreshold = Dinero({
|
||||
amount: Math.round(thresholdAmount * 100),
|
||||
});
|
||||
remainingTaxableAmounts[taxTierKey] = remainingTaxableAmounts[
|
||||
taxTierKey
|
||||
].subtract(
|
||||
Dinero({
|
||||
amount: Math.round(taxableAmountInThisThreshold * 100),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const taxAmountToAdd =
|
||||
taxableAmountInThisThreshold.percentage(thresholdTaxRate);
|
||||
|
||||
totalTaxByTier[taxTierKey] =
|
||||
totalTaxByTier[taxTierKey].add(taxAmountToAdd);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("PFP Calculation error", error);
|
||||
}
|
||||
});
|
||||
|
||||
// console.log("*** Total Tax by Tier Amounts***");
|
||||
// console.table(JSON.parse(JSON.stringify(totalTaxByTier)));
|
||||
|
||||
statePartsTax = statePartsTax
|
||||
.add(totalTaxByTier.ty1Tax)
|
||||
.add(totalTaxByTier.ty2Tax)
|
||||
.add(totalTaxByTier.ty3Tax)
|
||||
.add(totalTaxByTier.ty4Tax)
|
||||
.add(totalTaxByTier.ty5Tax)
|
||||
.add(totalTaxByTier.ty6Tax);
|
||||
us_sales_tax_breakdown = totalTaxByTier;
|
||||
//console.log("Tiered Taxes Total for Parts/Labor", statePartsTax.toFormat());
|
||||
} else {
|
||||
//Use the old thing.
|
||||
job.joblines
|
||||
.filter((jl) => !jl.removed)
|
||||
.forEach((val) => {
|
||||
if (!val.tax_part) return;
|
||||
if (!val.part_type && IsAdditionalCost(val)) {
|
||||
additionalItemsTax = additionalItemsTax.add(
|
||||
Dinero({ amount: Math.round((val.act_price || 0) * 100) })
|
||||
.multiply(val.part_qty || 0)
|
||||
.percentage(
|
||||
((job.parts_tax_rates &&
|
||||
job.parts_tax_rates["PAN"] &&
|
||||
job.parts_tax_rates["PAN"].prt_tax_rt) ||
|
||||
0) * 100
|
||||
)
|
||||
);
|
||||
} else {
|
||||
statePartsTax = statePartsTax.add(
|
||||
Dinero({ amount: Math.round((val.act_price || 0) * 100) })
|
||||
.multiply(val.part_qty || 0)
|
||||
.add(
|
||||
val.prt_dsmk_m &&
|
||||
val.prt_dsmk_m !== 0 &&
|
||||
DiscountNotAlreadyCounted(val, job.joblines)
|
||||
? val.prt_dsmk_m
|
||||
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
||||
: Dinero({
|
||||
amount: Math.round(val.act_price * 100),
|
||||
})
|
||||
.multiply(val.part_qty || 0)
|
||||
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||
: Dinero()
|
||||
)
|
||||
.percentage(
|
||||
((job.parts_tax_rates &&
|
||||
job.parts_tax_rates[val.part_type] &&
|
||||
job.parts_tax_rates[val.part_type].prt_tax_rt) ||
|
||||
(val.part_type &&
|
||||
val.part_type.startsWith("PAG") &&
|
||||
BackupGlassTax &&
|
||||
BackupGlassTax.prt_tax_rt) ||
|
||||
(!val.part_type &&
|
||||
val.db_ref === "900510" &&
|
||||
job.parts_tax_rates["PAN"] &&
|
||||
job.parts_tax_rates["PAN"].prt_tax_rt) ||
|
||||
0) * 100
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let laborTaxTotal = Dinero();
|
||||
|
||||
if (Object.keys(job.cieca_pfl).length > 0) {
|
||||
//Do it by labor type
|
||||
const types = [
|
||||
"la1",
|
||||
"la2",
|
||||
"la3",
|
||||
"la4",
|
||||
"lau",
|
||||
"laa",
|
||||
"lab",
|
||||
"lad",
|
||||
"lae",
|
||||
"laf",
|
||||
"lag",
|
||||
"lam",
|
||||
"lar",
|
||||
"las",
|
||||
];
|
||||
types.forEach((type) => {
|
||||
laborTaxTotal = laborTaxTotal.add(
|
||||
otherTotals.rates[type].total.percentage(
|
||||
job.cieca_pfl[type.toUpperCase()]
|
||||
? job.cieca_pfl[type.toUpperCase()].lbr_taxp
|
||||
: (job.tax_lbr_rt || 0) * 100
|
||||
)
|
||||
);
|
||||
});
|
||||
//Ignore it now, we have calculated it above.
|
||||
//This was previously used for JCS before parts were also calculated at a different rate.
|
||||
} else {
|
||||
//We don't have it, just add in how it was before.
|
||||
laborTaxTotal = otherTotals.rates.subtotal.percentage(
|
||||
(job.tax_lbr_rt || 0) * 100
|
||||
); // THis is currently using the lbr tax rate from PFH not PFL.
|
||||
}
|
||||
|
||||
//console.log("Labor Tax Total", laborTaxTotal.toFormat());
|
||||
|
||||
let ret = {
|
||||
subtotal: subtotal,
|
||||
federal_tax: subtotal
|
||||
@@ -863,35 +1152,8 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
)
|
||||
),
|
||||
statePartsTax,
|
||||
state_tax: statePartsTax
|
||||
.add(laborTaxTotal)
|
||||
.add(
|
||||
otherTotals.additional.adjustments.percentage(
|
||||
(job.tax_lbr_rt || 0) * 100
|
||||
)
|
||||
)
|
||||
.add(
|
||||
otherTotals.additional.towing.percentage((job.tax_tow_rt || 0) * 100)
|
||||
)
|
||||
.add(
|
||||
otherTotals.additional.storage.percentage((job.tax_str_rt || 0) * 100)
|
||||
)
|
||||
.add(additionalItemsTax)
|
||||
.add(
|
||||
otherTotals.rates.mapa.hasMapaLine === false //If parts and materials were not added as lines, we must calculate the taxes on them.
|
||||
? otherTotals.rates.mapa.total.percentage(
|
||||
(job.tax_paint_mat_rt || 0) * 100
|
||||
)
|
||||
: Dinero()
|
||||
)
|
||||
.add(
|
||||
otherTotals.rates.mash.hasMashLine === false //If parts and materials were not added as lines, we must calculate the taxes on them.
|
||||
? otherTotals.rates.mash.total.percentage(
|
||||
(job.tax_shop_mat_rt || 0) * 100
|
||||
)
|
||||
: Dinero()
|
||||
),
|
||||
|
||||
us_sales_tax_breakdown,
|
||||
state_tax: statePartsTax,
|
||||
local_tax: subtotal.percentage((job.local_tax_rate || 0) * 100),
|
||||
};
|
||||
ret.total_repairs = ret.subtotal
|
||||
@@ -928,6 +1190,7 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
exports.default = Totals;
|
||||
|
||||
function DiscountNotAlreadyCounted(jobline, joblines) {
|
||||
return false;
|
||||
//CCC already factors in the discount. If the difference between the 2 is exactly the discount, it's all good.
|
||||
if (
|
||||
Math.round(
|
||||
@@ -937,11 +1200,9 @@ function DiscountNotAlreadyCounted(jobline, joblines) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check it against the database price too? If it's an OE part.
|
||||
if (
|
||||
Math.abs(jobline.db_price - jobline.act_price) -
|
||||
Math.abs(jobline.prt_dsmk_m) <
|
||||
0.01
|
||||
jobline.db_price !== jobline.act_price &&
|
||||
jobline.db_price - jobline.act_price - Math.abs(jobline.prt_dsmk_m) < 0.02
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -964,3 +1225,35 @@ function ParseCalopCode(opcode) {
|
||||
if (!opcode) return [];
|
||||
return opcode.trim().split(" ");
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
`;
|
||||
|
||||
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
|
||||
}
|
||||
}`;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var { admin } = require("./server/firebase/firebase-handler");
|
||||
|
||||
const uidToMakeAdmin = "yTvpfkcNnGckLd1JnoXC7bTdvtu1";
|
||||
const uidToMakeAdmin = "fIaZcVQQfUR12Fu14I2fyA5vXbp1";
|
||||
|
||||
admin
|
||||
.auth()
|
||||
|
||||
Reference in New Issue
Block a user