- Progress commit

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-03-28 13:03:09 -04:00
876 changed files with 111723 additions and 125595 deletions

View File

@@ -1,47 +1,41 @@
import {notification} from "antd";
import { notification } from "antd";
import i18n from "i18next";
import {logImEXEvent} from "../../firebase/firebase.utils";
import {UPDATE_JOB} from "../../graphql/jobs.queries";
import {insertAuditTrail} from "../../redux/application/application.actions";
import {store} from "../../redux/store";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { store } from "../../redux/store";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
export default function AddToProduction(
apolloClient,
jobId,
completionCallback,
remove = false
) {
logImEXEvent("job_add_to_production");
export default function AddToProduction(apolloClient, jobId, completionCallback, remove = false) {
logImEXEvent("job_add_to_production");
//get a list of all fields on the job
apolloClient
.mutate({
mutation: UPDATE_JOB,
variables: {jobId: jobId, job: {inproduction: !remove}},
//get a list of all fields on the job
apolloClient
.mutate({
mutation: UPDATE_JOB,
variables: { jobId: jobId, job: { inproduction: !remove } }
})
.then((res) => {
notification["success"]({
message: i18n.t("jobs.successes.save")
});
store.dispatch(
insertAuditTrail({
jobid: jobId,
operation: AuditTrailMapping.jobinproductionchange(!remove),
type: "jobinproductionchange"
})
.then((res) => {
notification["success"]({
message: i18n.t("jobs.successes.save"),
});
store.dispatch(
insertAuditTrail({
jobid: jobId,
operation: AuditTrailMapping.jobinproductionchange(!remove),
type: "jobinproductionchange",
})
);
if (completionCallback) completionCallback();
);
if (completionCallback) completionCallback();
})
.catch((error) => {
notification["errors"]({
message: i18n.t("jobs.errors.saving", {
error: JSON.stringify(error)
})
.catch((error) => {
notification["errors"]({
message: i18n.t("jobs.errors.saving", {
error: JSON.stringify(error),
}),
});
});
//insert the new job. call the callback with the returned ID when done.
});
});
//insert the new job. call the callback with the returned ID when done.
}

View File

@@ -1,138 +1,124 @@
import Axios from "axios";
import _ from "lodash";
import {logImEXEvent} from "../../firebase/firebase.utils";
import {INSERT_NEW_JOB, QUERY_JOB_FOR_DUPE} from "../../graphql/jobs.queries";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_NEW_JOB, QUERY_JOB_FOR_DUPE } from "../../graphql/jobs.queries";
import dayjs from "../../utils/day";
import i18n from "i18next";
export default async function DuplicateJob(
apolloClient,
jobId,
config,
completionCallback,
keepJobLines = false
) {
logImEXEvent("job_duplicate");
export default async function DuplicateJob(apolloClient, jobId, config, completionCallback, keepJobLines = false) {
logImEXEvent("job_duplicate");
const {defaultOpenStatus} = config;
//get a list of all fields on the job
const res = await apolloClient.query({
query: QUERY_JOB_FOR_DUPE,
variables: {id: jobId},
});
const { defaultOpenStatus } = config;
//get a list of all fields on the job
const res = await apolloClient.query({
query: QUERY_JOB_FOR_DUPE,
variables: { id: jobId }
});
const {jobs_by_pk} = res.data;
const existingJob = _.cloneDeep(jobs_by_pk);
delete existingJob.__typename;
delete existingJob.id;
delete existingJob.createdat;
delete existingJob.updatedat;
delete existingJob.cieca_stl;
delete existingJob.cieca_ttl;
const { jobs_by_pk } = res.data;
const existingJob = _.cloneDeep(jobs_by_pk);
delete existingJob.__typename;
delete existingJob.id;
delete existingJob.createdat;
delete existingJob.updatedat;
delete existingJob.cieca_stl;
delete existingJob.cieca_ttl;
const newJob = {
...existingJob,
status: defaultOpenStatus,
};
const newJob = {
...existingJob,
status: defaultOpenStatus
};
const _tempLines = _.cloneDeep(existingJob.joblines);
_tempLines.forEach((line) => {
delete line.id;
delete line.__typename;
line.manual_line = true;
});
newJob.joblines = keepJobLines ? _tempLines : [];
const _tempLines = _.cloneDeep(existingJob.joblines);
_tempLines.forEach((line) => {
delete line.id;
delete line.__typename;
line.manual_line = true;
});
newJob.joblines = keepJobLines ? _tempLines : [];
delete newJob.joblines;
newJob.joblines = keepJobLines ? {data: _tempLines} : null;
delete newJob.joblines;
newJob.joblines = keepJobLines ? { data: _tempLines } : null;
const res2 = await apolloClient.mutate({
mutation: INSERT_NEW_JOB,
variables: {job: [newJob]},
});
await Axios.post("/job/totalsssu", {
id: res2.data.insert_jobs.returning[0].id,
});
const res2 = await apolloClient.mutate({
mutation: INSERT_NEW_JOB,
variables: { job: [newJob] }
});
await Axios.post("/job/totalsssu", {
id: res2.data.insert_jobs.returning[0].id
});
if (completionCallback)
completionCallback(res2.data.insert_jobs.returning[0].id);
if (completionCallback) completionCallback(res2.data.insert_jobs.returning[0].id);
//insert the new job. call the callback with the returned ID when done.
//insert the new job. call the callback with the returned ID when done.
return;
return;
}
export async function CreateIouForJob(
apolloClient,
jobId,
config,
jobLinesToKeep
) {
logImEXEvent("job_create_iou");
export async function CreateIouForJob(apolloClient, jobId, config, jobLinesToKeep) {
logImEXEvent("job_create_iou");
const {status} = config;
//get a list of all fields on the job
const res = await apolloClient.query({
query: QUERY_JOB_FOR_DUPE,
variables: {id: jobId},
});
const { status } = config;
//get a list of all fields on the job
const res = await apolloClient.query({
query: QUERY_JOB_FOR_DUPE,
variables: { id: jobId }
});
const {jobs_by_pk} = res.data;
const existingJob = _.cloneDeep(jobs_by_pk);
delete existingJob.__typename;
delete existingJob.id;
delete existingJob.createdat;
delete existingJob.updatedat;
delete existingJob.cieca_stl;
delete existingJob.cieca_ttl;
const { jobs_by_pk } = res.data;
const existingJob = _.cloneDeep(jobs_by_pk);
delete existingJob.__typename;
delete existingJob.id;
delete existingJob.createdat;
delete existingJob.updatedat;
delete existingJob.cieca_stl;
delete existingJob.cieca_ttl;
const newJob = {
...existingJob,
const newJob = {
...existingJob,
converted: true,
status: status,
iouparent: jobId,
date_open: dayjs(),
audit_trails: {
data: [
{
useremail: config.useremail,
bodyshopid: config.bodyshopid,
operation: i18n.t("audit_trail.messages.jobioucreated"),
},
],
},
};
converted: true,
status: status,
iouparent: jobId,
date_open: dayjs(),
audit_trails: {
data: [
{
useremail: config.useremail,
bodyshopid: config.bodyshopid,
operation: i18n.t("audit_trail.messages.jobioucreated")
}
]
}
};
const selectedJoblinesIds = jobLinesToKeep.map((l) => l.id);
const selectedJoblinesIds = jobLinesToKeep.map((l) => l.id);
const _tempLines = _.cloneDeep(existingJob.joblines).filter((l) =>
selectedJoblinesIds.includes(l.id)
);
_tempLines.forEach((line) => {
delete line.id;
delete line.__typename;
line.oem_partno = `${line.oem_partno ? `${line.oem_partno} - ` : ``}IOU $${
(line.act_price && line.act_price.toFixed(2)) || 0
}/${line.mod_lb_hrs || 0}hrs`;
line.act_price = 0;
line.mod_lb_hrs = 0;
line.manual_line = true;
});
const _tempLines = _.cloneDeep(existingJob.joblines).filter((l) => selectedJoblinesIds.includes(l.id));
_tempLines.forEach((line) => {
delete line.id;
delete line.__typename;
line.oem_partno = `${line.oem_partno ? `${line.oem_partno} - ` : ``}IOU $${
(line.act_price && line.act_price.toFixed(2)) || 0
}/${line.mod_lb_hrs || 0}hrs`;
line.act_price = 0;
line.mod_lb_hrs = 0;
line.manual_line = true;
});
delete newJob.joblines;
newJob.joblines = {data: _tempLines};
delete newJob.joblines;
newJob.joblines = { data: _tempLines };
const res2 = await apolloClient.mutate({
mutation: INSERT_NEW_JOB,
variables: {job: [newJob]},
});
const res2 = await apolloClient.mutate({
mutation: INSERT_NEW_JOB,
variables: { job: [newJob] }
});
Axios.post("/job/totalsssu", {
id: res2.data.insert_jobs.returning[0].id,
});
Axios.post("/job/totalsssu", {
id: res2.data.insert_jobs.returning[0].id
});
//insert the new job. call the callback with the returned ID when done.
//insert the new job. call the callback with the returned ID when done.
return res2.data.insert_jobs.returning[0].id;
return res2.data.insert_jobs.returning[0].id;
}

View File

@@ -1,33 +1,28 @@
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';
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,
jobRO: selectJobReadOnly
});
const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation })),
insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation }))
});
export function JobsDetailHeaderActionsToggleProduction({
bodyshop,
job,
jobRO,
insertAuditTrail,
}) {
export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO, insertAuditTrail }) {
const [scenario, setScenario] = useState(false);
const [loading, setLoading] = useState(false);
const [mutationUpdateJob] = useMutation(JOB_PRODUCTION_TOGGLE);
@@ -38,11 +33,11 @@ export function JobsDetailHeaderActionsToggleProduction({
//Figure out what scenario were in, populate accodingly
if (job && bodyshop) {
if (bodyshop.md_ro_statuses.pre_production_statuses.includes(job.status)) {
setScenario('pre');
setScenario("pre");
} else if (bodyshop.md_ro_statuses.production_statuses.includes(job.status)) {
setScenario('prod');
setScenario("prod");
} else {
setScenario('post');
setScenario("post");
}
}
}, [job, setScenario, bodyshop]);
@@ -55,23 +50,21 @@ export function JobsDetailHeaderActionsToggleProduction({
job: {
...values,
status:
scenario === 'pre'
? bodyshop.md_ro_statuses.default_arrived
: bodyshop.md_ro_statuses.default_delivered,
inproduction: scenario === 'pre' ? true : false,
},
},
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'),
notification["success"]({
message: t("jobs.successes.converted")
});
insertAuditTrail({
jobid: job.id,
operation:
scenario === 'pre'
scenario === "pre"
? AuditTrailMapping.jobintake(
res.data.update_jobs.returning[0].status,
DateTimeFormatterFunction(values.scheduled_completion)
@@ -79,7 +72,7 @@ export function JobsDetailHeaderActionsToggleProduction({
: AuditTrailMapping.jobdelivery(
res.data.update_jobs.returning[0].status,
DateTimeFormatterFunction(values.actual_completion)
),
)
});
}
setLoading(false);
@@ -96,56 +89,56 @@ export function JobsDetailHeaderActionsToggleProduction({
scheduled_completion: job.scheduled_completion,
actual_completion: job.actual_completion,
scheduled_deliver: job.scheduled_deliver,
actual_delivery: job.actual_delivery,
actual_delivery: job.actual_delivery
}}
>
{scenario === 'pre' && (
{scenario === "pre" && (
<>
<Form.Item
name={['actual_in']}
label={t('jobs.fields.actual_in')}
name={["actual_in"]}
label={t("jobs.fields.actual_in")}
rules={[
{
required: true,
required: true
//message: t("general.validation.required"),
},
}
]}
>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
<Form.Item
name={['scheduled_completion']}
label={t('jobs.fields.scheduled_completion')}
name={["scheduled_completion"]}
label={t("jobs.fields.scheduled_completion")}
rules={[
{
required: true,
required: true
//message: t("general.validation.required"),
},
}
]}
>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
<Form.Item name={['scheduled_delivery']} label={t('jobs.fields.scheduled_delivery')}>
<Form.Item name={["scheduled_delivery"]} label={t("jobs.fields.scheduled_delivery")}>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
</>
)}
{scenario === 'prod' && (
{scenario === "prod" && (
<>
<Form.Item
name={['actual_completion']}
label={t('jobs.fields.actual_completion')}
name={["actual_completion"]}
label={t("jobs.fields.actual_completion")}
rules={[
{
required: true,
required: true
//message: t("general.validation.required"),
},
}
]}
>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
<Form.Item name={['actual_delivery']} label={t('jobs.fields.actual_delivery')}>
<Form.Item name={["actual_delivery"]} label={t("jobs.fields.actual_delivery")}>
<FormDateTimePickerComponent disabled={jobRO} />
</Form.Item>
</>
@@ -153,15 +146,15 @@ export function JobsDetailHeaderActionsToggleProduction({
<Space wrap>
<Button type="primary" onClick={() => form.submit()} loading={loading}>
{t('general.actions.save')}
{t("general.actions.save")}
</Button>
<Button
disabled={scenario === 'post'}
disabled={scenario === "post"}
onClick={() => {
// setOpen(false);
// setOpen(false);
}}
>
{t('general.actions.close')}
{t("general.actions.close")}
</Button>
</Space>
</Form>
@@ -175,13 +168,10 @@ export function JobsDetailHeaderActionsToggleProduction({
getPopupContainer={(trigger) => trigger.parentNode}
trigger="click"
>
{scenario === 'pre' && t('jobs.actions.intake')}
{scenario === 'prod' && t('jobs.actions.deliver')}
{scenario === "pre" && t("jobs.actions.intake")}
{scenario === "prod" && t("jobs.actions.deliver")}
</Popover>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobsDetailHeaderActionsToggleProduction);
export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailHeaderActionsToggleProduction);