Added view intake and deliver checklists. IO-241

This commit is contained in:
Patrick Fic
2021-02-23 16:34:27 -08:00
parent 7e3200a993
commit 707eab563a
12 changed files with 339 additions and 8 deletions

View File

@@ -14203,6 +14203,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>viewchecklist</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>viewdetail</name>
<definition_loaded>false</definition_loaded>
@@ -18569,6 +18590,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>checklistcompletedby</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>checklists</name>
<definition_loaded>false</definition_loaded>
@@ -18915,6 +18957,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>deliverchecklist</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>difference</name>
<definition_loaded>false</definition_loaded>
@@ -19209,6 +19272,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>intakechecklist</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>job</name>
<definition_loaded>false</definition_loaded>
@@ -28398,6 +28482,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobs-checklist</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobs-close</name>
<definition_loaded>false</definition_loaded>
@@ -29072,6 +29177,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobs-checklist</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobs-close</name>
<definition_loaded>false</definition_loaded>

View File

@@ -30,6 +30,7 @@ export function JobChecklistForm({
currentUser,
type,
job,
readOnly = false,
}) {
const { t } = useTranslation();
const [intakeJob] = useMutation(UPDATE_JOB);
@@ -63,6 +64,12 @@ export function JobChecklistForm({
[(type === "intake" && "intakechecklist") ||
(type === "deliver" && "deliverchecklist")]: {
...values,
formItems: formItems.map((fi) => {
return {
...fi,
value: values[fi.name],
};
}),
completed_by: currentUser.email,
completed_at: new Date(),
},
@@ -118,11 +125,17 @@ export function JobChecklistForm({
removeFromProduction: true,
actual_completion: job && job.actual_completion,
}),
...formItems
.filter((fi) => fi.value)
.reduce((acc, fi) => {
acc[fi.name] = fi.value;
return acc;
}, {}),
}}
>
{t("checklist.labels.checklist")}
<ConfigFormComponents componentList={formItems} />
<ConfigFormComponents componentList={formItems} readOnly={readOnly} />
{type === "intake" && (
<div>
@@ -130,12 +143,14 @@ export function JobChecklistForm({
name="addToProduction"
valuePropName="checked"
label={t("checklist.labels.addtoproduction")}
disabled={readOnly}
>
<Switch />
</Form.Item>
<Form.Item
name="scheduled_completion"
label={t("jobs.fields.scheduled_completion")}
disabled={readOnly}
rules={[
{
required: true,
@@ -148,6 +163,7 @@ export function JobChecklistForm({
<Form.Item
name="scheduled_delivery"
label={t("jobs.fields.scheduled_delivery")}
disabled={readOnly}
>
<DateTimePicker />
</Form.Item>
@@ -158,6 +174,7 @@ export function JobChecklistForm({
<Form.Item
name="actual_completion"
label={t("jobs.fields.actual_completion")}
disabled={readOnly}
rules={[
{
required: true,
@@ -171,15 +188,17 @@ export function JobChecklistForm({
name="removeFromProduction"
valuePropName="checked"
label={t("checklist.labels.removefromproduction")}
disabled={readOnly}
>
<Switch defaultChecked={true} />
</Form.Item>
</div>
)}
<Button loading={loading} htmlType="submit">
{t("general.actions.submit")}
</Button>
{!readOnly && (
<Button loading={loading} htmlType="submit">
{t("general.actions.submit")}
</Button>
)}
</Form>
);
}

View File

@@ -105,6 +105,11 @@ export function JobsDetailHeaderActions({
</Link>
)}
</Menu.Item>
<Menu.Item>
<Link to={`/manage/jobs/${job.id}/checklist`}>
{t("jobs.actions.viewchecklist")}
</Link>
</Menu.Item>
<Menu.Item
key="enterpayments"
disabled={jobRO}

View File

@@ -23,6 +23,7 @@ const ret = {
"jobs:close": 5,
"jobs:detail": 1,
"jobs:partsqueue": 4,
"jobs:checklist-view": 2,
"bills:enter": 2,
"bills:view": 2,

View File

@@ -137,7 +137,6 @@ export function ScheduleEventComponent({
</Space>
<Space>
<span>
{" "}
{`${(event.job && event.job.v_model_yr) || ""} ${
(event.job && event.job.v_make_desc) || ""
} ${(event.job && event.job.v_model_desc) || ""}`}

View File

@@ -260,6 +260,18 @@ export default function ShopInfoRbacComponent({ form }) {
>
<InputNumber />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.rbac.jobs.checklist-view")}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
name={["md_rbac", "jobs:checklist-view"]}
>
<InputNumber />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.rbac.bills.enter")}
rules={[

View File

@@ -377,7 +377,7 @@ export const GET_JOB_BY_PK = gql`
est_co_nm
est_ct_fn
est_ct_ln
est_ph1
est_ea
selling_dealer
@@ -981,7 +981,7 @@ export const QUERY_ALL_JOB_FIELDS = gql`
parts_tax_rates
pay_amt
pay_chknm
pay_type
payee_nms
plate_no
@@ -1354,3 +1354,22 @@ export const GET_JOB_FOR_CC_CONTRACT = gql`
}
}
`;
export const QUERY_JOB_CHECKLISTS = gql`
query QUERY_JOB_CHECKLISTS($id: uuid!) {
jobs_by_pk(id: $id) {
id
deliverchecklist
intakechecklist
ro_number
scheduled_completion
actual_completion
scheduled_delivery
bodyshop {
id
intakechecklist
deliverchecklist
}
}
}
`;

View File

@@ -0,0 +1,124 @@
import { useQuery } from "@apollo/react-hooks";
import { Col, Row, Typography } from "antd";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useParams } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component";
import JobChecklistForm from "../../components/job-checklist/components/job-checklist-form/job-checklist-form.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import { QUERY_JOB_CHECKLISTS } from "../../graphql/jobs.queries";
import {
setBreadcrumbs,
setSelectedHeader,
} from "../../redux/application/application.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import moment from "moment";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
});
export function JobsChecklistViewContainer({
bodyshop,
setBreadcrumbs,
setSelectedHeader,
}) {
const { t } = useTranslation();
const { jobId } = useParams();
const { loading, error, data } = useQuery(QUERY_JOB_CHECKLISTS, {
variables: { id: jobId },
});
useEffect(() => {
document.title = t("titles.jobs-checklist");
setSelectedHeader("activejobs");
setBreadcrumbs([
{ link: "/manage/jobs", 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) || "",
}),
},
{
link: `/manage/jobs/${jobId}/checklist`,
label: t("titles.bc.jobs-checklist"),
},
]);
}, [t, setBreadcrumbs, jobId, data, setSelectedHeader]);
if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />;
//The Form is the actual config to use.
const CompletedBy = ({ checklist }) => (
<div>
<div>
{t("jobs.labels.checklistcompletedby", {
by: checklist.completed_by,
at: moment(checklist.completed_at).format("MM/DD/YYYY @ h:mm a"),
})}
</div>
</div>
);
return (
<RbacWrapper action="jobs:checklist-view">
<Row gutter={[32, 32]}>
<Col span={12}>
<Typography.Title level={4}>
{t("jobs.labels.intakechecklist")}
</Typography.Title>
{data.jobs_by_pk.intakechecklist &&
data.jobs_by_pk.intakechecklist.formItems && (
<>
<JobChecklistForm
formItems={
data.jobs_by_pk.intakechecklist &&
data.jobs_by_pk.intakechecklist.formItems
}
type="intake"
job={data.jobs_by_pk}
readOnly
/>
<CompletedBy checklist={data.jobs_by_pk.intakechecklist} />
</>
)}
</Col>
<Col span={12}>
<Typography.Title level={4}>
{t("jobs.labels.deliverchecklist")}
</Typography.Title>
{data.jobs_by_pk.deliverchecklist &&
data.jobs_by_pk.deliverchecklist.formItems && (
<>
<JobChecklistForm
formItems={
data.jobs_by_pk.deliverchecklist &&
data.jobs_by_pk.deliverchecklist.formItems
}
type="deliver"
job={data.jobs_by_pk}
readOnly
/>
<CompletedBy checklist={data.jobs_by_pk.deliverchecklist} />
</>
)}
</Col>
</Row>
</RbacWrapper>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobsChecklistViewContainer);

View File

@@ -106,6 +106,9 @@ const ShopTemplates = lazy(() =>
const JobIntake = lazy(() =>
import("../jobs-intake/jobs-intake.page.container")
);
const JobChecklistView = lazy(() =>
import("../jobs-checklist-view/jobs-checklist-view.page")
);
const JobDeliver = lazy(() =>
import("../jobs-deliver/jobs-delivery.page.container")
);
@@ -218,6 +221,11 @@ export function Manage({ match, conflict }) {
path={`${match.path}/jobs/:jobId/deliver`}
component={JobDeliver}
/>
<Route
exact
path={`${match.path}/jobs/:jobId/checklist`}
component={JobChecklistView}
/>
<Route
exact
path={`${match.path}/jobs/:jobId/close`}

View File

@@ -908,6 +908,7 @@
"schedule": "Schedule",
"sendcsi": "Send CSI",
"sync": "Sync",
"viewchecklist": "View Checklists",
"viewdetail": "View Details"
},
"errors": {
@@ -1130,6 +1131,7 @@
"vehicle": "Vehicle"
},
"changeclass": "Changing the job's class can have fundamental impacts to already exported accounting items. Are you sure you want to do this?",
"checklistcompletedby": "Checklist completed by {{by}} at {{at}}",
"checklists": "Checklists",
"closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.",
"cost": "Cost",
@@ -1150,6 +1152,7 @@
"waived": "Waived"
},
"deleteconfirm": "Are you sure you want to delete this job? This cannot be undone. ",
"deliverchecklist": "Deliver Checklist",
"difference": "Difference",
"documents": "Documents",
"documents-images": "Images",
@@ -1164,6 +1167,7 @@
"hrs_total": "Hours Total",
"importnote": "The job was initially imported on {{date}} at {{time}}.",
"inproduction": "In Production",
"intakechecklist": "Intake Checklist",
"job": "Job Details",
"jobcosting": "Job Costing",
"jobtotals": "Job Totals",
@@ -1739,6 +1743,7 @@
"jobs-active": "Active Jobs",
"jobs-admin": "Admin",
"jobs-all": "All Jobs",
"jobs-checklist": "Checklist",
"jobs-close": "Close Job",
"jobs-deliver": "Deliver Job",
"jobs-detail": "Job {{number}}",
@@ -1772,6 +1777,7 @@
"jobs": "Active Jobs | $t(titles.app)",
"jobs-admin": "Job {{ro_number}} - Admin | $t(titles.app)",
"jobs-all": "All Jobs | $t(titles.app)",
"jobs-checklist": "Job Checklist | $t(titles.app)",
"jobs-close": "Close Job {{number}} | $t(titles.app)",
"jobs-create": "Create a New Job | $t(titles.app)",
"jobs-deliver": "Deliver Job | $t(titles.app)",

View File

@@ -908,6 +908,7 @@
"schedule": "Programar",
"sendcsi": "",
"sync": "",
"viewchecklist": "",
"viewdetail": ""
},
"errors": {
@@ -1130,6 +1131,7 @@
"vehicle": "Vehículo"
},
"changeclass": "",
"checklistcompletedby": "",
"checklists": "",
"closeconfirm": "",
"cost": "",
@@ -1150,6 +1152,7 @@
"waived": ""
},
"deleteconfirm": "",
"deliverchecklist": "",
"difference": "",
"documents": "documentos",
"documents-images": "",
@@ -1164,6 +1167,7 @@
"hrs_total": "",
"importnote": "",
"inproduction": "",
"intakechecklist": "",
"job": "",
"jobcosting": "",
"jobtotals": "",
@@ -1739,6 +1743,7 @@
"jobs-active": "",
"jobs-admin": "",
"jobs-all": "",
"jobs-checklist": "",
"jobs-close": "",
"jobs-deliver": "",
"jobs-detail": "",
@@ -1772,6 +1777,7 @@
"jobs": "Todos los trabajos | $t(titles.app)",
"jobs-admin": "",
"jobs-all": "",
"jobs-checklist": "",
"jobs-close": "",
"jobs-create": "",
"jobs-deliver": "",

View File

@@ -908,6 +908,7 @@
"schedule": "Programme",
"sendcsi": "",
"sync": "",
"viewchecklist": "",
"viewdetail": ""
},
"errors": {
@@ -1130,6 +1131,7 @@
"vehicle": "Véhicule"
},
"changeclass": "",
"checklistcompletedby": "",
"checklists": "",
"closeconfirm": "",
"cost": "",
@@ -1150,6 +1152,7 @@
"waived": ""
},
"deleteconfirm": "",
"deliverchecklist": "",
"difference": "",
"documents": "Les documents",
"documents-images": "",
@@ -1164,6 +1167,7 @@
"hrs_total": "",
"importnote": "",
"inproduction": "",
"intakechecklist": "",
"job": "",
"jobcosting": "",
"jobtotals": "",
@@ -1739,6 +1743,7 @@
"jobs-active": "",
"jobs-admin": "",
"jobs-all": "",
"jobs-checklist": "",
"jobs-close": "",
"jobs-deliver": "",
"jobs-detail": "",
@@ -1772,6 +1777,7 @@
"jobs": "Tous les emplois | $t(titles.app)",
"jobs-admin": "",
"jobs-all": "",
"jobs-checklist": "",
"jobs-close": "",
"jobs-create": "",
"jobs-deliver": "",