IO-1613 add suspended days to jobs.

This commit is contained in:
Patrick Fic
2022-01-04 12:33:20 -08:00
parent fc023367cc
commit 6457acc61e
18 changed files with 170 additions and 24 deletions

View File

@@ -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 BabelEdit project file
@@ -26904,6 +26904,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>suspended</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>suspense</name> <name>suspense</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -35564,6 +35585,48 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>suspend</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>unsuspend</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children> </children>
</folder_node> </folder_node>
<folder_node> <folder_node>

View File

@@ -89,6 +89,19 @@ export function JobsDetailHeaderActions({
}); });
}; };
const handleSuspend = (e) => {
logImEXEvent("production_toggle_alert");
//e.stopPropagation();
updateJob({
variables: {
jobId: job.id,
job: {
suspended: !job.suspended,
},
},
});
};
const statusmenu = ( const statusmenu = (
<Menu key="popovermenu"> <Menu key="popovermenu">
<Menu.Item <Menu.Item
@@ -199,7 +212,11 @@ export function JobsDetailHeaderActions({
{t("jobs.actions.addtoproduction")} {t("jobs.actions.addtoproduction")}
</Menu.Item> </Menu.Item>
)} )}
<Menu.Item key="togglesuspend" onClick={handleSuspend}>
{job.suspended
? t("production.actions.unsuspend")
: t("production.actions.suspend")}
</Menu.Item>
<Menu.Item key="toggleAlert" onClick={handleAlertToggle}> <Menu.Item key="toggleAlert" onClick={handleAlertToggle}>
{job.production_vars && job.production_vars.alert {job.production_vars && job.production_vars.alert
? t("production.labels.alertoff") ? t("production.labels.alertoff")

View File

@@ -1,5 +1,9 @@
import { Card, Col, Row, Space, Tag } from "antd"; import { Card, Col, Row, Space, Tag } from "antd";
import { WarningFilled, ExclamationCircleFilled } from "@ant-design/icons"; import {
WarningFilled,
ExclamationCircleFilled,
PauseCircleOutlined,
} from "@ant-design/icons";
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -68,6 +72,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
{t("jobs.labels.inproduction")} {t("jobs.labels.inproduction")}
</Tag> </Tag>
)} )}
{job.suspended && (
<PauseCircleOutlined style={{ color: "orangered" }} />
)}
{job.production_vars && job.production_vars.alert ? ( {job.production_vars && job.production_vars.alert ? (
<ExclamationCircleFilled className="production-alert" /> <ExclamationCircleFilled className="production-alert" />
) : null} ) : null}

View File

@@ -1,4 +1,8 @@
import { SyncOutlined, ExclamationCircleFilled } from "@ant-design/icons"; import {
SyncOutlined,
ExclamationCircleFilled,
PauseCircleOutlined,
} from "@ant-design/icons";
import { useQuery } from "@apollo/client"; import { useQuery } from "@apollo/client";
import { Button, Card, Grid, Input, Space, Table } from "antd"; import { Button, Card, Grid, Input, Space, Table } from "antd";
import queryString from "query-string"; import queryString from "query-string";
@@ -111,6 +115,9 @@ export function JobsList({ bodyshop }) {
{record.production_vars && record.production_vars.alert ? ( {record.production_vars && record.production_vars.alert ? (
<ExclamationCircleFilled className="production-alert" /> <ExclamationCircleFilled className="production-alert" />
) : null} ) : null}
{record.suspended && (
<PauseCircleOutlined style={{ color: "orangered" }} />
)}
</Space> </Space>
</Link> </Link>
), ),

View File

@@ -1,4 +1,8 @@
import { CalendarOutlined, EyeFilled } from "@ant-design/icons"; import {
CalendarOutlined,
EyeFilled,
PauseCircleOutlined,
} from "@ant-design/icons";
import { Card, Col, Row, Space } from "antd"; import { Card, Col, Row, Space } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -40,6 +44,9 @@ export default function ProductionBoardCard(
title={ title={
<Space> <Space>
<ProductionAlert record={card} key="alert" /> <ProductionAlert record={card} key="alert" />
{card.suspended && (
<PauseCircleOutlined style={{ color: "orangered" }} />
)}
<span style={{ fontWeight: "bolder" }}> <span style={{ fontWeight: "bolder" }}>
{card.ro_number || t("general.labels.na")} {card.ro_number || t("general.labels.na")}
</span> </span>

View File

@@ -1,3 +1,5 @@
import { PauseCircleOutlined } from "@ant-design/icons";
import { Space } from "antd";
import i18n from "i18next"; import i18n from "i18next";
import moment from "moment"; import moment from "moment";
import React from "react"; import React from "react";
@@ -43,9 +45,19 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
technician ? ( technician ? (
<Link to={`/tech/joblookup?selected=${record.id}`}> <Link to={`/tech/joblookup?selected=${record.id}`}>
{record.ro_number} {record.ro_number}
{record.suspended && (
<PauseCircleOutlined style={{ color: "orangered" }} />
)}
</Link> </Link>
) : ( ) : (
<Link to={`/manage/jobs/${record.id}`}>{record.ro_number}</Link> <Link to={`/manage/jobs/${record.id}`}>
<Space>
{record.ro_number}
{record.suspended && (
<PauseCircleOutlined style={{ color: "orangered" }} />
)}
</Space>
</Link>
), ),
}, },
{ {

View File

@@ -5,6 +5,7 @@ import { QUERY_APPOINTMENT_BY_DATE } from "../../graphql/appointments.queries";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import moment from "moment"; import moment from "moment";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export default function ScheduleDayViewContainer({ day }) { export default function ScheduleDayViewContainer({ day }) {
const { loading, error, data } = useQuery(QUERY_APPOINTMENT_BY_DATE, { const { loading, error, data } = useQuery(QUERY_APPOINTMENT_BY_DATE, {
variables: { variables: {

View File

@@ -188,10 +188,10 @@ export function ScheduleJobModalComponent({
/> />
</Col> </Col>
<Col span={12}> <Col span={12}>
<Form.Item shouldUpdate> <Form.Item shouldUpdate={(prev, cur) => prev.start !== cur.start}>
{() => { {() => {
console.log("render");
const values = form.getFieldsValue(); const values = form.getFieldsValue();
return ( return (
<div className="schedule-job-modal"> <div className="schedule-job-modal">
<ScheduleDayViewContainer day={values.start} /> <ScheduleDayViewContainer day={values.start} />

View File

@@ -212,7 +212,9 @@ export const QUERY_APPOINTMENTS_BY_JOBID = gql`
`; `;
export const QUERY_SCHEDULE_LOAD_DATA = gql` export const QUERY_SCHEDULE_LOAD_DATA = gql`
query QUERY_SCHEDULE_LOAD_DATA($start: timestamptz!, $end: timestamptz!) { query QUERY_SCHEDULE_LOAD_DATA($start: timestamptz!, $end: timestamptz!) {
prodJobs: jobs(where: { inproduction: { _eq: true } }) { prodJobs: jobs(
where: { inproduction: { _eq: true }, suspended: { _eq: false } }
) {
id id
labhrs: joblines_aggregate( labhrs: joblines_aggregate(
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } } where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
@@ -235,9 +237,14 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
} }
compJobs: jobs( compJobs: jobs(
where: { where: {
_or: [ _and: [
{ scheduled_completion: { _gte: $start, _lte: $end } } { suspended: { _eq: false } }
{ actual_completion: { _gte: $start, _lte: $end } } {
_or: [
{ scheduled_completion: { _gte: $start, _lte: $end } }
{ actual_completion: { _gte: $start, _lte: $end } }
]
}
] ]
} }
) { ) {
@@ -264,7 +271,12 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
} }
} }
} }
arrJobs: jobs(where: { scheduled_in: { _gte: $start, _lte: $end } }) { arrJobs: jobs(
where: {
scheduled_in: { _gte: $start, _lte: $end }
suspended: { _eq: false }
}
) {
id id
scheduled_in scheduled_in
ro_number ro_number

View File

@@ -42,6 +42,7 @@ export const QUERY_ALL_ACTIVE_JOBS = gql`
status status
updated_at updated_at
ded_amt ded_amt
suspended
} }
} }
`; `;
@@ -290,6 +291,7 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
employee_refinish employee_refinish
employee_prep employee_prep
employee_csr employee_csr
suspended
labhrs: joblines_aggregate( labhrs: joblines_aggregate(
where: { where: {
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }] _and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
@@ -654,6 +656,7 @@ export const GET_JOB_BY_PK = gql`
voided voided
ca_bc_pvrt ca_bc_pvrt
ca_customer_gst ca_customer_gst
suspended
joblines(where: { removed: { _eq: false } }, order_by: { line_no: asc }) { joblines(where: { removed: { _eq: false } }, order_by: { line_no: asc }) {
id id
alt_partm alt_partm
@@ -828,6 +831,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
ca_gst_registrant ca_gst_registrant
owner_owing owner_owing
special_coverage_policy special_coverage_policy
suspended
available_jobs { available_jobs {
id id
} }
@@ -1034,6 +1038,7 @@ export const UPDATE_JOB = gql`
ro_number ro_number
production_vars production_vars
lbr_adjustments lbr_adjustments
suspended
} }
} }
} }

View File

@@ -1578,6 +1578,7 @@
"subletstotal": "Sublets Total", "subletstotal": "Sublets Total",
"subtotal": "Subtotal", "subtotal": "Subtotal",
"supplementnote": "The job had a supplement imported.", "supplementnote": "The job had a supplement imported.",
"suspended": "SUSPENDED",
"suspense": "Suspense", "suspense": "Suspense",
"total_cost": "Total Cost", "total_cost": "Total Cost",
"total_cust_payable": "Total Customer Amount Payable", "total_cust_payable": "Total Customer Amount Payable",
@@ -2118,7 +2119,9 @@
"paintpriority-set": "Set Paint Priority", "paintpriority-set": "Set Paint Priority",
"remove": "Remove from Production", "remove": "Remove from Production",
"removecolumn": "Remove Column", "removecolumn": "Remove Column",
"saveconfig": "Save Configuration" "saveconfig": "Save Configuration",
"suspend": "Suspend",
"unsuspend": "Unsuspend"
}, },
"errors": { "errors": {
"boardupdate": "Error encountered updating job. {{message}}", "boardupdate": "Error encountered updating job. {{message}}",

View File

@@ -1578,6 +1578,7 @@
"subletstotal": "", "subletstotal": "",
"subtotal": "", "subtotal": "",
"supplementnote": "", "supplementnote": "",
"suspended": "",
"suspense": "", "suspense": "",
"total_cost": "", "total_cost": "",
"total_cust_payable": "", "total_cust_payable": "",
@@ -2118,7 +2119,9 @@
"paintpriority-set": "", "paintpriority-set": "",
"remove": "", "remove": "",
"removecolumn": "", "removecolumn": "",
"saveconfig": "" "saveconfig": "",
"suspend": "",
"unsuspend": ""
}, },
"errors": { "errors": {
"boardupdate": "", "boardupdate": "",

View File

@@ -1578,6 +1578,7 @@
"subletstotal": "", "subletstotal": "",
"subtotal": "", "subtotal": "",
"supplementnote": "", "supplementnote": "",
"suspended": "",
"suspense": "", "suspense": "",
"total_cost": "", "total_cost": "",
"total_cust_payable": "", "total_cust_payable": "",
@@ -2118,7 +2119,9 @@
"paintpriority-set": "", "paintpriority-set": "",
"remove": "", "remove": "",
"removecolumn": "", "removecolumn": "",
"saveconfig": "" "saveconfig": "",
"suspend": "",
"unsuspend": ""
}, },
"errors": { "errors": {
"boardupdate": "", "boardupdate": "",

View File

@@ -2780,6 +2780,7 @@
- state_tax_rate - state_tax_rate
- status - status
- storage_payable - storage_payable
- suspended
- tax_lbr_rt - tax_lbr_rt
- tax_levies_rt - tax_levies_rt
- tax_paint_mat_rt - tax_paint_mat_rt
@@ -3035,6 +3036,7 @@
- state_tax_rate - state_tax_rate
- status - status
- storage_payable - storage_payable
- suspended
- tax_lbr_rt - tax_lbr_rt
- tax_levies_rt - tax_levies_rt
- tax_paint_mat_rt - tax_paint_mat_rt
@@ -3300,6 +3302,7 @@
- state_tax_rate - state_tax_rate
- status - status
- storage_payable - storage_payable
- suspended
- tax_lbr_rt - tax_lbr_rt
- tax_levies_rt - tax_levies_rt
- tax_paint_mat_rt - tax_paint_mat_rt

View File

@@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."jobs" add column "suspended" boolean
-- not null default 'false';

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "suspended" boolean
not null default 'false';

View File

@@ -473,7 +473,7 @@ exports.QUERY_UPCOMING_APPOINTMENTS = `query QUERY_UPCOMING_APPOINTMENTS($now: t
start start
block block
} }
arrJobs: jobs(where: {scheduled_in: {_gte: $now}}) { arrJobs: jobs(where: {scheduled_in: {_gte: $now}, suspended: {_eq: false}}) {
id id
scheduled_in scheduled_in
ro_number ro_number
@@ -492,7 +492,7 @@ exports.QUERY_UPCOMING_APPOINTMENTS = `query QUERY_UPCOMING_APPOINTMENTS($now: t
} }
} }
} }
compJobs: jobs(where: {_or: [{scheduled_completion: {_gte: $now}}, {actual_completion: {_gte: $now}}]}) { compJobs: jobs(where: {_and: [{suspended: {_eq: false}}, {_or: [{scheduled_completion: {_gte: $now}}, {actual_completion: {_gte: $now}}]}]}) {
id id
ro_number ro_number
scheduled_completion scheduled_completion
@@ -512,7 +512,7 @@ exports.QUERY_UPCOMING_APPOINTMENTS = `query QUERY_UPCOMING_APPOINTMENTS($now: t
} }
} }
} }
prodJobs: jobs(where: {inproduction: {_eq: true}}) { prodJobs: jobs(where: {inproduction: {_eq: true}, suspended: {_eq: false}}) {
id id
scheduled_completion scheduled_completion
labhrs: joblines_aggregate(where: {_and: [{mod_lbr_ty: {_neq: "LAR"}}, {removed: {_eq: false}}]}) { labhrs: joblines_aggregate(where: {_and: [{mod_lbr_ty: {_neq: "LAR"}}, {removed: {_eq: false}}]}) {
@@ -530,11 +530,7 @@ exports.QUERY_UPCOMING_APPOINTMENTS = `query QUERY_UPCOMING_APPOINTMENTS($now: t
} }
} }
} }
} }`;
`;
exports.QUERY_EMPLOYEE_PIN = `query QUERY_EMPLOYEE_PIN($shopId: uuid!, $employeeId: String!) { exports.QUERY_EMPLOYEE_PIN = `query QUERY_EMPLOYEE_PIN($shopId: uuid!, $employeeId: String!) {
employees(where: {_and: {shopid: {_eq: $shopId}, employee_number: {_eq: $employeeId}}}) { employees(where: {_and: {shopid: {_eq: $shopId}, employee_number: {_eq: $employeeId}}}) {

View File

@@ -140,6 +140,7 @@ exports.job = async (req, res) => {
...filteredCompJobs ...filteredCompJobs
.map((p) => moment(p.actual_completion || p.scheduled_completion)) .map((p) => moment(p.actual_completion || p.scheduled_completion))
.filter((p) => p.isValid() && p.isAfter(yesterday)), .filter((p) => p.isValid() && p.isAfter(yesterday)),
moment().add(5, "days"),
]); ]);
const range = Math.round(moment.duration(end.diff(today)).asDays()); const range = Math.round(moment.duration(end.diff(today)).asDays());
for (var day = 0; day < range; day++) { for (var day = 0; day < range; day++) {