236 lines
7.1 KiB
JavaScript
236 lines
7.1 KiB
JavaScript
import moment from "moment";
|
|
import { all, call, put, select, takeLatest } from "redux-saga/effects";
|
|
import { QUERY_SCHEDULE_LOAD_DATA } from "../../graphql/appointments.queries";
|
|
import { INSERT_AUDIT_TRAIL } from "../../graphql/audit_trail.queries";
|
|
import client from "../../utils/GraphQLClient";
|
|
import { CalculateLoad, CheckJobBucket } from "../../utils/SSSUtils";
|
|
import {
|
|
scheduleLoadFailure,
|
|
scheduleLoadSuccess,
|
|
setProblemJobs,
|
|
} from "./application.actions";
|
|
import ApplicationActionTypes from "./application.types";
|
|
|
|
export function* onCalculateScheduleLoad() {
|
|
yield takeLatest(
|
|
ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD,
|
|
calculateScheduleLoad
|
|
);
|
|
}
|
|
export function* calculateScheduleLoad({ payload: end }) {
|
|
//REMINDER: Moment.js is not immutable. Today WILL change when adjusted.
|
|
const today = moment().startOf("day");
|
|
const state = yield select();
|
|
const buckets = state.user.bodyshop.ssbuckets;
|
|
|
|
try {
|
|
const result = yield client.query({
|
|
query: QUERY_SCHEDULE_LOAD_DATA,
|
|
variables: {
|
|
start: today,
|
|
end: end,
|
|
},
|
|
});
|
|
const { prodJobs, arrJobs, compJobs } = result.data;
|
|
|
|
const load = {
|
|
productionTotal: {},
|
|
productionHours: 0,
|
|
};
|
|
|
|
//Set the current load.
|
|
buckets.forEach((bucket) => {
|
|
load.productionTotal[bucket.id] = { count: 0, label: bucket.label };
|
|
});
|
|
|
|
prodJobs.forEach((item) => {
|
|
//Add all of the jobs currently in production to the buckets so that we have a starting point.
|
|
const bucketId = CheckJobBucket(buckets, item);
|
|
load.productionHours =
|
|
load.productionHours +
|
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
|
if (bucketId) {
|
|
load.productionTotal[bucketId].count =
|
|
load.productionTotal[bucketId].count + 1;
|
|
} else {
|
|
console.log("Uh oh, this job doesn't fit in a bucket!", item);
|
|
}
|
|
});
|
|
|
|
arrJobs.forEach((item) => {
|
|
if (!item.scheduled_in)
|
|
console.log("JOB HAS NO SCHEDULED IN DATE.", item);
|
|
const itemDate = moment(item.scheduled_in).format("yyyy-MM-DD");
|
|
if (!!load[itemDate]) {
|
|
load[itemDate].hoursIn =
|
|
(load[itemDate].hoursIn || 0) +
|
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
|
load[itemDate].jobsIn.push(item);
|
|
} else {
|
|
load[itemDate] = {
|
|
jobsIn: [item],
|
|
jobsOut: [],
|
|
hoursIn:
|
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
|
item.larhrs.aggregate.sum.mod_lb_hrs,
|
|
};
|
|
}
|
|
});
|
|
|
|
let problemJobs = [];
|
|
compJobs.forEach((item) => {
|
|
if (!(item.actual_completion || item.scheduled_completion))
|
|
console.log("JOB HAS NO COMPLETION DATE.", item);
|
|
|
|
const inProdJobs = prodJobs.find((p) => p.id === item.id);
|
|
const inArrJobs = arrJobs.find((p) => p.id === item.id);
|
|
|
|
if (!(inProdJobs || inArrJobs)) {
|
|
//Job isn't found in production or coming in.
|
|
//is it going today or scheduled to go today?
|
|
if (
|
|
moment(item.actual_completion || item.scheduled_completion).isSame(
|
|
moment(),
|
|
"day"
|
|
)
|
|
) {
|
|
console.log("Job is going today anyways, ignore it.", item);
|
|
return;
|
|
}
|
|
|
|
if (
|
|
moment(item.actual_completion || item.scheduled_completion).isBefore(
|
|
moment(),
|
|
"day"
|
|
)
|
|
) {
|
|
console.log("Job should have already gone. Ignoring it.", item);
|
|
return;
|
|
}
|
|
|
|
problemJobs.push({
|
|
...item,
|
|
code: "Job is scheduled for completion, but it is not marked in production nor is it an arriving job in this period. Check the scheduled in and completion dates",
|
|
});
|
|
return;
|
|
}
|
|
|
|
const itemDate = moment(
|
|
item.actual_completion || item.scheduled_completion
|
|
).format("yyyy-MM-DD");
|
|
if (!!load[itemDate]) {
|
|
load[itemDate].hoursOut =
|
|
(load[itemDate].hoursOut || 0) +
|
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
|
load[itemDate].jobsOut.push(item);
|
|
} else {
|
|
load[itemDate] = {
|
|
jobsOut: [item],
|
|
hoursOut:
|
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
|
item.larhrs.aggregate.sum.mod_lb_hrs,
|
|
};
|
|
}
|
|
});
|
|
|
|
//Propagate the expected load to each day.
|
|
const range = Math.round(moment.duration(end.diff(today)).asDays());
|
|
for (var day = 0; day < range; day++) {
|
|
const current = moment(today).add(day, "days").format("yyyy-MM-DD");
|
|
const prev = moment(today)
|
|
.add(day - 1, "days")
|
|
.format("yyyy-MM-DD");
|
|
if (!!!load[current]) {
|
|
load[current] = {};
|
|
}
|
|
if (day === 0) {
|
|
//Starting on day 1. The load is current.
|
|
load[current].expectedLoad = CalculateLoad(
|
|
load.productionTotal,
|
|
buckets,
|
|
load[current].jobsIn || [],
|
|
load[current].jobsOut || []
|
|
);
|
|
load[current].expectedJobCount =
|
|
prodJobs.length +
|
|
(load[current].jobsIn || []).length -
|
|
(load[current].jobsOut || []).length;
|
|
load[current].expectedHours =
|
|
load.productionHours +
|
|
(load[current].hoursIn || 0) -
|
|
(load[current].hoursOut || 0);
|
|
} else {
|
|
load[current].expectedLoad = CalculateLoad(
|
|
load[prev].expectedLoad,
|
|
buckets,
|
|
load[current].jobsIn || [],
|
|
load[current].jobsOut || []
|
|
);
|
|
load[current].expectedJobCount =
|
|
load[prev].expectedJobCount +
|
|
(load[current].jobsIn || []).length -
|
|
(load[current].jobsOut || []).length;
|
|
load[current].expectedHours =
|
|
load[prev].expectedHours +
|
|
(load[current].hoursIn || 0) -
|
|
(load[current].hoursOut || 0);
|
|
}
|
|
}
|
|
|
|
yield put(setProblemJobs(problemJobs));
|
|
yield put(scheduleLoadSuccess(load));
|
|
} catch (error) {
|
|
yield put(scheduleLoadFailure(error));
|
|
}
|
|
}
|
|
|
|
export function* onInsertAuditTrail() {
|
|
yield takeLatest(
|
|
ApplicationActionTypes.INSERT_AUDIT_TRAIL,
|
|
insertAuditTrailSaga
|
|
);
|
|
}
|
|
|
|
export function* insertAuditTrailSaga({
|
|
payload: { jobid, billid, operation },
|
|
}) {
|
|
const state = yield select();
|
|
const bodyshop = state.user.bodyshop;
|
|
const currentUser = state.user.currentUser;
|
|
|
|
const variables = {
|
|
auditObj: {
|
|
bodyshopid: bodyshop.id,
|
|
jobid,
|
|
billid,
|
|
operation,
|
|
useremail: currentUser.email,
|
|
},
|
|
};
|
|
yield client.mutate({
|
|
mutation: INSERT_AUDIT_TRAIL,
|
|
variables,
|
|
update(cache, { data }) {
|
|
cache.modify({
|
|
fields: {
|
|
audit_trail(existingAuditTrail, { readField }) {
|
|
const newAuditTrail = cache.writeQuery({
|
|
data: data.insert_audit_trail_one,
|
|
query: INSERT_AUDIT_TRAIL,
|
|
variables,
|
|
});
|
|
return [...existingAuditTrail, newAuditTrail];
|
|
},
|
|
},
|
|
});
|
|
},
|
|
});
|
|
}
|
|
|
|
export function* applicationSagas() {
|
|
yield all([call(onCalculateScheduleLoad), call(onInsertAuditTrail)]);
|
|
}
|