IO-2162 Updated smart schedule graph logic.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<babeledit_project be_version="2.7.1" version="1.2">
|
||||
<babeledit_project version="1.2" be_version="2.7.1">
|
||||
<!--
|
||||
|
||||
BabelEdit project file
|
||||
|
||||
@@ -22,10 +22,6 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
});
|
||||
|
||||
export function ScheduleCalendarHeaderGraph({ bodyshop, loadData }) {
|
||||
console.log(
|
||||
"🚀 ~ file: schedule-calendar-header-graph.component.js:23 ~ ScheduleCalendarHeaderGraph ~ loadData",
|
||||
loadData
|
||||
);
|
||||
const { ssbuckets } = bodyshop;
|
||||
const { t } = useTranslation();
|
||||
const data = useMemo(() => {
|
||||
|
||||
@@ -66,8 +66,8 @@ export function ScheduleCalendarHeaderComponent({
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<table>
|
||||
<tbody>
|
||||
{loadData && loadData.jobsOut ? (
|
||||
loadData.jobsOut.map((j) => (
|
||||
{loadData && loadData.allJobsOut ? (
|
||||
loadData.allJobsOut.map((j) => (
|
||||
<tr key={j.id}>
|
||||
<td>
|
||||
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
||||
@@ -102,11 +102,12 @@ export function ScheduleCalendarHeaderComponent({
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<table>
|
||||
<tbody>
|
||||
{loadData && loadData.jobsIn ? (
|
||||
loadData.jobsIn.map((j) => (
|
||||
{loadData && loadData.allJobsIn ? (
|
||||
loadData.allJobsIn.map((j) => (
|
||||
<tr key={j.id}>
|
||||
<td>
|
||||
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
||||
{j.status}
|
||||
</td>
|
||||
<td>
|
||||
<OwnerNameDisplay ownerObject={j} />
|
||||
@@ -142,7 +143,7 @@ export function ScheduleCalendarHeaderComponent({
|
||||
title={t("appointments.labels.arrivingjobs")}
|
||||
>
|
||||
<Icon component={MdFileDownload} style={{ color: "green" }} />
|
||||
{(loadData.hoursIn || 0) && loadData.hoursIn.toFixed(2)}
|
||||
{(loadData.allHoursIn || 0) && loadData.allHoursIn.toFixed(2)}
|
||||
</Popover>
|
||||
<Popover
|
||||
placement={"bottom"}
|
||||
@@ -151,7 +152,7 @@ export function ScheduleCalendarHeaderComponent({
|
||||
title={t("appointments.labels.completingjobs")}
|
||||
>
|
||||
<Icon component={MdFileUpload} style={{ color: "red" }} />
|
||||
{(loadData.hoursOut || 0) && loadData.hoursOut.toFixed(2)}
|
||||
{(loadData.allHoursOut || 0) && loadData.allHoursOut.toFixed(2)}
|
||||
</Popover>
|
||||
<ScheduleCalendarHeaderGraph loadData={loadData} />
|
||||
</div>
|
||||
|
||||
@@ -294,6 +294,12 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
|
||||
where: { inproduction: { _eq: true }, suspended: { _eq: false } }
|
||||
) {
|
||||
id
|
||||
actual_in
|
||||
scheduled_in
|
||||
actual_completion
|
||||
scheduled_completion
|
||||
inproduction
|
||||
ro_number
|
||||
labhrs: joblines_aggregate(
|
||||
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
||||
) {
|
||||
@@ -327,12 +333,15 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
|
||||
}
|
||||
) {
|
||||
id
|
||||
status
|
||||
ro_number
|
||||
scheduled_completion
|
||||
actual_completion
|
||||
scheduled_in
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
inproduction
|
||||
labhrs: joblines_aggregate(
|
||||
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
||||
) {
|
||||
@@ -360,11 +369,16 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
|
||||
) {
|
||||
id
|
||||
scheduled_in
|
||||
actual_in
|
||||
scheduled_completion
|
||||
ro_number
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
alt_transport
|
||||
actual_completion
|
||||
inproduction
|
||||
status
|
||||
labhrs: joblines_aggregate(
|
||||
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
||||
) {
|
||||
|
||||
@@ -37,7 +37,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
||||
productionTotal: {},
|
||||
productionHours: 0,
|
||||
};
|
||||
|
||||
let problemJobs = [];
|
||||
//Set the current load.
|
||||
buckets.forEach((bucket) => {
|
||||
load.productionTotal[bucket.id] = { count: 0, label: bucket.label };
|
||||
@@ -45,6 +45,32 @@ export function* calculateScheduleLoad({ payload: end }) {
|
||||
|
||||
prodJobs.forEach((item) => {
|
||||
//Add all of the jobs currently in production to the buckets so that we have a starting point.
|
||||
if (
|
||||
!item.actual_completion &&
|
||||
moment(item.scheduled_completion).isBefore(moment().startOf("day"))
|
||||
) {
|
||||
problemJobs.push({
|
||||
...item,
|
||||
code: "Job was scheduled to go, but it has not been completed. Update the scheduled completion date to correct projections",
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
item.actual_completion &&
|
||||
moment(item.actual_completion).isBefore(moment().startOf("day"))
|
||||
) {
|
||||
problemJobs.push({
|
||||
...item,
|
||||
code: "Job is already marked as completed, but it is still in production. This job should be removed from production",
|
||||
});
|
||||
}
|
||||
if (!(item.actual_completion || item.scheduled_completion)) {
|
||||
problemJobs.push({
|
||||
...item,
|
||||
code: "Job does not have a scheduled or actual completion date. Update the scheduled or actual completion dates to correct projections",
|
||||
});
|
||||
}
|
||||
|
||||
const bucketId = CheckJobBucket(buckets, item);
|
||||
load.productionHours =
|
||||
load.productionHours +
|
||||
@@ -59,77 +85,119 @@ export function* calculateScheduleLoad({ payload: end }) {
|
||||
});
|
||||
|
||||
arrJobs.forEach((item) => {
|
||||
if (!item.scheduled_in)
|
||||
if (!item.scheduled_in) {
|
||||
console.log("JOB HAS NO SCHEDULED IN DATE.", item);
|
||||
const itemDate = moment(item.scheduled_in).format("yyyy-MM-DD");
|
||||
problemJobs.push({
|
||||
...item,
|
||||
code: "Job has no scheduled in date",
|
||||
});
|
||||
}
|
||||
if (
|
||||
item.actual_completion &&
|
||||
moment(item.actual_completion).isAfter(moment())
|
||||
) {
|
||||
problemJobs.push({
|
||||
...item,
|
||||
code: "Job has an actual completion date set in the future",
|
||||
});
|
||||
}
|
||||
if (item.actual_completion && item.inproduction) {
|
||||
problemJobs.push({
|
||||
...item,
|
||||
code: "Job has an actual completion date but it is still marked in production",
|
||||
});
|
||||
}
|
||||
|
||||
const itemDate = moment(item.actual_in || item.scheduled_in).format(
|
||||
"yyyy-MM-DD"
|
||||
);
|
||||
|
||||
const AddJobForSchedulingCalc =
|
||||
!item.inproduction &&
|
||||
!moment(item.actual_completion || item.scheduled_completion).isSame(
|
||||
moment(item.actual_in || item.scheduled_in),
|
||||
"day"
|
||||
);
|
||||
|
||||
if (!!load[itemDate]) {
|
||||
load[itemDate].hoursIn =
|
||||
(load[itemDate].hoursIn || 0) +
|
||||
load[itemDate].allHoursIn =
|
||||
(load[itemDate].allHoursIn || 0) +
|
||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||
load[itemDate].jobsIn.push(item);
|
||||
|
||||
//If the job hasn't already arrived, add it to the jobs in list.
|
||||
// Make sure it also hasn't already been completed, or isn't an in and out job.
|
||||
//This prevents the duplicate counting.
|
||||
load[itemDate].allJobsIn.push(item);
|
||||
if (AddJobForSchedulingCalc) {
|
||||
load[itemDate].jobsIn.push(item);
|
||||
load[itemDate].hoursIn =
|
||||
(load[itemDate].hoursIn || 0) +
|
||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||
}
|
||||
} else {
|
||||
load[itemDate] = {
|
||||
jobsIn: [item],
|
||||
allJobsIn: [item],
|
||||
jobsIn: AddJobForSchedulingCalc ? [item] : [], //Same as above, only add it if it isn't already in production.
|
||||
jobsOut: [],
|
||||
hoursIn:
|
||||
allJobsOut: [],
|
||||
allHoursIn:
|
||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs,
|
||||
hoursIn: AddJobForSchedulingCalc
|
||||
? item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs
|
||||
: 0,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
let problemJobs = [];
|
||||
compJobs.forEach((item) => {
|
||||
if (!(item.actual_completion || item.scheduled_completion))
|
||||
console.log("JOB HAS NO COMPLETION DATE.", item);
|
||||
console.warn("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 AddJobForSchedulingCalc =
|
||||
item.inproduction &&
|
||||
!moment(item.actual_completion || item.scheduled_completion).isSame(
|
||||
moment(item.scheduled_in),
|
||||
"day"
|
||||
) &&
|
||||
(inProdJobs || inArrJobs);
|
||||
|
||||
const itemDate = moment(
|
||||
item.actual_completion || item.scheduled_completion
|
||||
).format("yyyy-MM-DD");
|
||||
//Skip it, it's already completed.
|
||||
|
||||
if (!!load[itemDate]) {
|
||||
load[itemDate].hoursOut =
|
||||
(load[itemDate].hoursOut || 0) +
|
||||
load[itemDate].allHoursOut =
|
||||
(load[itemDate].allHoursOut || 0) +
|
||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||
load[itemDate].jobsOut.push(item);
|
||||
//Add only the jobs that are still in production to get rid of.
|
||||
//If it's not in production, we'd subtract unnecessarily.
|
||||
load[itemDate].allJobsOut.push(item);
|
||||
|
||||
if (AddJobForSchedulingCalc) {
|
||||
load[itemDate].jobsOut.push(item);
|
||||
load[itemDate].hoursOut =
|
||||
(load[itemDate].hoursOut || 0) +
|
||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||
}
|
||||
} else {
|
||||
load[itemDate] = {
|
||||
jobsOut: [item],
|
||||
hoursOut:
|
||||
allJobsOut: [item],
|
||||
jobsOut: AddJobForSchedulingCalc ? [item] : [], //Same as above.
|
||||
hoursOut: AddJobForSchedulingCalc
|
||||
? item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs
|
||||
: 0,
|
||||
allHoursOut:
|
||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||
item.larhrs.aggregate.sum.mod_lb_hrs,
|
||||
};
|
||||
@@ -137,6 +205,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
||||
});
|
||||
|
||||
//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");
|
||||
@@ -146,6 +215,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
||||
if (!!!load[current]) {
|
||||
load[current] = {};
|
||||
}
|
||||
|
||||
if (day === 0) {
|
||||
//Starting on day 1. The load is current.
|
||||
load[current].expectedLoad = CalculateLoad(
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"blocked": "Blocked",
|
||||
"cancelledappointment": "Canceled appointment for: ",
|
||||
"completingjobs": "Completing Jobs",
|
||||
"dataconsistency": "{{ro_number}} has a data consistency issue. It has been excluded for scheduling purposes. CODE: {{code}}.",
|
||||
"dataconsistency": "{{ro_number}} has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.",
|
||||
"expectedjobs": "Expected Jobs in Production: ",
|
||||
"expectedprodhrs": "Expected Production Hours:",
|
||||
"history": "History",
|
||||
|
||||
@@ -23,6 +23,7 @@ let transporter = nodemailer.createTransport({
|
||||
});
|
||||
|
||||
exports.sendServerEmail = async function ({ subject, text }) {
|
||||
if (process.env.NODE_ENV === undefined) return;
|
||||
try {
|
||||
transporter.sendMail(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user