diff --git a/client/src/components/job-payments/job-payments.component.jsx b/client/src/components/job-payments/job-payments.component.jsx
index bfb74d8fc..979b23d44 100644
--- a/client/src/components/job-payments/job-payments.component.jsx
+++ b/client/src/components/job-payments/job-payments.component.jsx
@@ -133,6 +133,7 @@ export function JobPayments({
}
];
+ //Same as in RO guard. If changed, update in both.
const total = useMemo(() => {
return (
job.payments &&
diff --git a/client/src/components/labor-allocations-table/labor-allocations-table.component.jsx b/client/src/components/labor-allocations-table/labor-allocations-table.component.jsx
index 649f49584..aabe7b179 100644
--- a/client/src/components/labor-allocations-table/labor-allocations-table.component.jsx
+++ b/client/src/components/labor-allocations-table/labor-allocations-table.component.jsx
@@ -1,5 +1,5 @@
import { EditFilled } from "@ant-design/icons";
-import { Card, Col, Row, Space, Table, Typography } from "antd";
+import { Alert, Card, Col, Row, Space, Table, Typography } from "antd";
import _ from "lodash";
import React, { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
@@ -18,7 +18,16 @@ const mapStateToProps = createStructuredSelector({
technician: selectTechnician
});
-export function LaborAllocationsTable({ jobId, joblines, timetickets, bodyshop, adjustments, technician }) {
+export function LaborAllocationsTable({
+ jobId,
+ joblines,
+ timetickets,
+ bodyshop,
+ adjustments,
+ technician,
+ showWarning,
+ warningCallback
+}) {
const { t } = useTranslation();
const [totals, setTotals] = useState([]);
const [state, setState] = useState({
@@ -176,6 +185,10 @@ export function LaborAllocationsTable({ jobId, joblines, timetickets, bodyshop,
{ hrs_total: 0, hrs_claimed: 0, adjustments: 0, difference: 0 }
);
+ if (summary.difference !== 0 && typeof warningCallback === "function") {
+ warningCallback({ key: "labor", warning: t("jobs.labels.outstandinghours") });
+ }
+
return (
@@ -227,6 +240,9 @@ export function LaborAllocationsTable({ jobId, joblines, timetickets, bodyshop,
)}
+ {showWarning && summary.difference !== 0 && (
+
+ )}
);
}
diff --git a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx
index 164c75fb2..3e8adc17b 100644
--- a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx
+++ b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx
@@ -1,4 +1,4 @@
-import { Button, Card, Col, notification, Row, Space, Table, Typography } from "antd";
+import { Alert, Button, Card, Col, notification, Row, Space, Table, Typography } from "antd";
import { SyncOutlined } from "@ant-design/icons";
import axios from "axios";
import _ from "lodash";
@@ -23,7 +23,9 @@ export function PayrollLaborAllocationsTable({
bodyshop,
adjustments,
technician,
- refetch
+ refetch,
+ showWarning,
+ warningCallback
}) {
const { t } = useTranslation();
const [totals, setTotals] = useState([]);
@@ -191,6 +193,10 @@ export function PayrollLaborAllocationsTable({
{ hrs_total: 0, hrs_claimed: 0, adjustments: 0, difference: 0 }
);
+ if (summary.difference !== 0 && typeof warningCallback === "function") {
+ warningCallback({ key: "labor", warning: t("jobs.labels.outstandinghours") });
+ }
+
return (
@@ -285,6 +291,9 @@ export function PayrollLaborAllocationsTable({
)}
+ {showWarning && summary.difference !== 0 && (
+
+ )}
);
}
diff --git a/client/src/components/shop-info/shop-info.component.jsx b/client/src/components/shop-info/shop-info.component.jsx
index 90f4a5034..fd9ba96a8 100644
--- a/client/src/components/shop-info/shop-info.component.jsx
+++ b/client/src/components/shop-info/shop-info.component.jsx
@@ -1,24 +1,25 @@
-import { useSplitTreatments } from "@splitsoftware/splitio-react";
-import { Button, Card, Tabs } from "antd";
-import React from "react";
-import { useTranslation } from "react-i18next";
-import { connect } from "react-redux";
-import { createStructuredSelector } from "reselect";
-import { selectBodyshop } from "../../redux/user/user.selectors";
-import ShopInfoGeneral from "./shop-info.general.component";
-import ShopInfoIntakeChecklistComponent from "./shop-info.intake.component";
-import ShopInfoLaborRates from "./shop-info.laborrates.component";
-import ShopInfoOrderStatusComponent from "./shop-info.orderstatus.component";
-import ShopInfoPartsScan from "./shop-info.parts-scan";
-import ShopInfoRbacComponent from "./shop-info.rbac.component";
-import ShopInfoResponsibilityCenterComponent from "./shop-info.responsibilitycenters.component";
-import ShopInfoROStatusComponent from "./shop-info.rostatus.component";
-import ShopInfoSchedulingComponent from "./shop-info.scheduling.component";
-import ShopInfoSpeedPrint from "./shop-info.speedprint.component";
-import { useLocation, useNavigate } from "react-router-dom";
-import ShopInfoTaskPresets from "./shop-info.task-presets.component";
-import queryString from "query-string";
-import InstanceRenderManager from "../../utils/instanceRenderMgr";
+import { useSplitTreatments } from '@splitsoftware/splitio-react';
+import { Button, Card, Tabs } from 'antd';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { connect } from 'react-redux';
+import { createStructuredSelector } from 'reselect';
+import { selectBodyshop } from '../../redux/user/user.selectors';
+import ShopInfoGeneral from './shop-info.general.component';
+import ShopInfoIntakeChecklistComponent from './shop-info.intake.component';
+import ShopInfoLaborRates from './shop-info.laborrates.component';
+import ShopInfoOrderStatusComponent from './shop-info.orderstatus.component';
+import ShopInfoPartsScan from './shop-info.parts-scan';
+import ShopInfoRbacComponent from './shop-info.rbac.component';
+import ShopInfoResponsibilityCenterComponent from './shop-info.responsibilitycenters.component';
+import ShopInfoROStatusComponent from './shop-info.rostatus.component';
+import ShopInfoSchedulingComponent from './shop-info.scheduling.component';
+import ShopInfoSpeedPrint from './shop-info.speedprint.component';
+import { useLocation, useNavigate } from 'react-router-dom';
+import ShopInfoTaskPresets from './shop-info.task-presets.component';
+import queryString from 'query-string';
+import InstanceRenderManager from '../../utils/instanceRenderMgr';
+import ShopInfoRoGuard from './shop-info.roguard.component';
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
@@ -111,7 +112,18 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) {
children:
}
]
- : [])
+ : []),
+ ...InstanceRenderManager({
+ imex: [
+ {
+ key: 'roguard',
+ label: t('bodyshop.labels.roguard.title'),
+ children:
,
+ },
+ ],
+ rome: 'USE_IMEX',
+ promanager: [],
+ }),
];
return (
+
+
+
+
+
+
+ {() => {
+ const disabled = !form.getFieldValue(['md_ro_guard', 'enabled']);
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }}
+
+
+ );
+}
diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js
index e1d5b93e1..6bbafe6e3 100644
--- a/client/src/graphql/bodyshop.queries.js
+++ b/client/src/graphql/bodyshop.queries.js
@@ -138,6 +138,7 @@ export const QUERY_BODYSHOP = gql`
tt_enforce_hours_for_tech_console
md_tasks_presets
use_paint_scale_data
+ md_ro_guard
employee_teams(order_by: { name: asc }, where: { active: { _eq: true } }) {
id
name
@@ -265,6 +266,7 @@ export const UPDATE_SHOP = gql`
enforce_conversion_category
tt_enforce_hours_for_tech_console
md_tasks_presets
+ md_ro_guard
employee_teams(order_by: { name: asc }, where: { active: { _eq: true } }) {
id
name
diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js
index 1dd4ea175..52a14bb61 100644
--- a/client/src/graphql/jobs.queries.js
+++ b/client/src/graphql/jobs.queries.js
@@ -1969,6 +1969,19 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
kmout
qb_multiple_payers
lbr_adjustments
+ payments {
+ amount
+ created_at
+ date
+ exportedat
+ id
+ jobid
+ memo
+ payer
+ paymentnum
+ transactionid
+ type
+ }
joblines(where: { removed: { _eq: false } }, order_by: { line_no: asc }) {
id
removed
@@ -1981,6 +1994,7 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
db_price
act_price
part_qty
+ notes
mod_lbr_ty
db_hrs
mod_lb_hrs
@@ -1992,6 +2006,9 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
prt_dsmk_p
convertedtolbr
convertedtolbr_data
+ act_price_before_ppc
+ sublet_ignored
+ sublet_completed
}
}
}
diff --git a/client/src/pages/jobs-close/jobs-close.component.jsx b/client/src/pages/jobs-close/jobs-close.component.jsx
index 0554f6a6e..102ba0611 100644
--- a/client/src/pages/jobs-close/jobs-close.component.jsx
+++ b/client/src/pages/jobs-close/jobs-close.component.jsx
@@ -41,6 +41,7 @@ import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
+import JobCloseRoGuardContainer from '../../components/job-close-ro-guard/job-close-ro-guard.container';
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -183,7 +184,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail }) {
}
/>
-
+