290 lines
9.1 KiB
JavaScript
290 lines
9.1 KiB
JavaScript
import { useApolloClient, useMutation } from "@apollo/client";
|
|
import {
|
|
Button,
|
|
Form,
|
|
notification,
|
|
Popconfirm,
|
|
Space,
|
|
Alert,
|
|
Divider,
|
|
PageHeader,
|
|
InputNumber,
|
|
Input,
|
|
} from "antd";
|
|
import React, { useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { connect } from "react-redux";
|
|
//import { useHistory } from "react-router-dom";
|
|
import { createStructuredSelector } from "reselect";
|
|
import FormsFieldChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
|
|
import JobsScoreboardAdd from "../../components/job-scoreboard-add-button/job-scoreboard-add-button.component";
|
|
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 { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.queries";
|
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
|
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
import LayoutFormRow from "../../components/layout-form-row/layout-form-row.component";
|
|
import DateTimePicker from "../../components/form-date-time-picker/form-date-time-picker.component";
|
|
import moment from "moment";
|
|
import { Link } from "react-router-dom";
|
|
|
|
const mapStateToProps = createStructuredSelector({
|
|
bodyshop: selectBodyshop,
|
|
jobRO: selectJobReadOnly,
|
|
});
|
|
|
|
export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|
const { t } = useTranslation();
|
|
const [form] = Form.useForm();
|
|
const client = useApolloClient();
|
|
// const history = useHistory();
|
|
const [closeJob] = useMutation(UPDATE_JOB);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handleFinish = async (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: new Date(),
|
|
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,
|
|
invoice_final_note: values.invoice_final_note,
|
|
},
|
|
},
|
|
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
|
|
awaitRefetchQueries: true,
|
|
});
|
|
|
|
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.
|
|
}
|
|
|
|
if (!closeResult.errors) {
|
|
setLoading(false);
|
|
|
|
notification["success"]({
|
|
message: t("jobs.successes.closed"),
|
|
});
|
|
// history.push(`/manage/jobs/${job.id}`);
|
|
} else {
|
|
setLoading(false);
|
|
notification["error"]({
|
|
message: t("job.errors.closing", {
|
|
error: JSON.stringify(closeResult.errors),
|
|
}),
|
|
});
|
|
}
|
|
form.resetFields();
|
|
form.resetFields();
|
|
|
|
setLoading(false);
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<Form
|
|
layout="vertical"
|
|
form={form}
|
|
onFinish={handleFinish}
|
|
initialValues={{
|
|
joblines: job.joblines,
|
|
actual_in: job.actual_in
|
|
? moment(job.actual_in)
|
|
: job.scheduled_in && moment(job.scheduled_in),
|
|
actual_completion: job.actual_completion
|
|
? moment(job.actual_completion)
|
|
: job.scheduled_completion && moment(job.scheduled_completion),
|
|
actual_delivery: job.actual_delivery
|
|
? moment(job.actual_delivery)
|
|
: job.scheduled_delivery && moment(job.scheduled_delivery),
|
|
kmin: job.kmin,
|
|
kmout: job.kmout,
|
|
dms_allocation: job.dms_allocation,
|
|
invoice_final_note: job.invoice_final_note,
|
|
}}
|
|
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="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>
|
|
{(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>
|
|
)}
|
|
<Form.Item
|
|
label={t("jobs.fields.invoice_final_note")}
|
|
name="invoice_final_note"
|
|
>
|
|
<Input.TextArea disabled={jobRO} />
|
|
</Form.Item>
|
|
</LayoutFormRow>
|
|
<Divider />
|
|
<JobsCloseLines job={job} />
|
|
</Form>
|
|
</div>
|
|
);
|
|
}
|
|
export default connect(mapStateToProps, null)(JobsCloseComponent);
|