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"; } };