Compare commits

...

61 Commits

Author SHA1 Message Date
Allan Carr
55842faedd IO-2468 CC Mileage and Service KMs 2023-11-21 14:01:33 -08:00
Allan Carr
c0d756fa38 Merged in release/2023-11-17 (pull request #1060)
Release/2023 11 17
2023-11-17 21:46:20 +00:00
Allan Carr
fc16190ec4 Merged in feature/IO-2470-CC-Year-b-Make-UI (pull request #1058)
IO-2470-CC-Year-b-Make-UI
2023-11-17 19:08:43 +00:00
Allan Carr
cf7f4f1b46 IO-2470-CC-Year-b-Make-UI 2023-11-17 11:08:17 -08:00
Dave Richer
ba95a636cf Merged in feature/IO-2331-Remove-Required-CC-Fields (pull request #1055)
IO-2331 Remove required CC fields Next Service KMS and Next Service Date
2023-11-15 22:13:56 +00:00
Dave Richer
2478fedf1a IO-2331 Remove required CC fields Next Service KMS and Next Service Date 2023-11-15 17:10:52 -05:00
Dave Richer
bc6c889afc Merged in feature/io-2283-Add-Plate-Number-To-Global-Search (pull request #1053)
IO-2283 - Add Plate Number to global search

Approved-by: Patrick Fic
2023-11-15 21:42:09 +00:00
Dave Richer
33bcf250d0 Merged release/2023-11-17 into feature/io-2283-Add-Plate-Number-To-Global-Search 2023-11-15 21:32:04 +00:00
Dave Richer
bad32e069b IO-2283 - Add Plate Number to global search 2023-11-15 16:29:04 -05:00
Allan Carr
9acf20d4f3 Merged in feature/IO-1016-Registration-Expiry-for-CCs (pull request #1052)
IO-1016 Remove required rule for Registration Expiry date
2023-11-15 18:36:53 +00:00
Allan Carr
26f1ee0d89 Merged in feature/IO-2453-Clear-Bin-Location (pull request #1051)
IO-2453 Clear Bin Location
2023-11-15 18:36:36 +00:00
Allan Carr
9c86be8250 Merged in feature/IO-2448-CC-Search-by-Plate (pull request #1050)
IO-2448 Search by C/C Plate number
2023-11-15 18:36:20 +00:00
Allan Carr
4a06f9a686 Merged in feature/IO-2451-Non-Converted-Jobs-in-List (pull request #1049)
IO-2451 Non Converted Jobs in Lists
2023-11-15 18:36:04 +00:00
Allan Carr
98700f54b4 IO-1016 Remove required rule for Registration Expiry date 2023-11-14 17:55:57 -08:00
Patrick Fic
9a37cb5cb8 IO-1532 Re-enable hasura event. 2023-11-14 13:53:28 -08:00
Allan Carr
673d0bb7c5 IO-2453 Clear Bin Location 2023-11-14 12:15:09 -08:00
Allan Carr
04c7bc445b IO-2448 Search by C/C Plate number 2023-11-10 16:32:38 -08:00
Allan Carr
41782fe120 IO-2451 Non Converted Jobs in Lists
These lists should be converted jobs only
2023-11-10 16:01:17 -08:00
Patrick Fic
4e8e25a336 Merged in release/2023-11-10 (pull request #1048)
Release/2023 11 10
2023-11-10 19:21:15 +00:00
Patrick Fic
3c2d3156cb Merge branch 'release/2023-11-10' into test 2023-11-09 13:39:46 -08:00
Patrick Fic
0dac15391f Merge branch 'feature/IO-2445-block-types' into release/2023-11-10 2023-11-09 13:39:21 -08:00
Patrick Fic
106534b59b IO-2445 Updated blocked day types. 2023-11-09 13:39:05 -08:00
Allan Carr
19c0553746 Merged in release/2023-11-10 (pull request #1047)
Release/2023 11 10
2023-11-09 21:23:41 +00:00
Patrick Fic
5f1475d2ec Merge branch 'feature/IO-2444-single-device-login' into release/2023-11-10 2023-11-08 12:08:32 -08:00
Patrick Fic
84f4d5956a IO-2444 update fingerprint JS and re-enable using shop flag. 2023-11-08 12:08:21 -08:00
Allan Carr
4330ddd926 Merged in feature/IO-2438-All-Employee-Scoreboard-Summary (pull request #1046)
IO-2438 All Employee Scoreboard
2023-11-08 17:15:37 +00:00
Patrick Fic
458ec76835 Merge branch 'feature/IO-2437-CDK-make-override' into release/2023-11-10 2023-11-07 12:36:40 -08:00
Patrick Fic
682ea860fb IO-2437 override CDK make model on update. 2023-11-07 12:36:30 -08:00
Patrick Fic
99977934e7 IO-2429 Remove CIECA information on duplication. 2023-11-07 09:24:21 -08:00
Patrick Fic
3e05b21c90 IO-2426 Add FCM Cache update for conversation aggregate count. 2023-11-07 08:55:59 -08:00
Patrick Fic
4e1dd52bea IO-2332 filter insurance company name on convert. 2023-11-06 15:07:26 -08:00
Patrick Fic
f6bcc743d8 IO-2330 Remove phone validation for vendor sav.e 2023-11-06 15:04:01 -08:00
Allan Carr
d747594e39 Merged in release/2023-11-03 (pull request #1039)
Release/2023 11 03
2023-11-02 22:47:29 +00:00
Allan Carr
a33bfedbb8 Merged in feature/2023-10-27 (pull request #1034)
Feature/2023 10 27
2023-10-27 15:24:30 +00:00
Allan Carr
5da34cbeac Merged in release/2023-10-20 (pull request #1027)
Release/2023 10 20

Approved-by: Patrick Fic
2023-10-20 15:37:26 +00:00
Allan Carr
34b4baac3d Merged in 2023-09-29 (pull request #1006)
IO-1559 Adjust count object to new field tag
2023-10-12 21:53:29 +00:00
Allan Carr
6b4709b76b Merged in 2023-09-29 (pull request #1003)
2023 09 29

Approved-by: Patrick Fic
2023-10-12 19:41:37 +00:00
Allan Carr
4513acc640 Merged in release/2023-09-23 (pull request #991)
IO-2408 Remove unneeded library
2023-09-22 18:50:44 +00:00
Allan Carr
f1aa7944a3 Merged in release/2023-09-23 (pull request #989)
IO-2408 Use bodyshop.timezone instead of UTCOffset in Speedprint
2023-09-22 18:33:50 +00:00
Allan Carr
4313cf471f Merged in release/2023-09-23 (pull request #987)
Release/2023 09 23
2023-09-22 15:27:51 +00:00
Patrick Fic
171c0b2b5a Merged in release/2023-09-15 (pull request #979)
Refactor payments for intellipay.
2023-09-15 17:39:16 +00:00
Allan Carr
fd4820336f Merged in release/2023-09-15 (pull request #977)
IO-2395 Adjust Payment Number Label
2023-09-15 16:14:40 +00:00
Allan Carr
46840266ee Merged in release/2023-09-15 (pull request #975)
Release/2023 09 15
2023-09-15 16:05:02 +00:00
Allan Carr
82a0d287d6 Merged in release/2023-09-01 (pull request #970)
IO-2391 Remote IP comment out till proxy for X-Forwarded-For can be figured out from AWS Load balancer
2023-09-08 20:17:48 +00:00
Allan Carr
4de604ef7c Merged in release/2023-09-01 (pull request #968)
IO-2368 Move Cache update to function and just pass in keys array
2023-09-08 17:18:06 +00:00
Allan Carr
ec2c26ca69 Merged in release/2023-09-01 (pull request #962)
Release/2023 09 01

Approved-by: Patrick Fic
2023-09-08 01:35:06 +00:00
Allan Carr
026ce853e2 Merged in release/2023-08-25 (pull request #952)
Release/2023 08 25
2023-08-25 18:09:40 +00:00
Patrick Fic
720b7f891b Merged in release/2023-08-25 (pull request #951)
Release/2023 08 25
2023-08-25 16:46:10 +00:00
Allan Carr
b5332458ec Merged in release/2023-08-18 (pull request #936)
Release/2023 08 18
2023-08-18 21:00:11 +00:00
Allan Carr
3c7b16412b Merged in release/2023-08-11 (pull request #929)
IO-2325 Shift Clock Created By
2023-08-11 16:05:39 +00:00
Allan Carr
a454c57bc9 Merged in release/2023-08-11 (pull request #927)
Release/2023 08 11
2023-08-10 19:07:49 +00:00
Allan Carr
86ff7cbc69 Merged in release/2023-08-04 (pull request #919)
Release/2023 08 04
2023-08-04 17:36:26 +00:00
Allan Carr
fbfdbc903c Merged in release/2023-08-04 (pull request #917)
IO-2370 Work In Progress Jobs
2023-08-02 23:38:22 +00:00
Allan Carr
9e64fdc985 Merged in release/2023-07-28 (pull request #912)
Release/2023 07 28
2023-07-28 20:01:26 +00:00
Allan Carr
d7c23297ab Merged in release/2023-07-28 (pull request #907)
Release/2023 07 28
2023-07-26 23:45:22 +00:00
Allan Carr
f6e095e0a6 Merged in release/2023-07-28 (pull request #905)
IO-2356 Auto CC for Parts Return
2023-07-24 22:44:46 +00:00
Allan Carr
d7ec2e717c Merged in release/2023-07-28 (pull request #903)
Release/2023 07 28
2023-07-24 20:02:19 +00:00
Allan Carr
35fd74d3fe Merged in release/2023-07-21 (pull request #900)
Release/2023 07 21
2023-07-21 17:09:31 +00:00
Patrick Fic
8325e2d9cf Merged in release/2023-07-14 (pull request #892)
IO-2349 Change control number for AP to allow RO.
2023-07-14 23:14:34 +00:00
Allan Carr
cc3c1242f5 Merged in release/2023-07-14 (pull request #889)
IO-2170 Job Status change on Job Clock Out
2023-07-12 17:40:32 +00:00
Patrick Fic
b2f4a5539c Merged in feature/IO-2349-pbs-ap-cogs-wip (pull request #886)
IO-2349 Allow PBS AP Posting to WIP
2023-07-12 16:39:01 +00:00
29 changed files with 27335 additions and 2398 deletions

4
.gitignore vendored
View File

@@ -117,4 +117,6 @@ logs/oAuthClient-log.log
.node-persist/**
/*.env.*
/*.env.*
.idea/*
.idea

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
@@ -364,6 +364,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>unblock</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>viewjob</name>
<definition_loaded>false</definition_loaded>
@@ -17755,6 +17776,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>reports</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>required</name>
<definition_loaded>false</definition_loaded>
@@ -19472,6 +19514,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>paymentnum</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>paymenttype</name>
<definition_loaded>false</definition_loaded>
@@ -24075,6 +24138,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>dms_model_override</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>dms_unsold</name>
<definition_loaded>false</definition_loaded>
@@ -43260,6 +43344,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>hours_sold_detail_closed_estimator</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>hours_sold_detail_closed_ins_co</name>
<definition_loaded>false</definition_loaded>
@@ -43344,6 +43449,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>hours_sold_detail_open_estimator</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>hours_sold_detail_open_ins_co</name>
<definition_loaded>false</definition_loaded>
@@ -43428,6 +43554,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>hours_sold_summary_closed_estimator</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>hours_sold_summary_closed_ins_co</name>
<definition_loaded>false</definition_loaded>
@@ -43512,6 +43659,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>hours_sold_summary_open_estimator</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>hours_sold_summary_open_ins_co</name>
<definition_loaded>false</definition_loaded>
@@ -43848,6 +44016,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>open_orders_referral</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>open_orders_specific_csr</name>
<definition_loaded>false</definition_loaded>
@@ -46227,6 +46416,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>created_by</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>date</name>
<definition_loaded>false</definition_loaded>

24522
client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
"@apollo/client": "^3.7.9",
"@asseinfo/react-kanban": "^2.2.0",
"@craco/craco": "^7.0.0",
"@fingerprintjs/fingerprintjs": "^3.3.3",
"@fingerprintjs/fingerprintjs": "^3.4.2",
"@jsreport/browser-client": "^3.1.0",
"@sentry/react": "^7.40.0",
"@sentry/tracing": "^7.40.0",

View File

@@ -2,10 +2,10 @@ import { useQuery } from "@apollo/client";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import ContractJobsComponent from "./contract-jobs.component";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -15,6 +15,7 @@ export function ContractJobsContainer({ selectedJobState, bodyshop }) {
const { loading, error, data } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open"],
isConverted: true,
},
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",

View File

@@ -4,14 +4,14 @@ import queryString from "query-string";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Link, useHistory, useLocation } from "react-router-dom";
import { setModalContext } from "../../redux/modals/modals.actions";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters";
import ContractsFindModalContainer from "../contracts-find-modal/contracts-find-modal.container";
import { setModalContext } from "../../redux/modals/modals.actions";
import moment from "moment";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import moment from "moment";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({

View File

@@ -34,6 +34,18 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
{/* <FormFieldsChanged form={form} /> */}
<LayoutFormRow header={t("courtesycars.labels.vehicle")}>
<Form.Item
label={t("courtesycars.fields.year")}
name="year"
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("courtesycars.fields.make")}
name="make"
@@ -58,18 +70,6 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
>
<Input />
</Form.Item>
<Form.Item
label={t("courtesycars.fields.year")}
name="year"
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("courtesycars.fields.plate")}
name="plate"
@@ -118,7 +118,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
},
]}
>
<InputNumber precision={0} />
<InputNumber min={0} precision={0} />
</Form.Item>
<Form.Item
label={t("courtesycars.fields.fleetnumber")}
@@ -213,49 +213,24 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
>
<CourtesyCarStatus />
</Form.Item>
<Form.Item
label={t("courtesycars.fields.nextservicekm")}
name="nextservicekm"
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<InputNumber />
</Form.Item>
<div>
<Form.Item
label={t("courtesycars.fields.nextservicedate")}
name="nextservicedate"
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
label={t("courtesycars.fields.nextservicekm")}
name="nextservicekm"
>
<FormDatePicker />
<InputNumber min={0} precision={0} />
</Form.Item>
<Form.Item
shouldUpdate={(p, c) =>
p.mileage !== c.mileage ||
p.nextservicedate !== c.nextservicedate ||
p.nextservicekm !== c.nextservicekm
p.mileage !== c.mileage || p.nextservicekm !== c.nextservicekm
}
>
{() => {
const nextservicedate = form.getFieldValue("nextservicedate");
const nextservicekm = form.getFieldValue("nextservicekm");
const mileageOver =
nextservicekm <= form.getFieldValue("mileage");
const dueForService =
nextservicedate && moment(nextservicedate).isBefore(moment());
if (mileageOver || dueForService)
if (mileageOver)
return (
<Space direction="vertical" style={{ color: "tomato" }}>
<span>
@@ -263,6 +238,36 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
{t("contracts.labels.cardueforservice")}
</span>
<span>{`${nextservicekm} km`}</span>
</Space>
);
return <></>;
}}
</Form.Item>
</div>
<div>
<Form.Item
label={t("courtesycars.fields.nextservicedate")}
name="nextservicedate"
>
<FormDatePicker />
</Form.Item>
<Form.Item
shouldUpdate={(p, c) => p.nextservicedate !== c.nextservicedate}
>
{() => {
const nextservicedate = form.getFieldValue("nextservicedate");
const dueForService =
nextservicedate &&
moment(nextservicedate).endOf("day").isSameOrBefore(moment());
if (dueForService)
return (
<Space direction="vertical" style={{ color: "tomato" }}>
<span>
<WarningFilled style={{ marginRight: ".3rem" }} />
{t("contracts.labels.cardueforservice")}
</span>
<span>
<DateFormatter>{nextservicedate}</DateFormatter>
</span>
@@ -283,12 +288,6 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
<Form.Item
label={t("courtesycars.fields.registrationexpires")}
name="registrationexpires"
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<FormDatePicker />
</Form.Item>
@@ -300,7 +299,8 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
{() => {
const expires = form.getFieldValue("registrationexpires");
const dateover = expires && moment(expires).isBefore(moment());
const dateover =
expires && moment(expires).endOf("day").isBefore(moment());
if (dateover)
return (
@@ -330,14 +330,13 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
<FormDatePicker />
</Form.Item>
<Form.Item
shouldUpdate={(p, c) =>
p.insuranceexpires !== c.insuranceexpires
}
shouldUpdate={(p, c) => p.insuranceexpires !== c.insuranceexpires}
>
{() => {
const expires = form.getFieldValue("insuranceexpires");
const dateover = expires && moment(expires).isBefore(moment());
const dateover =
expires && moment(expires).endOf("day").isBefore(moment());
if (dateover)
return (

View File

@@ -174,6 +174,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
(c.year || "").toLowerCase().includes(searchText.toLowerCase()) ||
(c.make || "").toLowerCase().includes(searchText.toLowerCase()) ||
(c.model || "").toLowerCase().includes(searchText.toLowerCase()) ||
(c.plate || "").toLowerCase().includes(searchText.toLowerCase()) ||
(t(c.status) || "").toLowerCase().includes(searchText.toLowerCase())
)
: courtesycars;

View File

@@ -191,6 +191,13 @@ export function DmsPostForm({ bodyshop, socket, job, logsRef }) {
>
<Switch />
</Form.Item>
<Form.Item
name="dms_model_override"
label={t("jobs.fields.dms.dms_model_override")}
initialValue={false}
>
<Switch />
</Form.Item>
</Space>
</div>
)}

View File

@@ -54,6 +54,7 @@ export default function GlobalSearchOs() {
job.v_make_desc || ""
} ${job.v_model_desc || ""}`}</span>
<span>{`${job.clm_no || ""}`}</span>
<span>{`${job.plate_no || ""}`}</span>
</Space>
</Link>
),

View File

@@ -4,6 +4,7 @@ import {
Divider,
Dropdown,
Form,
Input,
Menu,
notification,
Popover,
@@ -34,6 +35,8 @@ import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.
import ScheduleAtChange from "./job-at-change.component";
import ScheduleEventColor from "./schedule-event.color.component";
import ScheduleEventNote from "./schedule-event.note.component";
import { useMutation } from "@apollo/client";
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -58,16 +61,44 @@ export function ScheduleEventComponent({
const [visible, setVisible] = useState(false);
const history = useHistory();
const searchParams = queryString.parse(useLocation().search);
const [updateAppointment] = useMutation(UPDATE_APPOINTMENT);
const [title, setTitle] = useState(event.title);
const blockContent = (
<div>
<Space direction="vertical" wrap>
<Input
value={title}
onChange={(e) => setTitle(e.currentTarget.value)}
onBlur={async () => {
await updateAppointment({
variables: {
appid: event.id,
app: {
title: title,
},
},
optimisticResponse: {
update_appointments: {
__typename: "appointments_mutation_response",
returning: [
{
...event,
title: title,
__typename: "appointments",
},
],
},
},
});
}}
/>
<Button
onClick={() => handleCancel({ id: event.id })}
disabled={event.arrived}
>
{t("appointments.actions.cancel")}
{t("appointments.actions.unblock")}
</Button>
</div>
</Space>
);
const popoverContent = (

View File

@@ -1,6 +1,6 @@
import { useMutation } from "@apollo/client";
import { notification, Select } from "antd";
import React, { useEffect, useState } from "react";
import { useMutation } from "@apollo/client";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -56,8 +56,10 @@ export function JobLineLocationPopup({ bodyshop, jobline, disabled }) {
<LoadingSpinner loading={loading}>
<Select
autoFocus
allowClear
dropdownMatchSelectWidth={100}
value={location}
onClear={() => setLocation(null)}
onSelect={handleChange}
onBlur={handleSave}
>

View File

@@ -108,7 +108,7 @@ export function JobsConvertButton({
},
]}
>
<Select>
<Select showSearch>
{bodyshop.md_ins_cos.map((s, i) => (
<Select.Option key={i} value={s.name}>
{s.name}

View File

@@ -27,6 +27,8 @@ export default async function DuplicateJob(
delete existingJob.id;
delete existingJob.createdat;
delete existingJob.updatedat;
delete existingJob.cieca_stl;
delete existingJob.cieca_ttl;
const newJob = {
...existingJob,
@@ -81,6 +83,8 @@ export async function CreateIouForJob(
delete existingJob.id;
delete existingJob.createdat;
delete existingJob.updatedat;
delete existingJob.cieca_stl;
delete existingJob.cieca_ttl;
const newJob = {
...existingJob,

View File

@@ -1,8 +1,8 @@
import {
BranchesOutlined,
ExclamationCircleFilled,
PauseCircleOutlined,
SyncOutlined,
BranchesOutlined,
} from "@ant-design/icons";
import { useQuery } from "@apollo/client";
import { Button, Card, Grid, Input, Space, Table, Tooltip } from "antd";
@@ -14,8 +14,8 @@ import { Link, useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { onlyUnique } from "../../utils/arrayHelper";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { onlyUnique } from "../../utils/arrayHelper";
import { alphaSort } from "../../utils/sorters";
import AlertComponent from "../alert/alert.component";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
@@ -46,6 +46,7 @@ export function JobsReadyList({ bodyshop }) {
const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: readyStatuses,
isConverted: true,
},
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",

View File

@@ -25,6 +25,7 @@ export function TechLookupJobsList({ bodyshop }) {
const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"],
isConverted: true,
},
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",

View File

@@ -154,7 +154,6 @@ export function VendorsFormComponent({
label={t("vendors.fields.phone")}
name="phone"
rules={[
{ required: true, message: t("general.validation.required") },
({ getFieldValue }) =>
PhoneItemFormatterValidation(getFieldValue, "phone"),
]}

View File

@@ -1,9 +1,9 @@
import { gql } from "@apollo/client";
export const QUERY_ALL_ACTIVE_JOBS = gql`
query QUERY_ALL_ACTIVE_JOBS($statuses: [String!]!) {
query QUERY_ALL_ACTIVE_JOBS($statuses: [String!]!, $isConverted: Boolean) {
jobs(
where: { status: { _in: $statuses } }
where: { status: { _in: $statuses }, converted: { _eq: $isConverted } }
order_by: { created_at: desc }
) {
iouparent
@@ -432,7 +432,6 @@ export const QUERY_JOB_COSTING_DETAILS = gql`
status
ca_bc_pvrt
ca_customer_gst
joblines(where: { removed: { _eq: false } }) {
id
unq_seq
@@ -1001,7 +1000,6 @@ export const QUERY_TECH_JOB_DETAILS = gql`
actual_completion
actual_delivery
actual_in
id
ins_co_nm
clm_no
@@ -1586,7 +1584,6 @@ export const QUERY_ALL_JOB_FIELDS = gql`
clm_title
clm_total
clm_zip
cust_pr
ded_amt
ded_status
@@ -1669,7 +1666,6 @@ export const QUERY_ALL_JOB_FIELDS = gql`
parts_tax_rates
pay_amt
pay_chknm
pay_type
payee_nms
plate_no
@@ -2077,6 +2073,7 @@ export const QUERY_JOB_EXPORT_DMS = gql`
}
}
`;
export const QUERY_RELATED_ROS = gql`
query QUERY_RELATED_ROS($jobid: uuid!) {
relatedjobs(
@@ -2098,6 +2095,7 @@ export const QUERY_RELATED_ROS = gql`
}
}
`;
export const INSERT_RELATED_ROS = gql`
mutation INSERT_RELATED_ROS($relationship: relatedjobs_insert_input!) {
insert_relatedjobs_one(object: $relationship) {
@@ -2115,6 +2113,7 @@ export const INSERT_RELATED_ROS = gql`
}
}
`;
export const DELETE_RELATED_RO = gql`
mutation DELETE_RELATED_RO($relationshipid: uuid!) {
delete_relatedjobs_by_pk(id: $relationshipid) {
@@ -2122,6 +2121,7 @@ export const DELETE_RELATED_RO = gql`
}
}
`;
export const GET_JOB_LINE_ORDERS = gql`
query GET_JOB_LINE_ORDERS($joblineid: uuid!) {
billlines(where: { joblineid: { _eq: $joblineid } }) {

View File

@@ -1,15 +1,17 @@
import Fingerprint2 from "@fingerprintjs/fingerprintjs";
import FingerprintJS from "@fingerprintjs/fingerprintjs";
import * as Sentry from "@sentry/browser";
import { notification } from "antd";
import axios from "axios";
import { setUserId, setUserProperties } from "firebase/analytics";
import {
checkActionCode,
confirmPasswordReset,
sendPasswordResetEmail,
signInWithEmailAndPassword,
signOut,
sendPasswordResetEmail,
} from "firebase/auth";
import { doc } from "firebase/firestore";
import { doc, getDoc, setDoc } from "firebase/firestore";
import { getToken } from "firebase/messaging";
import i18next from "i18next";
import LogRocket from "logrocket";
import { all, call, delay, put, select, takeLatest } from "redux-saga/effects";
@@ -20,6 +22,7 @@ import {
firestore,
getCurrentUser,
logImEXEvent,
messaging,
updateCurrentUser,
} from "../../firebase/firebase.utils";
import {
@@ -28,6 +31,7 @@ import {
sendPasswordResetSuccess,
setAuthlevel,
setInstanceConflict,
setInstanceId,
setLocalFingerprint,
signInFailure,
signInSuccess,
@@ -39,9 +43,8 @@ import {
validatePasswordResetSuccess,
} from "./user.actions";
import UserActionTypes from "./user.types";
import axios from "axios";
import { messaging } from "../../firebase/firebase.utils";
import { getToken } from "firebase/messaging";
const fpPromise = FingerprintJS.load();
export function* onEmailSignInStart() {
yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
@@ -148,17 +151,15 @@ export function* setInstanceIdSaga({ payload: uid }) {
try {
const userInstanceRef = doc(firestore, `userInstance/${uid}`);
const fingerprint = Fingerprint2.x64hash128(
(yield Fingerprint2.getPromise({})).map((c) => c.value).join(""),
31
);
yield userInstanceRef.set({
// Get the visitor identifier when you need it.
const fp = yield fpPromise;
const result = yield fp.get();
yield setDoc(userInstanceRef, {
timestamp: new Date(),
fingerprint,
fingerprint: result.visitorId,
});
yield put(setLocalFingerprint(fingerprint));
yield put(setLocalFingerprint(result.visitorId));
yield delay(5 * 60 * 1000);
if (process.env.NODE_ENV === "production") yield put(checkInstanceId(uid));
} catch (error) {
@@ -171,11 +172,9 @@ export function* onCheckInstanceId() {
}
export function* checkInstanceIdSaga({ payload: uid }) {
try {
const userInstanceRef = doc(firestore, `userInstance/${uid}`);
const snapshot = yield userInstanceRef.get();
const snapshot = yield getDoc(doc(firestore, `userInstance/${uid}`));
let fingerprint = yield select((state) => state.user.fingerprint);
yield put(setInstanceConflict());
if (snapshot.data().fingerprint === fingerprint) {
yield delay(5 * 60 * 1000);
yield put(checkInstanceId(uid));
@@ -215,7 +214,6 @@ export function* signInSuccessSaga({ payload }) {
console.log("Error updating Crisp settings.", error);
}
// if (!payload.email.includes("@imex.")) yield put(setInstanceId(payload.uid));
setUserId(analytics, payload.email);
setUserProperties(analytics, payload);
yield logImEXEvent("redux_sign_in_success");
@@ -289,6 +287,14 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
: { validemail: false }
)
);
if (payload.features.singleDeviceOnly) {
const user = yield select((state) => state.user.currentUser);
if (!(user.email.includes("@imex.") || user.email.includes("@rome.")))
yield put(setInstanceId(user.uid));
}
try {
window.$crisp.push(["set", "user:company", [payload.shopname]]);
if (authRecord[0] && authRecord[0].user.validemail) {

View File

@@ -27,6 +27,7 @@
"preview": "Preview",
"reschedule": "Reschedule",
"sendreminder": "Send Reminder",
"unblock": "Unblock",
"viewjob": "View Job"
},
"errors": {
@@ -1463,6 +1464,7 @@
"cost_dms_acctnumber": "Cost DMS Acct #",
"dms_make": "DMS Make",
"dms_model": "DMS Model",
"dms_model_override": "Override DMS Make/Model",
"dms_unsold": "New, Unsold Vehicle",
"dms_wip_acctnumber": "Cost WIP DMS Acct #",
"id": "DMS ID",

View File

@@ -27,6 +27,7 @@
"preview": "",
"reschedule": "Reprogramar",
"sendreminder": "",
"unblock": "",
"viewjob": "Ver trabajo"
},
"errors": {
@@ -1463,6 +1464,7 @@
"cost_dms_acctnumber": "",
"dms_make": "",
"dms_model": "",
"dms_model_override": "",
"dms_unsold": "",
"dms_wip_acctnumber": "",
"id": "",

View File

@@ -27,6 +27,7 @@
"preview": "",
"reschedule": "Replanifier",
"sendreminder": "",
"unblock": "",
"viewjob": "Voir le travail"
},
"errors": {
@@ -1463,6 +1464,7 @@
"cost_dms_acctnumber": "",
"dms_make": "",
"dms_model": "",
"dms_model_override": "",
"dms_unsold": "",
"dms_wip_acctnumber": "",
"id": "",

View File

@@ -12,6 +12,13 @@ export default async function FcmHandler({ client, payload }) {
},
},
});
client.cache.modify({
fields: {
messages_aggregate(cached) {
return { aggregate: { count: cached.aggregate.count + 1 } };
},
},
});
break;
case "messaging-outbound":
client.cache.modify({
@@ -30,6 +37,7 @@ export default async function FcmHandler({ client, payload }) {
});
break;
case "messaging-mark-conversation-read":
let previousUnreadCount = 0;
client.cache.modify({
id: client.cache.identify({
__typename: "conversations",
@@ -37,10 +45,22 @@ export default async function FcmHandler({ client, payload }) {
}),
fields: {
messages_aggregate(cached) {
previousUnreadCount = cached.aggregate.count;
return { aggregate: { count: 0 } };
},
},
});
client.cache.modify({
fields: {
messages_aggregate(cached) {
return {
aggregate: {
count: cached.aggregate.count - previousUnreadCount,
},
};
},
},
});
break;
default:
console.log("No payload type set.");

File diff suppressed because it is too large Load Diff

View File

@@ -4089,6 +4089,7 @@
- name: event-secret
value_from_env: EVENT_SECRET
request_transform:
method: POST
query_params: {}
template_engine: Kriti
url: '{{$base_url}}/job/statustransition'

View File

@@ -0,0 +1,38 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- CREATE OR REPLACE FUNCTION public.search_cccontracts(search text)
-- RETURNS SETOF cccontracts
-- LANGUAGE plpgsql
-- STABLE
-- AS $function$
-- BEGIN
-- IF search = '' THEN
-- RETURN query
-- SELECT
-- *
-- FROM
-- cccontracts c;
-- ELSE
-- RETURN query
-- SELECT
-- contracts.*
-- FROM
-- courtesycars cars,
-- jobs jobs,
-- cccontracts contracts
-- WHERE (jobs.ro_number ILIKE '%' || search || '%'
-- OR jobs.ownr_fn ILIKE '%' || search || '%'
-- OR jobs.ownr_ln ILIKE '%' || search || '%'
-- OR jobs.ownr_co_nm ILIKE '%' || search || '%'
-- OR (cast(contracts.agreementnumber as text)) ILIKE '%' || search || '%'
-- OR contracts.driver_fn ILIKE '%' || search || '%'
-- OR contracts.driver_ln ILIKE '%' || search || '%'
-- OR cars.fleetnumber ILIKE '%' || search || '%'
-- OR cars.make ILIKE '%' || search || '%'
-- OR cars.model ILIKE '%' || search || '%'
-- OR cars.plate ILIKE '%' || search || '%')
-- AND contracts.jobid = jobs.id
-- AND contracts.courtesycarid = cars.id;
-- END IF;
-- END
-- $function$;

View File

@@ -0,0 +1,36 @@
CREATE OR REPLACE FUNCTION public.search_cccontracts(search text)
RETURNS SETOF cccontracts
LANGUAGE plpgsql
STABLE
AS $function$
BEGIN
IF search = '' THEN
RETURN query
SELECT
*
FROM
cccontracts c;
ELSE
RETURN query
SELECT
contracts.*
FROM
courtesycars cars,
jobs jobs,
cccontracts contracts
WHERE (jobs.ro_number ILIKE '%' || search || '%'
OR jobs.ownr_fn ILIKE '%' || search || '%'
OR jobs.ownr_ln ILIKE '%' || search || '%'
OR jobs.ownr_co_nm ILIKE '%' || search || '%'
OR (cast(contracts.agreementnumber as text)) ILIKE '%' || search || '%'
OR contracts.driver_fn ILIKE '%' || search || '%'
OR contracts.driver_ln ILIKE '%' || search || '%'
OR cars.fleetnumber ILIKE '%' || search || '%'
OR cars.make ILIKE '%' || search || '%'
OR cars.model ILIKE '%' || search || '%'
OR cars.plate ILIKE '%' || search || '%')
AND contracts.jobid = jobs.id
AND contracts.courtesycarid = cars.id;
END IF;
END
$function$;

View File

@@ -879,6 +879,12 @@ async function UpdateDmsVehicle(socket) {
},
vehicle: {
...socket.DMSVeh.vehicle,
...(socket.txEnvelope.dms_model_override
? {
make: socket.txEnvelope.dms_make,
modelAbrev: socket.txEnvelope.dms_model,
}
: {}),
deliveryDate:
socket.txEnvelope.dms_unsold === true
? ""

View File

@@ -19,6 +19,7 @@ const aws4 = require("aws4");
const { gql } = require("graphql-request");
var host = process.env.OPEN_SEARCH_HOST;
const createAwsConnector = (credentials, region) => {
class AmazonConnection extends Connection {
buildRequestObject(params) {
@@ -207,13 +208,15 @@ async function OpenSearchUpdateHandler(req, res) {
}
}
async function OpensearchSearchHandler(req, res) {
async function OpenSearchSearchHandler(req, res) {
try {
const { search, bodyshopid, index } = req.body;
if (!req.user) {
res.sendStatus(401);
return;
}
logger.log("os-search", "DEBUG", req.user.email, null, {
search,
});
@@ -273,7 +276,7 @@ async function OpensearchSearchHandler(req, res) {
{
query_string: {
query: `*${search}*`,
// Weighted Fields
fields: [
"*ro_number^20",
"*clm_no^14",
@@ -320,4 +323,4 @@ async function OpensearchSearchHandler(req, res) {
}
exports.handler = OpenSearchUpdateHandler;
exports.search = OpensearchSearchHandler;
exports.search = OpenSearchSearchHandler;