IO-990 Refactor job closing.
This commit is contained in:
@@ -56,7 +56,13 @@ export function JobsChangeStatus({ job, bodyshop, jobRO }) {
|
|||||||
} else if (
|
} else if (
|
||||||
bodyshop.md_ro_statuses.post_production_statuses.includes(job.status)
|
bodyshop.md_ro_statuses.post_production_statuses.includes(job.status)
|
||||||
) {
|
) {
|
||||||
setAvailableStatuses(bodyshop.md_ro_statuses.post_production_statuses);
|
setAvailableStatuses(
|
||||||
|
bodyshop.md_ro_statuses.post_production_statuses.filter(
|
||||||
|
(s) =>
|
||||||
|
s !== bodyshop.md_ro_statuses.default_invoiced &&
|
||||||
|
s !== bodyshop.md_ro_statuses.default_exported
|
||||||
|
)
|
||||||
|
);
|
||||||
if (bodyshop.md_ro_statuses.production_statuses[0])
|
if (bodyshop.md_ro_statuses.production_statuses[0])
|
||||||
setOtherStages([bodyshop.md_ro_statuses.production_statuses[0]]);
|
setOtherStages([bodyshop.md_ro_statuses.production_statuses[0]]);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1406,6 +1406,8 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
|
|||||||
rate_matd
|
rate_matd
|
||||||
status
|
status
|
||||||
date_exported
|
date_exported
|
||||||
|
date_invoiced
|
||||||
|
voided
|
||||||
joblines(where: { removed: { _eq: false } }) {
|
joblines(where: { removed: { _eq: false } }) {
|
||||||
id
|
id
|
||||||
removed
|
removed
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ import { Button, Form, notification, Popconfirm, Space } from "antd";
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { useHistory } from "react-router-dom";
|
//import { useHistory } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import FormsFieldChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
|
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 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 JobsCloseAutoAllocate from "../../components/jobs-close-auto-allocate/jobs-close-auto-allocate.component";
|
||||||
import JobsCloseExportButton from "../../components/jobs-close-export-button/jobs-close-export-button.component";
|
|
||||||
import JobsCloseLines from "../../components/jobs-close-lines/jobs-close-lines.component";
|
import JobsCloseLines from "../../components/jobs-close-lines/jobs-close-lines.component";
|
||||||
import { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.queries";
|
import { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.queries";
|
||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
@@ -23,12 +22,9 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
const history = useHistory();
|
// const history = useHistory();
|
||||||
const [closeJob] = useMutation(UPDATE_JOB);
|
const [closeJob] = useMutation(UPDATE_JOB);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
// useEffect(() => {
|
|
||||||
// //if (job && form) form.setFields({ joblines: job.joblines });
|
|
||||||
// }, [job, form]);
|
|
||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (values) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -37,7 +33,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
|
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
|
||||||
awaitRefetchQueries: true,
|
awaitRefetchQueries: true,
|
||||||
});
|
});
|
||||||
if (!!!result.errors) {
|
if (!result.errors) {
|
||||||
notification["success"]({ message: t("jobs.successes.save") });
|
notification["success"]({ message: t("jobs.successes.save") });
|
||||||
// form.resetFields();
|
// form.resetFields();
|
||||||
} else {
|
} else {
|
||||||
@@ -46,15 +42,12 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
error: JSON.stringify(result.errors),
|
error: JSON.stringify(result.errors),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
return; // Abandon the rest of the close.
|
||||||
}
|
}
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
setLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = async () => {
|
const closeResult = await closeJob({
|
||||||
setLoading(true);
|
|
||||||
const result = await closeJob({
|
|
||||||
variables: {
|
variables: {
|
||||||
jobId: job.id,
|
jobId: job.id,
|
||||||
job: {
|
job: {
|
||||||
@@ -64,21 +57,23 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!!!result.errors) {
|
if (!closeResult.errors) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("jobs.successes.closed"),
|
message: t("jobs.successes.closed"),
|
||||||
});
|
});
|
||||||
history.push(`/manage/jobs/${job.id}`);
|
// history.push(`/manage/jobs/${job.id}`);
|
||||||
} else {
|
} else {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("job.errors.closing", {
|
message: t("job.errors.closing", {
|
||||||
error: JSON.stringify(result.errors),
|
error: JSON.stringify(closeResult.errors),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -97,16 +92,18 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
disabled={!!job.date_exported || jobRO}
|
disabled={!!job.date_exported || jobRO}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
{
|
||||||
loading={loading}
|
// <Button
|
||||||
onClick={() => form.submit()}
|
// loading={loading}
|
||||||
disabled={jobRO}
|
// onClick={() => form.submit()}
|
||||||
>
|
// disabled={jobRO}
|
||||||
{t("general.actions.save")}
|
// >
|
||||||
</Button>
|
// {t("general.actions.save")}
|
||||||
|
// </Button>
|
||||||
|
}
|
||||||
|
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
onConfirm={handleClose}
|
onConfirm={() => form.submit()}
|
||||||
disabled={jobRO}
|
disabled={jobRO}
|
||||||
okText={t("general.labels.yes")}
|
okText={t("general.labels.yes")}
|
||||||
cancelText={t("general.labels.no")}
|
cancelText={t("general.labels.no")}
|
||||||
@@ -118,7 +115,9 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|
||||||
<JobsScoreboardAdd job={job} disabled={false} />
|
<JobsScoreboardAdd job={job} disabled={false} />
|
||||||
<JobsCloseExportButton jobId={job.id} disabled={job.date_exported} />
|
{
|
||||||
|
// <JobsCloseExportButton jobId={job.id} disabled={job.date_exported} />
|
||||||
|
}
|
||||||
</Space>
|
</Space>
|
||||||
<FormsFieldChanged form={form} />
|
<FormsFieldChanged form={form} />
|
||||||
<JobsCloseLines job={job} />
|
<JobsCloseLines job={job} />
|
||||||
|
|||||||
@@ -1,32 +1,44 @@
|
|||||||
import { useQuery } from "@apollo/client";
|
import { useQuery } from "@apollo/client";
|
||||||
|
import { Result } from "antd";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import AlertComponent from "../../components/alert/alert.component";
|
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 LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||||
import NotFound from "../../components/not-found/not-found.component";
|
import NotFound from "../../components/not-found/not-found.component";
|
||||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||||
import { QUERY_JOB_CLOSE_DETAILS } from "../../graphql/jobs.queries";
|
import { QUERY_JOB_CLOSE_DETAILS } from "../../graphql/jobs.queries";
|
||||||
import {
|
import {
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
|
setJobReadOnly,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
|
import IsJobReadOnly from "../../utils/jobReadOnly";
|
||||||
import JobsCloseComponent from "./jobs-close.component";
|
import JobsCloseComponent from "./jobs-close.component";
|
||||||
import { Result } from "antd";
|
|
||||||
import JobCalculateTotals from "../../components/job-calculate-totals/job-calculate-totals.component";
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||||
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
|
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
|
||||||
|
setJobReadOnly: (bool) => dispatch(setJobReadOnly(bool)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader }) {
|
export function JobsCloseContainer({
|
||||||
|
setBreadcrumbs,
|
||||||
|
setSelectedHeader,
|
||||||
|
setJobReadOnly,
|
||||||
|
}) {
|
||||||
const { jobId } = useParams();
|
const { jobId } = useParams();
|
||||||
const { loading, error, data } = useQuery(QUERY_JOB_CLOSE_DETAILS, {
|
const { loading, error, data } = useQuery(QUERY_JOB_CLOSE_DETAILS, {
|
||||||
variables: { id: jobId },
|
variables: { id: jobId },
|
||||||
});
|
});
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
useEffect(() => {
|
||||||
|
if (data && data.jobs_by_pk) {
|
||||||
|
setJobReadOnly(IsJobReadOnly(data.jobs_by_pk));
|
||||||
|
}
|
||||||
|
}, [data, setJobReadOnly]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedHeader("activejobs");
|
setSelectedHeader("activejobs");
|
||||||
document.title = t("titles.jobs-close", {
|
document.title = t("titles.jobs-close", {
|
||||||
@@ -54,6 +66,7 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader }) {
|
|||||||
if (loading) return <LoadingSpinner />;
|
if (loading) return <LoadingSpinner />;
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
if (!!!data.jobs_by_pk) return <NotFound />;
|
if (!!!data.jobs_by_pk) return <NotFound />;
|
||||||
|
|
||||||
if (!data.jobs_by_pk.job_totals)
|
if (!data.jobs_by_pk.job_totals)
|
||||||
return (
|
return (
|
||||||
<Result
|
<Result
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import { CreateRecentItem } from "../../utils/create-recent-item";
|
import { CreateRecentItem } from "../../utils/create-recent-item";
|
||||||
|
import IsJobReadOnly from "../../utils/jobReadOnly";
|
||||||
import JobsDetailPage from "./jobs-detail.page.component";
|
import JobsDetailPage from "./jobs-detail.page.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
@@ -70,11 +71,7 @@ function JobsDetailPageContainer({
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (data && data.jobs_by_pk) {
|
if (data && data.jobs_by_pk) {
|
||||||
setJobReadOnly(
|
setJobReadOnly(IsJobReadOnly(data.jobs_by_pk));
|
||||||
data.jobs_by_pk.date_exported ||
|
|
||||||
data.jobs_by_pk.date_invoiced ||
|
|
||||||
data.jobs_by_pk.voided
|
|
||||||
);
|
|
||||||
|
|
||||||
addRecentItem(
|
addRecentItem(
|
||||||
CreateRecentItem(
|
CreateRecentItem(
|
||||||
|
|||||||
4
client/src/utils/jobReadOnly.js
Normal file
4
client/src/utils/jobReadOnly.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default function IsJobReadOnly(job) {
|
||||||
|
if (!job) return false;
|
||||||
|
return job.date_exported || job.date_invoiced || job.voided;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user