diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss
index 2ed11cbc6..b57e94677 100644
--- a/client/src/App/App.styles.scss
+++ b/client/src/App/App.styles.scss
@@ -156,3 +156,11 @@
td.ant-table-column-sort {
background-color: transparent;
}
+
+.ant-table-tbody > tr.ant-table-row:nth-child(2n) > td {
+ background-color: #f4f4f4;
+}
+
+.rowWithColor > td {
+ background-color: var(--bgColor) !important;
+}
diff --git a/client/src/components/email-overlay/email-overlay.component.jsx b/client/src/components/email-overlay/email-overlay.component.jsx
index 7db03471d..362d973b4 100644
--- a/client/src/components/email-overlay/email-overlay.component.jsx
+++ b/client/src/components/email-overlay/email-overlay.component.jsx
@@ -1,28 +1,28 @@
import { UploadOutlined, UserAddOutlined } from "@ant-design/icons";
import {
+ Button,
Divider,
+ Dropdown,
Form,
Input,
+ Menu,
Select,
+ Space,
Tabs,
Upload,
- Space,
- Menu,
- Dropdown,
- Button,
} from "antd";
+import _ from "lodash";
import React from "react";
import { useTranslation } from "react-i18next";
-import EmailDocumentsComponent from "../email-documents/email-documents.component";
-import _ from "lodash";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
+import { selectEmailConfig } from "../../redux/email/email.selectors";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { CreateExplorerLinkForJob } from "../../utils/localmedia";
-import { selectEmailConfig } from "../../redux/email/email.selectors";
+import EmailDocumentsComponent from "../email-documents/email-documents.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -54,6 +54,15 @@ export function EmailOverlayComponent({
]),
});
};
+ const handle_CC_Click = ({ item, key, keyPath }) => {
+ const email = item.props.value;
+ form.setFieldsValue({
+ cc: _.uniq([
+ ...(form.getFieldValue("cc") || ""),
+ ...(typeof email === "string" ? [email] : email),
+ ]),
+ });
+ };
const menu = (
@@ -74,6 +83,25 @@ export function EmailOverlayComponent({
);
+ const menuCC = (
+
+
+
+ );
+
return (
-
+
+ {t("emails.fields.cc")}
+
+ e.preventDefault()}
+ >
+
+
+
+
+ }
+ name="cc"
+ >
{!jobRO && job.converted && (
-
- e.stopPropagation()}
- onConfirm={async () => {
- //delete the job.
- const result = await voidJob({
- variables: {
- jobId: job.id,
- job: {
- status: bodyshop.md_ro_statuses.default_void,
- voided: true,
- scheduled_in: null,
- scheduled_completion: null,
- inproduction: false,
- },
- note: [
- {
- jobid: job.id,
- created_by: currentUser.email,
- audit: true,
- text: t("jobs.labels.voidnote"),
+
+
+ e.stopPropagation()}
+ onConfirm={async () => {
+ //delete the job.
+ const result = await voidJob({
+ variables: {
+ jobId: job.id,
+ job: {
+ status: bodyshop.md_ro_statuses.default_void,
+ voided: true,
+ scheduled_in: null,
+ scheduled_completion: null,
+ inproduction: false,
},
- ],
- },
- });
+ note: [
+ {
+ jobid: job.id,
+ created_by: currentUser.email,
+ audit: true,
+ text: t("jobs.labels.voidnote"),
+ },
+ ],
+ },
+ });
- if (!!!result.errors) {
- notification["success"]({
- message: t("jobs.successes.voided"),
- });
- //go back to jobs list.
- history.push(`/manage/`);
- } else {
- notification["error"]({
- message: t("jobs.errors.voiding", {
- error: JSON.stringify(result.errors),
- }),
- });
- }
- }}
- getPopupContainer={(trigger) => trigger.parentNode}
- >
- {t("menus.jobsactions.void")}
-
-
+ if (!!!result.errors) {
+ notification["success"]({
+ message: t("jobs.successes.voided"),
+ });
+ //go back to jobs list.
+ history.push(`/manage/`);
+ } else {
+ notification["error"]({
+ message: t("jobs.errors.voiding", {
+ error: JSON.stringify(result.errors),
+ }),
+ });
+ }
+ }}
+ getPopupContainer={(trigger) => trigger.parentNode}
+ >
+ {t("menus.jobsactions.void")}
+
+
+
)}
);
diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx
index 189014d37..e28e21901 100644
--- a/client/src/components/jobs-list/jobs-list.component.jsx
+++ b/client/src/components/jobs-list/jobs-list.component.jsx
@@ -112,7 +112,9 @@ export function JobsList({ bodyshop }) {
title: t("jobs.fields.ro_number"),
dataIndex: "ro_number",
key: "ro_number",
- sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
+ sorter: (a, b) =>
+ parseInt((a.ro_number || "0").replace(/\D/g, "")) -
+ parseInt((b.ro_number || "0").replace(/\D/g, "")),
sortOrder:
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
diff --git a/client/src/components/print-center-jobs/print-center-jobs.component.jsx b/client/src/components/print-center-jobs/print-center-jobs.component.jsx
index c96e3d3a5..ddb9a247d 100644
--- a/client/src/components/print-center-jobs/print-center-jobs.component.jsx
+++ b/client/src/components/print-center-jobs/print-center-jobs.component.jsx
@@ -23,17 +23,34 @@ export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
const { id: jobId, job } = printCenterModal.context;
const tempList = TemplateList("job", {});
const { t } = useTranslation();
- const JobsReportsList = Object.keys(tempList)
- .map((key) => {
- return tempList[key];
- })
- .filter(
- (temp) =>
- !temp.regions ||
- (temp.regions && temp.regions[bodyshop.region_config]) ||
- (temp.regions &&
- bodyshop.region_config.includes(Object.keys(temp.regions)) === true)
- );
+
+ const JobsReportsList =
+ bodyshop.cdk_dealerid === null && bodyshop.pbs_serialnumber === null
+ ? Object.keys(tempList)
+ .map((key) => {
+ return tempList[key];
+ })
+ .filter(
+ (temp) =>
+ (!temp.regions ||
+ (temp.regions && temp.regions[bodyshop.region_config]) ||
+ (temp.regions &&
+ bodyshop.region_config.includes(Object.keys(temp.regions)) ===
+ true)) &&
+ (!temp.dms || temp.dms === false)
+ )
+ : Object.keys(tempList)
+ .map((key) => {
+ return tempList[key];
+ })
+ .filter(
+ (temp) =>
+ !temp.regions ||
+ (temp.regions && temp.regions[bodyshop.region_config]) ||
+ (temp.regions &&
+ bodyshop.region_config.includes(Object.keys(temp.regions)) ===
+ true)
+ );
const filteredJobsReportsList =
search !== ""
diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx
index 746d956ab..1585c6480 100644
--- a/client/src/components/production-list-table/production-list-table.component.jsx
+++ b/client/src/components/production-list-table/production-list-table.component.jsx
@@ -246,11 +246,21 @@ export function ProductionListTable({
(x) => x.status === record.status
);
- if (!color) return null;
+ if (!color) {
+ if (index % 2 === 0)
+ return {
+ style: {
+ backgroundColor: `rgb(236, 236, 236)`,
+ },
+ };
+
+ return null;
+ }
return {
+ className: "rowWithColor",
style: {
- backgroundColor: `rgb(${color.color.r},${color.color.g},${color.color.b},${color.color.a})`,
+ "--bgColor": `rgb(${color.color.r},${color.color.g},${color.color.b},${color.color.a})`,
},
};
},
diff --git a/client/src/components/rbac-wrapper/rbac-defaults.js b/client/src/components/rbac-wrapper/rbac-defaults.js
index 1c2a779c4..24a564872 100644
--- a/client/src/components/rbac-wrapper/rbac-defaults.js
+++ b/client/src/components/rbac-wrapper/rbac-defaults.js
@@ -26,6 +26,8 @@ const ret = {
"jobs:partsqueue": 4,
"jobs:checklist-view": 2,
"jobs:list-ready": 1,
+ "jobs:void": 5,
+
"bills:enter": 2,
"bills:view": 2,
"bills:list": 2,
diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx
index 837f5cbbe..7cd90bd14 100644
--- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx
+++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx
@@ -12,7 +12,8 @@ import "./schedule-calendar.styles.scss";
import JobDetailCards from "../job-detail-cards/job-detail-cards.component";
import { selectProblemJobs } from "../../redux/application/application.selectors";
import { Alert, Collapse } from "antd";
-import { useTranslation } from "react-i18next";
+import { useTranslation, Trans } from "react-i18next";
+import { Link } from "react-router-dom";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -66,10 +67,21 @@ export function ScheduleCalendarWrapperComponent({
,
+ ]}
+ values={{
+ ro_number: problem.ro_number,
+ code: problem.code,
+ }}
+ />
+ }
/>
))}
@@ -79,10 +91,18 @@ export function ScheduleCalendarWrapperComponent({
,
+ ]}
+ values={{
+ ro_number: problem.ro_number,
+ code: problem.code,
+ }}
+ />
+ }
/>
))
)}
diff --git a/client/src/components/shop-info/shop-info.rbac.component.jsx b/client/src/components/shop-info/shop-info.rbac.component.jsx
index 291369255..fe4f80f31 100644
--- a/client/src/components/shop-info/shop-info.rbac.component.jsx
+++ b/client/src/components/shop-info/shop-info.rbac.component.jsx
@@ -1,12 +1,12 @@
+import { useTreatments } from "@splitsoftware/splitio-react";
import { Form, InputNumber } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
-import LayoutFormRow from "../layout-form-row/layout-form-row.component";
-import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
-import { useTreatments } from "@splitsoftware/splitio-react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
+import LayoutFormRow from "../layout-form-row/layout-form-row.component";
+import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
@@ -316,6 +316,18 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
>
+
+
+
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index 21983e70f..b93d0c0a4 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -49,7 +49,7 @@
"blocked": "Blocked",
"cancelledappointment": "Canceled appointment for: ",
"completingjobs": "Completing Jobs",
- "dataconsistency": "{{ro_number}} has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.",
+ "dataconsistency": "<0>{{ro_number}}0> 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",
@@ -405,7 +405,8 @@
"list-active": "Jobs -> List Active",
"list-all": "Jobs -> List All",
"list-ready": "Jobs -> List Ready",
- "partsqueue": "Jobs -> Parts Queue"
+ "partsqueue": "Jobs -> Parts Queue",
+ "void": "Jobs -> Void"
},
"owners": {
"detail": "Owners -> Detail",
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index 0ead918b2..ff3efbd30 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -405,7 +405,8 @@
"list-active": "",
"list-all": "",
"list-ready": "",
- "partsqueue": ""
+ "partsqueue": "",
+ "void": ""
},
"owners": {
"detail": "",
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index 040080a88..c8fc9ee4a 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -405,7 +405,8 @@
"list-active": "",
"list-all": "",
"list-ready": "",
- "partsqueue": ""
+ "partsqueue": "",
+ "void": ""
},
"owners": {
"detail": "",
diff --git a/client/src/utils/TemplateConstants.js b/client/src/utils/TemplateConstants.js
index 78f2f12f2..debbfc57e 100644
--- a/client/src/utils/TemplateConstants.js
+++ b/client/src/utils/TemplateConstants.js
@@ -512,6 +512,7 @@ export const TemplateList = (type, context) => {
key: "dms_posting_sheet",
disabled: false,
group: "financial",
+ dms: true,
},
}
: {}),
diff --git a/server/cdk/cdk-job-export.js b/server/cdk/cdk-job-export.js
index 37265a0a7..c20a899a1 100644
--- a/server/cdk/cdk-job-export.js
+++ b/server/cdk/cdk-job-export.js
@@ -729,9 +729,15 @@ async function InsertDmsVehicle(socket) {
deliveryDate: moment()
// .tz(socket.JobData.bodyshop.timezone)
.format("YYYYMMDD"),
- licensePlateNo: String(socket.JobData.plate_no)
- .replace(/([^\w]|_)/g, "")
- .toUpperCase(),
+ licensePlateNo:
+ socket.JobData.plate_no === null
+ ? null
+ : String(socket.JobData.plate_no).replace(/([^\w]|_)/g, "")
+ .length === 0
+ ? null
+ : String(socket.JobData.plate_no)
+ .replace(/([^\w]|_)/g, "")
+ .toUpperCase(),
make: socket.txEnvelope.dms_make,
modelAbrev: socket.txEnvelope.dms_model,
modelYear: socket.JobData.v_model_yr,