Files
bodyshop/server/scheduling/scheduling-job.js
2021-02-01 11:04:33 -08:00

162 lines
5.0 KiB
JavaScript

const GraphQLClient = require("graphql-request").GraphQLClient;
const path = require("path");
const queries = require("../graphql-client/queries");
const Dinero = require("dinero.js");
const moment = require("moment");
require("dotenv").config({
path: path.resolve(
process.cwd(),
`.env.${process.env.NODE_ENV || "development"}`
),
});
exports.job = async (req, res) => {
try {
const BearerToken = req.headers.authorization;
const { jobId } = req.body;
console.log("exports.job -> jobId", jobId);
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
headers: {
Authorization: BearerToken,
},
});
const result = await client
.setHeaders({ Authorization: BearerToken })
.request(queries.QUERY_UPCOMING_APPOINTMENTS, {
now: new Date(),
jobId: jobId,
});
const { appointments, jobs } = result;
const { ssbuckets, workingdays } = result.jobs_by_pk.bodyshop;
const jobHrs = result.jobs_by_pk.jobhrs.aggregate.sum.mod_lb_hrs;
const JobBucket = ssbuckets.filter(
(bucket) =>
bucket.gte <= jobHrs && (!!bucket.lt ? bucket.lt > jobHrs : true)
)[0];
const bucketMatrix = {};
const yesterday = moment().subtract(1, "day");
//Get latest date + add 5 days to allow for back end adding..
const totalMatrixDays = moment
.max([
...appointments.map((a) => moment(a.start)),
...jobs
.map((p) => moment(p.scheduled_completion))
.filter((p) => p.isValid() && p.isAfter(yesterday)),
])
.add("5", "days")
.diff(moment(), "days");
//Initialize the bucket matrix
for (i = 0; i < totalMatrixDays; i++) {
const theDate = moment().add(i, "days").format("yyyy-MM-DD");
//Only need to create a matrix for jobs of the same bucket.
bucketMatrix[theDate] = { in: 0, out: 0 };
// ssbuckets.forEach((bucket) => {
// bucketMatrix[theDate] = {
// ...bucketMatrix[theDate],
// [bucket.id]: { in: 0, out: 0 },
// };
// });
}
//Populate the jobs scheduled to come in.
appointments.forEach((appointment) => {
if (!appointment.block) {
const jobHrs =
appointment.job.joblines_aggregate.aggregate.sum.mod_lb_hrs;
//Is the job in the same bucket?
const appointmentBucket = ssbuckets.filter(
(bucket) =>
bucket.gte <= jobHrs && (!!bucket.lt ? bucket.lt > jobHrs : true)
)[0];
if (appointmentBucket.id === JobBucket.id) {
//Theyre the same classification. Add it to the matrix.
const appDate = moment(appointment.start).format("yyyy-MM-DD");
bucketMatrix[appDate] = {
...bucketMatrix[appDate],
in: bucketMatrix[appDate].in + 1,
};
}
} else {
//remove the date from the possible list.
const appDate = moment(appointment.start).format("yyyy-MM-DD");
delete bucketMatrix[appDate];
}
});
//Populate the jobs that are leaving today.
const todayIsoString = moment().format("yyyy-MM-DD");
jobs.forEach((pjob) => {
const jobHrs =
pjob.larhrs.aggregate.sum.mod_lb_hrs +
pjob.labhrs.aggregate.sum.mod_lb_hrs;
//Is the job in the same bucket?
const pjobBucket = ssbuckets.filter(
(bucket) =>
bucket.gte <= jobHrs && (!!bucket.lt ? bucket.lt > jobHrs : true)
)[0];
if (pjobBucket.id === JobBucket.id) {
//Theyre the same classification. Add it to the matrix.
const compDate = moment(pjob.scheduled_completion);
//Is the schedule completion behind today? If so, use today as it.
let dateToUse;
dateToUse = compDate.isValid()
? moment().diff(compDate, "days") < 0
? compDate.format("yyyy-MM-DD")
: todayIsoString
: todayIsoString;
bucketMatrix[dateToUse] = {
...bucketMatrix[dateToUse],
out: (bucketMatrix[dateToUse].out || 0) + 1,
};
}
});
//Propose the first 5 dates where we are below target.
const possibleDates = [];
const bucketMatrixKeys = Object.keys(bucketMatrix);
bucketMatrixKeys.forEach((bmkey) => {
const isShopOpen = workingdays[dayOfWeekMapper(moment(bmkey).day())];
if (
JobBucket.target > bucketMatrix[bmkey].in - bucketMatrix[bmkey].out &&
isShopOpen
)
possibleDates.push(new Date(bmkey).toISOString().substr(0, 10));
});
console.log("possibleDates", possibleDates, "bucketMatrix", bucketMatrix);
res.json(possibleDates);
} catch (error) {
console.log("error", error);
res.status(400).send(error);
}
};
const dayOfWeekMapper = (numberOfDay) => {
switch (numberOfDay) {
case 0:
return "sunday";
case 1:
return "monday";
case 2:
return "tuesday";
case 3:
return "wednesday";
case 4:
return "thursday";
case 5:
return "friday";
case 6:
return "saturday";
}
};