349 lines
10 KiB
JavaScript
349 lines
10 KiB
JavaScript
import {
|
|
useApolloClient,
|
|
useLazyQuery,
|
|
useMutation,
|
|
useQuery,
|
|
} from "@apollo/react-hooks";
|
|
import { notification } from "antd";
|
|
import Axios from "axios";
|
|
import Dinero from "dinero.js";
|
|
import gql from "graphql-tag";
|
|
import _ from "lodash";
|
|
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 { logImEXEvent } from "../../firebase/firebase.utils";
|
|
import {
|
|
DELETE_AVAILABLE_JOB,
|
|
QUERY_AVAILABLE_JOBS,
|
|
QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK,
|
|
} from "../../graphql/available-jobs.queries";
|
|
import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
|
|
import { SEARCH_VEHICLE_BY_VIN } from "../../graphql/vehicles.queries";
|
|
import {
|
|
selectBodyshop,
|
|
selectCurrentUser,
|
|
} from "../../redux/user/user.selectors";
|
|
import AlertComponent from "../alert/alert.component";
|
|
import JobsFindModalContainer from "../jobs-find-modal/jobs-find-modal.container";
|
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
|
import OwnerFindModalContainer from "../owner-find-modal/owner-find-modal.container";
|
|
import { GetSupplementDelta } from "./jobs-available-supplement.estlines.util";
|
|
import HeaderFields from "./jobs-available-supplement.headerfields";
|
|
import JobsAvailableTableComponent from "./jobs-available-table.component";
|
|
import moment from "moment";
|
|
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
|
|
const mapStateToProps = createStructuredSelector({
|
|
bodyshop: selectBodyshop,
|
|
currentUser: selectCurrentUser,
|
|
});
|
|
|
|
export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
|
const { loading, error, data, refetch } = useQuery(QUERY_AVAILABLE_JOBS, {
|
|
fetchPolicy: "network-only",
|
|
});
|
|
|
|
const history = useHistory();
|
|
const { t } = useTranslation();
|
|
|
|
const [ownerModalVisible, setOwnerModalVisible] = useState(false);
|
|
const [jobModalVisible, setJobModalVisible] = useState(false);
|
|
|
|
const [selectedJob, setSelectedJob] = useState(null);
|
|
const [selectedOwner, setSelectedOwner] = useState(null);
|
|
const [insertLoading, setInsertLoading] = useState(false);
|
|
|
|
const [insertNote] = useMutation(INSERT_NEW_NOTE);
|
|
const [deleteJob] = useMutation(DELETE_AVAILABLE_JOB);
|
|
const [updateJob] = useMutation(UPDATE_JOB);
|
|
|
|
const [insertNewJob] = useMutation(INSERT_NEW_JOB);
|
|
const client = useApolloClient();
|
|
|
|
const estDataLazyLoad = useLazyQuery(QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK);
|
|
const [loadEstData, estData] = estDataLazyLoad;
|
|
|
|
const importOptionsState = useState({ overrideHeaders: false });
|
|
const importOptions = importOptionsState[0];
|
|
const modalSearchState = useState("");
|
|
|
|
const onOwnerFindModalOk = async () => {
|
|
logImEXEvent("job_import_new");
|
|
|
|
setOwnerModalVisible(false);
|
|
setInsertLoading(true);
|
|
|
|
if (
|
|
!(
|
|
estData.data &&
|
|
estData.data.available_jobs_by_pk &&
|
|
estData.data.available_jobs_by_pk.est_data
|
|
)
|
|
) {
|
|
//We don't have the right data. Error!
|
|
setInsertLoading(false);
|
|
notification["error"]({
|
|
message: t("jobs.errors.creating", { error: "No job data present." }),
|
|
});
|
|
return;
|
|
}
|
|
|
|
const newTotals = (
|
|
await Axios.post("/job/totals", {
|
|
job: {
|
|
...estData.data.available_jobs_by_pk.est_data,
|
|
joblines: estData.data.available_jobs_by_pk.est_data.joblines.data,
|
|
},
|
|
})
|
|
).data;
|
|
|
|
let existingVehicles;
|
|
if (estData.data.available_jobs_by_pk.est_data.vehicle) {
|
|
//There's vehicle data, need to double check the VIN.
|
|
existingVehicles = await client.query({
|
|
query: SEARCH_VEHICLE_BY_VIN,
|
|
variables: {
|
|
vin: estData.data.available_jobs_by_pk.est_data.vehicle.data.v_vin,
|
|
},
|
|
});
|
|
}
|
|
|
|
const newJob = {
|
|
...estData.data.available_jobs_by_pk.est_data,
|
|
clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
|
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
|
|
job_totals: newTotals,
|
|
date_open: moment(),
|
|
notes: {
|
|
data: {
|
|
created_by: currentUser.email,
|
|
text: t("jobs.labels.importnote", {
|
|
date: moment().format("MM/DD/yyy"),
|
|
time: moment().format("hh:mm a"),
|
|
}),
|
|
},
|
|
},
|
|
queued_for_parts: true,
|
|
...(existingVehicles && existingVehicles.data.vehicles.length > 0
|
|
? { vehicleid: existingVehicles.data.vehicles[0].id, vehicle: null }
|
|
: {}),
|
|
};
|
|
|
|
insertNewJob({
|
|
variables: {
|
|
job: selectedOwner
|
|
? Object.assign(
|
|
{},
|
|
newJob,
|
|
{ owner: null },
|
|
{ ownerid: selectedOwner }
|
|
)
|
|
: newJob,
|
|
},
|
|
})
|
|
.then((r) => {
|
|
notification["success"]({
|
|
message: t("jobs.successes.created"),
|
|
onClick: () => {
|
|
history.push(`/manage/jobs/${r.data.insert_jobs.returning[0].id}`);
|
|
},
|
|
});
|
|
//Job has been inserted. Clean up the available jobs record.
|
|
|
|
deleteJob({
|
|
variables: { id: estData.data.available_jobs_by_pk.id },
|
|
}).then((r) => {
|
|
refetch();
|
|
setInsertLoading(false);
|
|
});
|
|
})
|
|
.catch((r) => {
|
|
//error while inserting
|
|
notification["error"]({
|
|
message: t("jobs.errors.creating", { error: r.message }),
|
|
});
|
|
refetch();
|
|
setInsertLoading(false);
|
|
});
|
|
};
|
|
|
|
const onJobFindModalOk = async () => {
|
|
logImEXEvent("job_import_supplement");
|
|
|
|
setJobModalVisible(false);
|
|
setInsertLoading(true);
|
|
|
|
if (
|
|
!(
|
|
estData.data &&
|
|
estData.data.available_jobs_by_pk &&
|
|
estData.data.available_jobs_by_pk.est_data
|
|
)
|
|
) {
|
|
//We don't have the right data. Error!
|
|
setInsertLoading(false);
|
|
notification["error"]({
|
|
message: t("jobs.errors.creating", { error: "No job data present." }),
|
|
});
|
|
} else {
|
|
//create upsert job
|
|
let supp = _.cloneDeep(estData.data.available_jobs_by_pk.est_data);
|
|
|
|
delete supp.owner;
|
|
delete supp.vehicle;
|
|
if (importOptions.overrideHeaders) {
|
|
HeaderFields.forEach((item) => delete supp[item]);
|
|
}
|
|
|
|
const newTotals = (
|
|
await Axios.post("/job/totals", {
|
|
job: {
|
|
...estData.data.available_jobs_by_pk.est_data,
|
|
joblines: estData.data.available_jobs_by_pk.est_data.joblines.data,
|
|
},
|
|
})
|
|
).data;
|
|
|
|
let suppDelta = await GetSupplementDelta(
|
|
client,
|
|
selectedJob,
|
|
estData.data.available_jobs_by_pk.est_data.joblines.data
|
|
);
|
|
|
|
delete supp.joblines;
|
|
await client.mutate({
|
|
mutation: gql`
|
|
${suppDelta}
|
|
`,
|
|
});
|
|
updateJob({
|
|
variables: {
|
|
jobId: selectedJob,
|
|
job: {
|
|
...supp,
|
|
clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
|
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat(
|
|
"0.00"
|
|
),
|
|
job_totals: newTotals,
|
|
queued_for_parts: true,
|
|
},
|
|
},
|
|
})
|
|
.then((r) => {
|
|
notification["success"]({
|
|
message: t("jobs.successes.supplemented"),
|
|
onClick: () => {
|
|
history.push(
|
|
`/manage/jobs/${r.data.update_jobs.returning[0].id}`
|
|
);
|
|
},
|
|
});
|
|
//Job has been inserted. Clean up the available jobs record.
|
|
|
|
deleteJob({
|
|
variables: { id: estData.data.available_jobs_by_pk.id },
|
|
}).then((r) => {
|
|
refetch();
|
|
setInsertLoading(false);
|
|
});
|
|
})
|
|
.catch((r) => {
|
|
//error while inserting
|
|
notification["error"]({
|
|
message: t("jobs.errors.creating", { error: r.message }),
|
|
});
|
|
refetch();
|
|
setInsertLoading(false);
|
|
});
|
|
|
|
await insertNote({
|
|
variables: {
|
|
noteInput: [
|
|
{
|
|
jobid: selectedJob,
|
|
created_by: currentUser.email,
|
|
text: t("jobs.labels.supplementnote", {
|
|
date: moment().format("MM/DD/yyy"),
|
|
time: moment().format("hh:mm a"),
|
|
}),
|
|
},
|
|
],
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
const owner =
|
|
estData.data &&
|
|
estData.data.available_jobs_by_pk &&
|
|
estData.data.available_jobs_by_pk.est_data &&
|
|
estData.data.available_jobs_by_pk.est_data.owner &&
|
|
estData.data.available_jobs_by_pk.est_data.owner.data &&
|
|
!estData.data.available_jobs_by_pk.issupplement
|
|
? estData.data.available_jobs_by_pk.est_data.owner.data
|
|
: null;
|
|
|
|
const onOwnerModalCancel = () => {
|
|
setOwnerModalVisible(false);
|
|
setSelectedOwner(null);
|
|
};
|
|
|
|
const onJobModalCancel = () => {
|
|
setJobModalVisible(false);
|
|
modalSearchState[1]("");
|
|
setSelectedJob(null);
|
|
};
|
|
|
|
const addJobAsNew = (record) => {
|
|
loadEstData({ variables: { id: record.id } });
|
|
setOwnerModalVisible(true);
|
|
};
|
|
|
|
const addJobAsSupp = (record) => {
|
|
loadEstData({ variables: { id: record.id } });
|
|
modalSearchState[1](record.clm_no);
|
|
setJobModalVisible(true);
|
|
};
|
|
|
|
if (error) return <AlertComponent type="error" message={error.message} />;
|
|
return (
|
|
<LoadingSpinner
|
|
loading={insertLoading}
|
|
message={t("jobs.labels.creating_new_job")}
|
|
>
|
|
<OwnerFindModalContainer
|
|
loading={estData.loading}
|
|
error={estData.error}
|
|
owner={owner}
|
|
selectedOwner={selectedOwner}
|
|
setSelectedOwner={setSelectedOwner}
|
|
visible={ownerModalVisible}
|
|
onOk={onOwnerFindModalOk}
|
|
onCancel={onOwnerModalCancel}
|
|
/>
|
|
<JobsFindModalContainer
|
|
loading={estData.loading}
|
|
error={estData.error}
|
|
selectedJob={selectedJob}
|
|
setSelectedJob={setSelectedJob}
|
|
importOptionsState={importOptionsState}
|
|
visible={jobModalVisible}
|
|
onOk={onJobFindModalOk}
|
|
onCancel={onJobModalCancel}
|
|
modalSearchState={modalSearchState}
|
|
/>
|
|
<JobsAvailableTableComponent
|
|
loading={loading}
|
|
data={data}
|
|
refetch={refetch}
|
|
addJobAsNew={addJobAsNew}
|
|
addJobAsSupp={addJobAsSupp}
|
|
/>
|
|
</LoadingSpinner>
|
|
);
|
|
}
|
|
export default connect(mapStateToProps, null)(JobsAvailableContainer);
|