Reformat all project files to use the prettier config file.

This commit is contained in:
Patrick Fic
2024-03-27 15:35:07 -07:00
parent b161530381
commit e1df64d592
873 changed files with 111387 additions and 125473 deletions

View File

@@ -1,33 +1,33 @@
import {DeleteFilled} from "@ant-design/icons";
import {useApolloClient, useMutation} from "@apollo/client";
import { DeleteFilled } from "@ant-design/icons";
import { useApolloClient, useMutation } from "@apollo/client";
import {
Alert,
Button,
Col,
Divider,
Form,
Input,
InputNumber,
notification,
Popconfirm,
Row,
Select,
Space,
Statistic,
Switch,
Typography,
Alert,
Button,
Col,
Divider,
Form,
Input,
InputNumber,
notification,
Popconfirm,
Row,
Select,
Space,
Statistic,
Switch,
Typography
} from "antd";
import {PageHeader} from "@ant-design/pro-layout";
import { PageHeader } from "@ant-design/pro-layout";
import React, {useState} from "react";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
// import { useNavigate } from 'react-router-dom';
import {useSplitTreatments} from "@splitsoftware/splitio-react";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import Dinero from "dinero.js";
import dayjs from "../../utils/day";
import {Link} from "react-router-dom";
import {createStructuredSelector} from "reselect";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import DateTimePicker from "../../components/form-date-time-picker/form-date-time-picker.component";
import FormsFieldChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
import CurrencyInput from "../../components/form-items-formatted/currency-form-item.component";
@@ -35,510 +35,450 @@ import JobsScoreboardAdd from "../../components/job-scoreboard-add-button/job-sc
import JobsCloseAutoAllocate from "../../components/jobs-close-auto-allocate/jobs-close-auto-allocate.component";
import JobsCloseLines from "../../components/jobs-close-lines/jobs-close-lines.component";
import LayoutFormRow from "../../components/layout-form-row/layout-form-row.component";
import {generateJobLinesUpdatesForInvoicing} from "../../graphql/jobs-lines.queries";
import {UPDATE_JOB} from "../../graphql/jobs.queries";
import {insertAuditTrail} from "../../redux/application/application.actions";
import {selectJobReadOnly} from "../../redux/application/application.selectors";
import {selectBodyshop} from "../../redux/user/user.selectors";
import { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.queries";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly
});
const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({jobid, operation, type}) =>
dispatch(insertAuditTrail({jobid, operation, type })),
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
});
export function JobsCloseComponent({job, bodyshop, jobRO, insertAuditTrail}) {
const {t} = useTranslation();
const [form] = Form.useForm();
const client = useApolloClient();
// const history = useNavigate();
const [closeJob] = useMutation(UPDATE_JOB);
const [loading, setLoading] = useState(false);
export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail }) {
const { t } = useTranslation();
const [form] = Form.useForm();
const client = useApolloClient();
// const history = useNavigate();
const [closeJob] = useMutation(UPDATE_JOB);
const [loading, setLoading] = useState(false);
const {treatments: {Qb_Multi_Ar, ClosingPeriod}} = useSplitTreatments({
attributes: {},
names: ["Qb_Multi_Ar", "ClosingPeriod"],
splitKey: bodyshop && bodyshop.imexshopid,
const {
treatments: { Qb_Multi_Ar, ClosingPeriod }
} = useSplitTreatments({
attributes: {},
names: ["Qb_Multi_Ar", "ClosingPeriod"],
splitKey: bodyshop && bodyshop.imexshopid
});
const handleFinish = async ({ removefromproduction, ...values }) => {
setLoading(true);
const result = await client.mutate({
mutation: generateJobLinesUpdatesForInvoicing(values.joblines)
});
if (result.errors) {
return; // Abandon the rest of the close.
}
const closeResult = await closeJob({
variables: {
jobId: job.id,
job: {
status: bodyshop.md_ro_statuses.default_invoiced || "",
date_invoiced: values.date_invoiced,
actual_in: values.actual_in,
actual_completion: values.actual_completion,
actual_delivery: values.actual_delivery,
kmin: values.kmin,
kmout: values.kmout,
dms_allocation: values.dms_allocation,
...(removefromproduction ? { inproduction: false } : {}),
...(values.qb_multiple_payers ? { qb_multiple_payers: values.qb_multiple_payers } : {})
}
},
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
awaitRefetchQueries: true
});
const handleFinish = async ({removefromproduction, ...values}) => {
setLoading(true);
const result = await client.mutate({
mutation: generateJobLinesUpdatesForInvoicing(values.joblines),
});
if (result.errors) {
return; // Abandon the rest of the close.
}
if (!result.errors) {
// notification["success"]({ message: t("jobs.successes.save") });
// form.resetFields();
} else {
notification["error"]({
message: t("job.errors.saving", {
error: JSON.stringify(result.errors)
})
});
return; // Abandon the rest of the close.
}
const closeResult = await closeJob({
variables: {
jobId: job.id,
job: {
status: bodyshop.md_ro_statuses.default_invoiced || "",
date_invoiced: values.date_invoiced,
actual_in: values.actual_in,
actual_completion: values.actual_completion,
actual_delivery: values.actual_delivery,
kmin: values.kmin,
kmout: values.kmout,
dms_allocation: values.dms_allocation,
...(removefromproduction ? {inproduction: false} : {}),
...(values.qb_multiple_payers
? {qb_multiple_payers: values.qb_multiple_payers}
: {}),
},
},
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
awaitRefetchQueries: true,
});
if (!closeResult.errors) {
setLoading(false);
if (!result.errors) {
// notification["success"]({ message: t("jobs.successes.save") });
// form.resetFields();
} else {
notification["error"]({
message: t("job.errors.saving", {
error: JSON.stringify(result.errors),
}),
});
return; // Abandon the rest of the close.
}
notification["success"]({
message: t("jobs.successes.closed")
});
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.jobinvoiced(),
type: "jobinvoiced"
});
// history(`/manage/jobs/${job.id}`);
} else {
setLoading(false);
notification["error"]({
message: t("job.errors.closing", {
error: JSON.stringify(closeResult.errors)
})
});
}
form.resetFields();
form.resetFields();
if (!closeResult.errors) {
setLoading(false);
setLoading(false);
};
notification["success"]({
message: t("jobs.successes.closed"),
});
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.jobinvoiced(),
type: "jobinvoiced",});
// history(`/manage/jobs/${job.id}`);
} else {
setLoading(false);
notification["error"]({
message: t("job.errors.closing", {
error: JSON.stringify(closeResult.errors),
}),
});
}
form.resetFields();
form.resetFields();
return (
<div>
<Form
layout="vertical"
form={form}
onFinish={handleFinish}
initialValues={{
joblines: job.joblines,
actual_in: job.actual_in ? dayjs(job.actual_in) : job.scheduled_in && dayjs(job.scheduled_in),
actual_completion: job.actual_completion
? dayjs(job.actual_completion)
: job.scheduled_completion && dayjs(job.scheduled_completion),
actual_delivery: job.actual_delivery
? dayjs(job.actual_delivery)
: job.scheduled_delivery && dayjs(job.scheduled_delivery),
date_invoiced: job.date_invoiced ? dayjs(job.date_invoiced) : dayjs(),
kmin: job.kmin,
kmout: job.kmout,
dms_allocation: job.dms_allocation,
qb_multiple_payers: job.qb_multiple_payers
}}
scrollToFirstError
>
<PageHeader
title={t("jobs.labels.closejob", { ro_number: job.ro_number })}
extra={
<Space>
<JobsCloseAutoAllocate joblines={job.joblines} form={form} disabled={!!job.date_exported || jobRO} />
setLoading(false);
};
<Popconfirm
onConfirm={() => form.submit()}
disabled={jobRO}
okText={t("general.labels.yes")}
cancelText={t("general.labels.no")}
title={t("jobs.labels.closeconfirm")}
>
<Button loading={loading} type="primary" danger disabled={jobRO}>
{t("general.actions.close")}
</Button>
</Popconfirm>
{(bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid) && (
<Link to={`/manage/dms?jobId=${job.id}`}>
<Button disabled={job.date_exported || !jobRO}>{t("jobs.actions.sendtodms")}</Button>
</Link>
)}
<JobsScoreboardAdd job={job} disabled={false} />
</Space>
}
/>
return (
<div>
<Form
layout="vertical"
form={form}
onFinish={handleFinish}
initialValues={{
joblines: job.joblines,
actual_in: job.actual_in
? dayjs(job.actual_in)
: job.scheduled_in && dayjs(job.scheduled_in),
actual_completion: job.actual_completion
? dayjs(job.actual_completion)
: job.scheduled_completion && dayjs(job.scheduled_completion),
actual_delivery: job.actual_delivery
? dayjs(job.actual_delivery)
: job.scheduled_delivery && dayjs(job.scheduled_delivery),
date_invoiced: job.date_invoiced
? dayjs(job.date_invoiced)
: dayjs(),
kmin: job.kmin,
kmout: job.kmout,
dms_allocation: job.dms_allocation,
qb_multiple_payers: job.qb_multiple_payers,
}}
scrollToFirstError
>
<PageHeader
title={t("jobs.labels.closejob", {ro_number: job.ro_number})}
extra={
<Space>
<JobsCloseAutoAllocate
joblines={job.joblines}
form={form}
disabled={!!job.date_exported || jobRO}
/>
<Popconfirm
onConfirm={() => form.submit()}
disabled={jobRO}
okText={t("general.labels.yes")}
cancelText={t("general.labels.no")}
title={t("jobs.labels.closeconfirm")}
>
<Button loading={loading} type="primary" danger disabled={jobRO}>
{t("general.actions.close")}
</Button>
</Popconfirm>
{(bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid) && (
<Link to={`/manage/dms?jobId=${job.id}`}>
<Button disabled={job.date_exported || !jobRO}>
{t("jobs.actions.sendtodms")}
</Button>
</Link>
)}
<JobsScoreboardAdd job={job} disabled={false}/>
</Space>
<Space wrap direction="vertical" style={{ width: "100%" }}>
<FormsFieldChanged form={form} />
{!job.actual_in && job.scheduled_in && <Alert type="warning" message={t("jobs.labels.actual_in_inferred")} />}
{!job.actual_completion && job.scheduled_completion && (
<Alert type="warning" message={t("jobs.labels.actual_completion_inferred")} />
)}
{!job.actual_delivery && job.scheduled_delivery && (
<Alert type="warning" message={t("jobs.labels.actual_delivery_inferred")} />
)}
</Space>
<LayoutFormRow>
<Form.Item
label={t("jobs.fields.actual_in")}
rules={[
{
required: true
}
]}
name="actual_in"
>
<DateTimePicker disabled={jobRO} />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
return (
<Form.Item
label={t("jobs.fields.actual_completion")}
name="actual_completion"
rules={[
{
required: true
}
]}
>
<DateTimePicker disabled={jobRO} />
</Form.Item>
);
}}
</Form.Item>
<Form.Item
label={t("jobs.fields.actual_delivery")}
name="actual_delivery"
rules={[
{
required: true
}
]}
>
<DateTimePicker disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.date_invoiced")}
name="date_invoiced"
rules={[
{
required: true
},
({ getFieldValue }) => ({
validator(_, value) {
if (!bodyshop.cdk_dealerid) return Promise.resolve();
if (!value || dayjs(value).isSameOrAfter(dayjs(), "day")) {
return Promise.resolve();
}
return Promise.reject(new Error(t("jobs.labels.dms.invoicedatefuture")));
}
}),
({ getFieldValue }) => ({
validator(_, value) {
if (ClosingPeriod.treatment === "on" && bodyshop.accountingconfig.ClosingPeriod) {
if (
dayjs(value).isSameOrAfter(dayjs(bodyshop.accountingconfig.ClosingPeriod[0]).startOf("day")) &&
dayjs(value).isSameOrBefore(dayjs(bodyshop.accountingconfig.ClosingPeriod[1]).endOf("day"))
) {
return Promise.resolve();
} else {
return Promise.reject(new Error(t("jobs.labels.closingperiod")));
}
} else {
return Promise.resolve();
}
}
})
]}
>
<DateTimePicker disabled={jobRO} onlyFuture={!!bodyshop.cdk_dealerid} />
</Form.Item>
{!jobRO && job.inproduction && (
<Form.Item
label={t("jobs.actions.removefromproduction")}
name="removefromproduction"
valuePropName="checked"
>
<Switch />
</Form.Item>
)}
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.kmin")}
name="kmin"
rules={[
{
required: true
}
]}
>
<InputNumber precision={0} disabled={jobRO} />
</Form.Item>
)}
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.kmout")}
name="kmout"
dependencies={["kmin"]}
hasFeedback
rules={[
{
required: true
},
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue("kmin") <= value) {
return Promise.resolve();
}
/>
<Space wrap direction="vertical" style={{width: "100%"}}>
<FormsFieldChanged form={form}/>
{!job.actual_in && job.scheduled_in && (
<Alert
type="warning"
message={t("jobs.labels.actual_in_inferred")}
/>
)}
{!job.actual_completion && job.scheduled_completion && (
<Alert
type="warning"
message={t("jobs.labels.actual_completion_inferred")}
/>
)}
{!job.actual_delivery && job.scheduled_delivery && (
<Alert
type="warning"
message={t("jobs.labels.actual_delivery_inferred")}
/>
)}
</Space>
<LayoutFormRow>
<Form.Item
label={t("jobs.fields.actual_in")}
rules={[
{
required: true,
},
]}
name="actual_in"
>
<DateTimePicker disabled={jobRO}/>
</Form.Item>
<Form.Item shouldUpdate>
{() => {
return (
<Form.Item
label={t("jobs.fields.actual_completion")}
name="actual_completion"
rules={[
{
required: true,
},
]}
>
<DateTimePicker disabled={jobRO}/>
</Form.Item>
return Promise.reject(new Error(t("jobs.labels.dms.kmoutnotgreaterthankmin")));
}
})
]}
>
<InputNumber precision={0} disabled={jobRO} />
</Form.Item>
)}
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.dms_allocation")}
name="dms_allocation"
rules={[
{
required: true
}
]}
>
<Input disabled />
</Form.Item>
)}
</LayoutFormRow>
{Qb_Multi_Ar.treatment === "on" && (
<>
<Divider>{t("jobs.labels.multipayers")}</Divider>
<Row gutter={[16, 16]}>
<Col lg={8} md={24}>
<Form.List
name={["qb_multiple_payers"]}
rules={[
({ getFieldValue }) => ({
validator(_, value) {
let totalAllocated = Dinero();
const payers = form.getFieldValue("qb_multiple_payers");
payers &&
payers.forEach((payer) => {
totalAllocated = totalAllocated.add(
Dinero({
amount: Math.round((payer?.amount || 0) * 100)
})
);
}}
</Form.Item>
<Form.Item
label={t("jobs.fields.actual_delivery")}
name="actual_delivery"
rules={[
{
required: true,
},
]}
>
<DateTimePicker disabled={jobRO}/>
</Form.Item>
<Form.Item
label={t("jobs.fields.date_invoiced")}
name="date_invoiced"
rules={[
{
required: true,
},
({getFieldValue}) => ({
validator(_, value) {
if (!bodyshop.cdk_dealerid) return Promise.resolve();
if (!value || dayjs(value).isSameOrAfter(dayjs(), "day")) {
return Promise.resolve();
}
return Promise.reject(
new Error(t("jobs.labels.dms.invoicedatefuture"))
);
},
}),
({getFieldValue}) => ({
validator(_, value) {
if (
ClosingPeriod.treatment === "on" &&
bodyshop.accountingconfig.ClosingPeriod
) {
if (
dayjs(value).isSameOrAfter(
dayjs(
bodyshop.accountingconfig.ClosingPeriod[0]
).startOf("day")
) &&
dayjs(value).isSameOrBefore(
dayjs(
bodyshop.accountingconfig.ClosingPeriod[1]
).endOf("day")
)
) {
return Promise.resolve();
} else {
return Promise.reject(
new Error(t("jobs.labels.closingperiod"))
);
}
} else {
return Promise.resolve();
}
},
}),
]}
>
<DateTimePicker
disabled={jobRO}
onlyFuture={!!bodyshop.cdk_dealerid}
/>
</Form.Item>
{!jobRO && job.inproduction && (
<Form.Item
label={t("jobs.actions.removefromproduction")}
name="removefromproduction"
valuePropName="checked"
>
<Switch/>
</Form.Item>
)}
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.kmin")}
name="kmin"
rules={[
{
required: true,
},
]}
>
<InputNumber precision={0} disabled={jobRO}/>
</Form.Item>
)}
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.kmout")}
name="kmout"
dependencies={["kmin"]}
hasFeedback
rules={[
{
required: true,
},
({getFieldValue}) => ({
validator(_, value) {
if (!value || getFieldValue("kmin") <= value) {
return Promise.resolve();
}
return Promise.reject(
new Error(t("jobs.labels.dms.kmoutnotgreaterthankmin"))
);
},
}),
]}
>
<InputNumber precision={0} disabled={jobRO}/>
</Form.Item>
)}
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.dms_allocation")}
name="dms_allocation"
rules={[
{
required: true,
},
]}
>
<Input disabled/>
</Form.Item>
)}
</LayoutFormRow>
{Qb_Multi_Ar.treatment === "on" && (
<><Divider>{t("jobs.labels.multipayers")}</Divider>
<Row gutter={[16, 16]}>
<Col lg={8} md={24}>
<Form.List
name={["qb_multiple_payers"]}
});
const discrep = job.job_totals
? Dinero(job.job_totals.totals.total_repairs).subtract(totalAllocated)
: Dinero();
return discrep.getAmount() >= 0
? Promise.resolve()
: Promise.reject(new Error(t("jobs.labels.additionalpayeroverallocation")));
}
})
]}
>
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key}>
<Space>
<Form.Item
label={t("jobs.fields.qb_multiple_payers.name")}
key={`${index}name`}
name={[field.name, "name"]}
rules={[
({getFieldValue}) => ({
validator(_, value) {
let totalAllocated = Dinero();
const payers = form.getFieldValue("qb_multiple_payers");
payers &&
payers.forEach((payer) => {
totalAllocated = totalAllocated.add(
Dinero({
amount: Math.round((payer?.amount || 0) * 100),
})
);
});
const discrep = job.job_totals
? Dinero(job.job_totals.totals.total_repairs).subtract(
totalAllocated
)
: Dinero();
return discrep.getAmount() >= 0
? Promise.resolve()
: Promise.reject(
new Error(
t("jobs.labels.additionalpayeroverallocation")
)
);
},
}),
{
required: true
}
]}
>
{(fields, {add, remove}) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key}>
<Space>
<Form.Item
label={t("jobs.fields.qb_multiple_payers.name")}
key={`${index}name`}
name={[field.name, "name"]}
rules={[
{
required: true,
},
]}
>
<Select
style={{minWidth: "12rem"}}
disabled={jobRO}
>
{bodyshop.md_ins_cos.map((s) => (
<Select.Option key={s.name} value={s.name}>
{s.name}
</Select.Option>
))}
</Select>
</Form.Item>
>
<Select style={{ minWidth: "12rem" }} disabled={jobRO}>
{bodyshop.md_ins_cos.map((s) => (
<Select.Option key={s.name} value={s.name}>
{s.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("jobs.fields.qb_multiple_payers.amount")}
key={`${index}amount`}
name={[field.name, "amount"]}
rules={[
{
required: true,
},
]}
>
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item
label={t("jobs.fields.qb_multiple_payers.amount")}
key={`${index}amount`}
name={[field.name, "amount"]}
rules={[
{
required: true
}
]}
>
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<DeleteFilled
disabled={jobRO}
onClick={() => {
if(!jobRO){
remove(field.name);
}
}}
/>
</Space>
</Form.Item>
))}
<Form.Item>
<Button
disabled={jobRO}
onClick={() => {
add();
}}
style={{width: "100%"}}
>
{t("jobs.actions.dms.addpayer")}
</Button>
</Form.Item>
</div>
);
<DeleteFilled
disabled={jobRO}
onClick={() => {
if (!jobRO) {
remove(field.name);
}
}}
</Form.List>
</Col>
<Col lg={16} md={24}>
<Form.Item shouldUpdate>
{() => {
//Perform Calculation to determine discrepancy.
let totalAllocated = Dinero();
/>
</Space>
</Form.Item>
))}
<Form.Item>
<Button
disabled={jobRO}
onClick={() => {
add();
}}
style={{ width: "100%" }}
>
{t("jobs.actions.dms.addpayer")}
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</Col>
<Col lg={16} md={24}>
<Form.Item shouldUpdate>
{() => {
//Perform Calculation to determine discrepancy.
let totalAllocated = Dinero();
const payers = form.getFieldValue("qb_multiple_payers");
payers &&
payers.forEach((payer) => {
totalAllocated = totalAllocated.add(
Dinero({
amount: Math.round((payer?.amount || 0) * 100),
})
);
});
const discrep = job.job_totals
? Dinero(job.job_totals.totals.total_repairs).subtract(
totalAllocated
)
: Dinero();
return (
<Space size="large" wrap align="center">
<Statistic
title={t("jobs.labels.total_cust_payable")}
value={(job.job_totals
? Dinero(job.job_totals.totals.custPayable)
: Dinero()
).toFormat()}
/>
<Divider type="vertical"/>
<Statistic
title={t("jobs.labels.total_repairs")}
value={(job.job_totals
? Dinero(job.job_totals.totals.total_repairs)
: Dinero()
).toFormat()}
/>
<Typography.Title>-</Typography.Title>
<Statistic
title={t("jobs.labels.dms.totalallocated")}
value={totalAllocated.toFormat()}
/>
<Typography.Title>=</Typography.Title>
<Statistic
title={t("jobs.labels.pimraryamountpayable")}
valueStyle={{
color: discrep.getAmount() > 0 ? "green" : "red",
}}
value={discrep.toFormat()}
/>
</Space>
);
}}
</Form.Item>
</Col>
</Row>
</>
)}
<Divider/>
<JobsCloseLines job={job}/>
</Form>
</div>
);
const payers = form.getFieldValue("qb_multiple_payers");
payers &&
payers.forEach((payer) => {
totalAllocated = totalAllocated.add(
Dinero({
amount: Math.round((payer?.amount || 0) * 100)
})
);
});
const discrep = job.job_totals
? Dinero(job.job_totals.totals.total_repairs).subtract(totalAllocated)
: Dinero();
return (
<Space size="large" wrap align="center">
<Statistic
title={t("jobs.labels.total_cust_payable")}
value={(job.job_totals ? Dinero(job.job_totals.totals.custPayable) : Dinero()).toFormat()}
/>
<Divider type="vertical" />
<Statistic
title={t("jobs.labels.total_repairs")}
value={(job.job_totals ? Dinero(job.job_totals.totals.total_repairs) : Dinero()).toFormat()}
/>
<Typography.Title>-</Typography.Title>
<Statistic title={t("jobs.labels.dms.totalallocated")} value={totalAllocated.toFormat()} />
<Typography.Title>=</Typography.Title>
<Statistic
title={t("jobs.labels.pimraryamountpayable")}
valueStyle={{
color: discrep.getAmount() > 0 ? "green" : "red"
}}
value={discrep.toFormat()}
/>
</Space>
);
}}
</Form.Item>
</Col>
</Row>
</>
)}
<Divider />
<JobsCloseLines job={job} />
</Form>
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(JobsCloseComponent);

View File

@@ -1,87 +1,82 @@
import {useQuery} from "@apollo/client";
import {Result} from "antd";
import React, {useEffect} from "react";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {useParams} from "react-router-dom";
import { useQuery } from "@apollo/client";
import { Result } from "antd";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useParams } from "react-router-dom";
import AlertComponent from "../../components/alert/alert.component";
import JobCalculateTotals from "../../components/job-calculate-totals/job-calculate-totals.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import NotFound from "../../components/not-found/not-found.component";
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import {QUERY_JOB_CLOSE_DETAILS} from "../../graphql/jobs.queries";
import {setBreadcrumbs, setJobReadOnly, setSelectedHeader,} from "../../redux/application/application.actions";
import { QUERY_JOB_CLOSE_DETAILS } from "../../graphql/jobs.queries";
import { setBreadcrumbs, setJobReadOnly, setSelectedHeader } from "../../redux/application/application.actions";
import IsJobReadOnly from "../../utils/jobReadOnly";
import JobsCloseComponent from "./jobs-close.component";
import InstanceRenderManager from '../../utils/instanceRenderMgr';
import InstanceRenderManager from "../../utils/instanceRenderMgr";
const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
setJobReadOnly: (bool) => dispatch(setJobReadOnly(bool)),
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
setJobReadOnly: (bool) => dispatch(setJobReadOnly(bool))
});
export function JobsCloseContainer({
setBreadcrumbs,
setSelectedHeader,
setJobReadOnly,
}) {
const {jobId} = useParams();
const {loading, error, data} = useQuery(QUERY_JOB_CLOSE_DETAILS, {
variables: {id: jobId},
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, setJobReadOnly }) {
const { jobId } = useParams();
const { loading, error, data } = useQuery(QUERY_JOB_CLOSE_DETAILS, {
variables: { id: jobId },
fetchPolicy: "network-only",
nextFetchPolicy: "network-only"
});
const { t } = useTranslation();
useEffect(() => {
if (data && data.jobs_by_pk) {
setJobReadOnly(IsJobReadOnly(data.jobs_by_pk));
}
}, [data, setJobReadOnly]);
useEffect(() => {
setSelectedHeader("activejobs");
document.title = t("titles.jobs-close", {
app: InstanceRenderManager({
imex: "$t(titles.imexonline)",
rome: "$t(titles.romeonline)",
promanager: "$t(titles.promanager)"
}),
number: data ? data.jobs_by_pk && data.jobs_by_pk.ro_number : null
});
const {t} = useTranslation();
useEffect(() => {
if (data && data.jobs_by_pk) {
setJobReadOnly(IsJobReadOnly(data.jobs_by_pk));
}
}, [data, setJobReadOnly]);
useEffect(() => {
setSelectedHeader("activejobs");
document.title = t("titles.jobs-close", {
app: InstanceRenderManager({imex:'$t(titles.imexonline)', rome: '$t(titles.romeonline)', promanager: '$t(titles.promanager)'}),
number: data ? data.jobs_by_pk && data.jobs_by_pk.ro_number : null,
});
setBreadcrumbs([
{
link: `/manage/jobs/${jobId}/`,
label: t("titles.bc.jobs"),
},
{
link: `/manage/jobs/${jobId}/`,
label: t("titles.bc.jobs-detail", {
number: data ? data.jobs_by_pk && data.jobs_by_pk.ro_number : null,
}),
},
{
link: `/manage/jobs/${jobId}/close`,
label: t("titles.bc.jobs-close"),
},
]);
}, [setBreadcrumbs, t, jobId, data, setSelectedHeader]);
setBreadcrumbs([
{
link: `/manage/jobs/${jobId}/`,
label: t("titles.bc.jobs")
},
{
link: `/manage/jobs/${jobId}/`,
label: t("titles.bc.jobs-detail", {
number: data ? data.jobs_by_pk && data.jobs_by_pk.ro_number : null
})
},
{
link: `/manage/jobs/${jobId}/close`,
label: t("titles.bc.jobs-close")
}
]);
}, [setBreadcrumbs, t, jobId, data, setSelectedHeader]);
if (loading) return <LoadingSpinner/>;
if (error) return <AlertComponent message={error.message} type="error"/>;
if (!!!data.jobs_by_pk) return <NotFound/>;
if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />;
if (!!!data.jobs_by_pk) return <NotFound />;
if (!data.jobs_by_pk.job_totals)
return (
<Result
title={t("jobs.errors.nofinancial")}
extra={<JobCalculateTotals job={data.jobs_by_pk}/>}
/>
);
if (!data.jobs_by_pk.job_totals)
return <Result title={t("jobs.errors.nofinancial")} extra={<JobCalculateTotals job={data.jobs_by_pk} />} />;
return (
<RbacWrapper action="jobs:close">
<div>
<JobsCloseComponent job={data ? data.jobs_by_pk : {}}/>
</div>
</RbacWrapper>
);
return (
<RbacWrapper action="jobs:close">
<div>
<JobsCloseComponent job={data ? data.jobs_by_pk : {}} />
</div>
</RbacWrapper>
);
}
export default connect(null, mapDispatchToProps)(JobsCloseContainer);