Added job intake and delivery bypass.

This commit is contained in:
Patrick Fic
2024-03-12 08:44:35 -04:00
parent 1ae2133d23
commit 53a55dd1ef
8 changed files with 265 additions and 3 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project version="1.2" be_version="2.7.1">
<babeledit_project be_version="2.7.1" version="1.2">
<!--
BabelEdit project file
@@ -1789,6 +1789,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobdelivery</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>jobfieldchanged</name>
<definition_loaded>false</definition_loaded>
@@ -1852,6 +1873,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobintake</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>jobinvoiced</name>
<definition_loaded>false</definition_loaded>

View File

@@ -29,6 +29,7 @@ import FormDateTimePickerComponent from "../form-date-time-picker/form-date-time
import dayjs from "../../utils/day";
import {useSplitTreatments} from "@splitsoftware/splitio-react";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import JobsDetailHeaderActionsToggleProduction from "./jobs-detail-header-actions.toggle-production";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -664,7 +665,14 @@ export function JobsDetailHeaderActions({
label: <Link to={`/manage/jobs/${job.id}/checklist`}>
{t("jobs.actions.viewchecklist")}
</Link>
},], rome: "USE_IMEX", promanager:[]}),
},], rome: "USE_IMEX", promanager:[
{
key:'toggleproduction',
disabled: !job.converted || jobRO,
label: <JobsDetailHeaderActionsToggleProduction job={job} refetch={refetch} />
}
]}),
...(InstanceRenderManager({
imex: true,
rome: "USE_IMEX",
@@ -808,7 +816,7 @@ export function JobsDetailHeaderActions({
}
]
},
... InstanceRenderManager({
...InstanceRenderManager({
imex: true,
rome: true,
promanager: HasFeatureAccess({ featureName: 'bills', bodyshop }),

View File

@@ -0,0 +1,187 @@
import { useMutation } from '@apollo/client';
import { Button, Form, notification, Popover, Space } from 'antd';
import dayjs from 'dayjs';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { JOB_PRODUCTION_TOGGLE } 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';
import { DateTimeFormatterFunction } from '../../utils/DateFormatter';
import FormDateTimePickerComponent from '../form-date-time-picker/form-date-time-picker.component';
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser,
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation })),
});
export function JobsDetailHeaderActionsToggleProduction({
bodyshop,
job,
jobRO,
insertAuditTrail,
}) {
const [scenario, setScenario] = useState(false);
const [loading, setLoading] = useState(false);
const [mutationUpdateJob] = useMutation(JOB_PRODUCTION_TOGGLE);
const { t } = useTranslation();
const [form] = Form.useForm();
useEffect(() => {
//Figure out what scenario were in, populate accodingly
if (job && bodyshop) {
if (bodyshop.md_ro_statuses.pre_production_statuses.includes(job.status)) {
setScenario('pre');
} else if (bodyshop.md_ro_statuses.production_statuses.includes(job.status)) {
setScenario('prod');
} else {
setScenario('post');
}
}
}, [job, setScenario, bodyshop]);
const handleConvert = async (values) => {
setLoading(true);
const res = await mutationUpdateJob({
variables: {
jobId: job.id,
job: {
...values,
status:
scenario === 'pre'
? bodyshop.md_ro_statuses.default_arrived
: bodyshop.md_ro_statuses.default_delivered,
inproduction: scenario === 'pre' ? true : false,
},
},
});
if (!res.errors) {
notification['success']({
message: t('jobs.successes.converted'),
});
insertAuditTrail({
jobid: job.id,
operation:
scenario === 'pre'
? AuditTrailMapping.jobintake(
res.data.update_jobs.returning[0].status,
DateTimeFormatterFunction(values.scheduled_completion)
)
: AuditTrailMapping.jobdelivery(
res.data.update_jobs.returning[0].status,
DateTimeFormatterFunction(values.actual_completion)
),
});
}
setLoading(false);
};
const popMenu = (
<div onClick={(e) => e.stopPropagation()}>
<Form
layout="vertical"
form={form}
onFinish={handleConvert}
initialValues={{
actual_in: dayjs(),
scheduled_completion: job.scheduled_completion,
actual_completion: job.actual_completion,
scheduled_deliver: job.scheduled_deliver,
actual_delivery: job.actual_delivery,
}}
>
{scenario === 'pre' && (
<>
<Form.Item
name={['actual_in']}
label={t('jobs.fields.actual_in')}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
<Form.Item
name={['scheduled_completion']}
label={t('jobs.fields.scheduled_completion')}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
<Form.Item name={['scheduled_delivery']} label={t('jobs.fields.scheduled_delivery')}>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
</>
)}
{scenario === 'prod' && (
<>
<Form.Item
name={['actual_completion']}
label={t('jobs.fields.actual_completion')}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
<Form.Item name={['actual_delivery']} label={t('jobs.fields.actual_delivery')}>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
</>
)}
<Space wrap>
<Button type="primary" onClick={() => form.submit()} loading={loading}>
{t('general.actions.save')}
</Button>
<Button
disabled={scenario === 'post'}
onClick={() => {
// setOpen(false);
}}
>
{t('general.actions.close')}
</Button>
</Space>
</Form>
</div>
);
return (
<Popover //open={open}
content={popMenu}
onClick={(e) => e.stopPropagation()}
getPopupContainer={(trigger) => trigger.parentNode}
trigger="click"
>
{scenario === 'pre' && t('jobs.actions.intake')}
{scenario === 'prod' && t('jobs.actions.deliver')}
</Popover>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobsDetailHeaderActionsToggleProduction);

View File

@@ -1201,6 +1201,21 @@ export const UPDATE_JOB = gql`
}
}
`;
export const JOB_PRODUCTION_TOGGLE = gql`
mutation UPDATE_JOB($jobId: uuid!, $job: jobs_set_input!) {
update_jobs(where: { id: { _eq: $jobId } }, _set: $job) {
returning {
id
status
inproduction
actual_completion
scheduled_delivery
actual_delivery
scheduled_completion
}
}
}
`;
export const UPDATE_JOB_ASSIGNMENTS = gql`
mutation UPDATE_JOB_ASSIGNMENTS($jobId: uuid!, $job: jobs_set_input!) {

View File

@@ -116,9 +116,11 @@
"jobassignmentremoved": "Employee assignment removed for {{operation}}",
"jobchecklist": "Checklist type \"{{type}}\" completed. In production set to {{inproduction}}. Status set to {{status}}.",
"jobconverted": "Job converted and assigned number {{ro_number}}.",
"jobdelivery": "Job intake completed. Status set to {{status}}. Actual completion is {{actual_completion}}.",
"jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.",
"jobimported": "Job imported.",
"jobinproductionchange": "Job production status set to {{inproduction}}",
"jobintake": "Job intake completed. Status set to {{status}}. Scheduled completion is {{scheduled_completion}}.",
"jobinvoiced": "Job has been invoiced.",
"jobioucreated": "IOU Created.",
"jobmodifylbradj": "Labor adjustments modified {{mod_lbr_ty}} / {{hours}}.",

View File

@@ -116,9 +116,11 @@
"jobassignmentremoved": "",
"jobchecklist": "",
"jobconverted": "",
"jobdelivery": "",
"jobfieldchanged": "",
"jobimported": "",
"jobinproductionchange": "",
"jobintake": "",
"jobinvoiced": "",
"jobioucreated": "",
"jobmodifylbradj": "",

View File

@@ -116,9 +116,11 @@
"jobassignmentremoved": "",
"jobchecklist": "",
"jobconverted": "",
"jobdelivery": "",
"jobfieldchanged": "",
"jobimported": "",
"jobinproductionchange": "",
"jobintake": "",
"jobinvoiced": "",
"jobioucreated": "",
"jobmodifylbradj": "",

View File

@@ -26,6 +26,10 @@ const AuditTrailMapping = {
i18n.t("audit_trail.messages.jobchecklist", {type, inproduction, status}),
jobconverted: (ro_number) =>
i18n.t("audit_trail.messages.jobconverted", {ro_number}),
jobintake: (status, email, scheduled_completion) =>
i18n.t("audit_trail.messages.jobintake", {status, email,scheduled_completion}),
jobdelivery: (status, email, actual_completion) =>
i18n.t("audit_trail.messages.jobdelivery", {status, email,actual_completion}),
jobfieldchange: (field, value) =>
i18n.t("audit_trail.messages.jobfieldchanged", {field, value}),
jobimported: () => i18n.t("audit_trail.messages.jobimported"),