From b0d077e104a4c23587ce7ed4528b7493927125b9 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Thu, 28 Dec 2023 10:12:59 -0800 Subject: [PATCH 1/8] IO-2514 Production Board Estimators --- .../production-list-columns.data.js | 29 ++++++++++++++++++- client/src/graphql/jobs.queries.js | 2 ++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/client/src/components/production-list-columns/production-list-columns.data.js b/client/src/components/production-list-columns/production-list-columns.data.js index a93e0f3e6..a7f1ead6e 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.js +++ b/client/src/components/production-list-columns/production-list-columns.data.js @@ -1,4 +1,4 @@ -import { PauseCircleOutlined, BranchesOutlined } from "@ant-design/icons"; +import { BranchesOutlined, PauseCircleOutlined } from "@ant-design/icons"; import { Space, Tooltip } from "antd"; import i18n from "i18next"; import moment from "moment"; @@ -536,6 +536,33 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => { ), }, + { + title: i18n.t("jobs.labels.estimator"), + dataIndex: "estimator", + key: "estimator", + sorter: (a, b) => + alphaSort( + `${a.est_ct_fn || ""} ${a.est_ct_ln || ""}`.trim(), + `${b.est_ct_fn || ""} ${b.est_ct_ln || ""}`.trim() + ), + sortOrder: + state.sortedInfo.columnKey === "estimator" && state.sortedInfo.order, + filters: + (bodyshop && + bodyshop.md_estimators.map((s) => { + return { + text: `${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim(), + value: [`${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim()], + }; + })) || + [], + onFilter: (value, record) => + value.includes( + `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim() + ), + render: (text, record) => + `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim(), + }, //Added as a place holder for St Claude. Not implemented as it requires another join for a field used by only 1 client. // { diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index b18673de6..fbeb8740d 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -364,6 +364,8 @@ export const QUERY_JOBS_IN_PRODUCTION = gql` employee_refinish employee_prep employee_csr + est_ct_fn + est_ct_ln suspended date_repairstarted joblines_status { From 823f07409aca7584a804c3118cf3e695209b58df Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 29 Dec 2023 16:03:40 -0800 Subject: [PATCH 2/8] IO-2517 All Courtesy Car Warning Indicator --- .../courtesy-cars-list/courtesy-cars-list.component.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx index 7c4b25534..3be08fff2 100644 --- a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx +++ b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx @@ -74,10 +74,10 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) { render: (text, record) => { const { nextservicedate, nextservicekm, mileage } = record; - const mileageOver = nextservicekm <= mileage; + const mileageOver = nextservicekm ? nextservicekm <= mileage : false; const dueForService = - nextservicedate && moment(nextservicedate).isBefore(moment()); + nextservicedate && moment(nextservicedate).isSameOrBefore(moment()); return ( From bfe94e3068c06d9b256269439ae275f2c6cb3f90 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 29 Dec 2023 16:17:37 -0800 Subject: [PATCH 3/8] IO-2517 Add same check within C/C form --- .../courtesy-car-form/courtesy-car-form.component.jsx | 10 ++++------ .../courtesy-cars-list.component.jsx | 3 ++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx index a64cb8a2a..f9a32dfee 100644 --- a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx +++ b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx @@ -214,10 +214,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) { > - +
@@ -234,8 +231,9 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) { > {() => { const nextservicekm = form.getFieldValue("nextservicekm"); - const mileageOver = - nextservicekm && nextservicekm <= form.getFieldValue("mileage"); + const mileageOver = nextservicekm + ? nextservicekm <= form.getFieldValue("mileage") + : false; if (mileageOver) return ( diff --git a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx index 3be08fff2..2c992990c 100644 --- a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx +++ b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx @@ -77,7 +77,8 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) { const mileageOver = nextservicekm ? nextservicekm <= mileage : false; const dueForService = - nextservicedate && moment(nextservicedate).isSameOrBefore(moment()); + nextservicedate && + moment(nextservicedate).endOf("day").isSameOrBefore(moment()); return ( From ded798fdf1fc8d01b99f18958cf4a6fbc5649fbd Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 29 Dec 2023 16:37:34 -0800 Subject: [PATCH 4/8] IO-2518 Dealership Vin Warning --- .../jobs-detail-header/jobs-detail-header.component.jsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx index 30bb98560..9ae08588d 100644 --- a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx +++ b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx @@ -221,6 +221,11 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) { {`${job.v_vin || t("general.labels.na")}`} + {bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? ( + job.v_vin.length !== 17 ? ( + + ) : null + ) : null} {job.regie_number || t("general.labels.na")} From 9d3aca646b2effb73d3269b1b2f46c97af4e246f Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 3 Jan 2024 10:55:45 -0800 Subject: [PATCH 5/8] IO-2514 Production Board Estimator filter by table data --- .../production-list-columns.add.component.jsx | 7 ++-- .../production-list-columns.data.js | 16 ++++----- ...ction-list-table-view-select.component.jsx | 3 ++ .../production-list-table.component.jsx | 35 +++++++++++++++++-- 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/client/src/components/production-list-columns/production-list-columns.add.component.jsx b/client/src/components/production-list-columns/production-list-columns.add.component.jsx index 82f884673..c79e9db7f 100644 --- a/client/src/components/production-list-columns/production-list-columns.add.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.add.component.jsx @@ -1,7 +1,7 @@ -import React from "react"; import { Button, Dropdown, Menu } from "antd"; -import dataSource from "./production-list-columns.data"; +import React from "react"; import { useTranslation } from "react-i18next"; +import dataSource from "./production-list-columns.data"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -24,6 +24,7 @@ export function ProductionColumnsComponent({ columnState, technician, bodyshop, + data, tableState, }) { const [columns, setColumns] = columnState; @@ -36,6 +37,7 @@ export function ProductionColumnsComponent({ bodyshop, technician, state: tableState, + data: data, activeStatuses: bodyshop.md_ro_statuses.active_statuses, }).filter((i) => i.key === e.key), ]); @@ -46,6 +48,7 @@ export function ProductionColumnsComponent({ technician, state: tableState, activeStatuses: bodyshop.md_ro_statuses.active_statuses, + data: data, }); const menu = ( { +const r = ({ technician, state, activeStatuses, data, bodyshop }) => { return [ { title: i18n.t("jobs.actions.viewdetail"), @@ -548,14 +548,12 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => { sortOrder: state.sortedInfo.columnKey === "estimator" && state.sortedInfo.order, filters: - (bodyshop && - bodyshop.md_estimators.map((s) => { - return { - text: `${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim(), - value: [`${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim()], - }; - })) || - [], + data?.map((s) => { + return { + text: `${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim(), + value: [`${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim()], + }; + }) || [], onFilter: (value, record) => value.includes( `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim() diff --git a/client/src/components/production-list-table/production-list-table-view-select.component.jsx b/client/src/components/production-list-table/production-list-table-view-select.component.jsx index 044c75994..82086ac96 100644 --- a/client/src/components/production-list-table/production-list-table-view-select.component.jsx +++ b/client/src/components/production-list-table/production-list-table-view-select.component.jsx @@ -24,6 +24,7 @@ export function ProductionListTable({ technician, currentUser, state, + data, setColumns, setState, }) { @@ -41,6 +42,7 @@ export function ProductionListTable({ bodyshop, technician, state, + data: data, activeStatuses: bodyshop.md_ro_statuses.active_statuses, }).find((e) => e.key === k.key), width: k.width, @@ -95,6 +97,7 @@ export function ProductionListTable({ ...ProductionListColumns({ technician, state, + data: data, activeStatuses: bodyshop.md_ro_statuses.active_statuses, }).find((e) => e.key === k.key), width: k.width, 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 3ea3391d3..5257cea9d 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 @@ -10,7 +10,7 @@ import { Statistic, Table, } from "antd"; -import React, { useMemo, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import ReactDragListView from "react-drag-listview"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -79,6 +79,7 @@ export function ProductionListTable({ bodyshop, technician, state, + data: data, activeStatuses: bodyshop.md_ro_statuses.active_statuses, }).find((e) => e.key === k.key), width: k.width ?? 100, @@ -87,6 +88,33 @@ export function ProductionListTable({ [] ); + useEffect(() => { + const newColumns = + (state && + matchingColumnConfig && + matchingColumnConfig.columns.columnKeys.map((k) => { + return { + ...ProductionListColumns({ + bodyshop, + technician, + state, + data: data, + activeStatuses: bodyshop.md_ro_statuses.active_statuses, + }).find((e) => e.key === k.key), + width: k.width ?? 100, + }; + })) || + []; + setColumns(newColumns); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + //state, + matchingColumnConfig, + bodyshop, + technician, + data, + ]); //State removed from dependency array as it causes race condition when removing columns from table view and is not needed. + const handleTableChange = (pagination, filters, sorter) => { setState({ ...state, @@ -104,7 +132,8 @@ export function ProductionListTable({ const removeColumn = (e) => { const { key } = e; - setColumns(columns.filter((i) => i.key !== key)); + const newColumns = columns.filter((i) => i.key !== key); + setColumns(newColumns); }; const handleResize = @@ -227,6 +256,7 @@ export function ProductionListTable({ Date: Fri, 5 Jan 2024 08:53:17 -0800 Subject: [PATCH 6/8] Minor intellipay change. --- server/intellipay/intellipay.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 0ece0c69c..60b74c1b5 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -132,6 +132,7 @@ exports.payment_refund = async (req, res) => { exports.generate_payment_url = async (req, res) => { logger.log("intellipay-payment-url", "DEBUG", req.user?.email, null, null); const shopCredentials = await getShopCredentials(req.body.bodyshop); + try { const options = { method: "POST", @@ -139,7 +140,12 @@ exports.generate_payment_url = async (req, res) => { //TODO: Move these to environment variables/database. data: qs.stringify({ ...shopCredentials, - ...req.body, + //...req.body, + amount: Dinero({ amount: Math.round(req.body.amount * 100) }).toFormat( + "0.00" + ), + account: req.body.account, + invoice: req.body.invoice, createshorturl: true, //The postback URL is set at the CP teller global terminal settings page. }), From c0dab92d0ef6d0f2f7b51129d556edd2aae9d2c1 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 5 Jan 2024 12:01:47 -0800 Subject: [PATCH 7/8] IO-2522 Load Level Table Change --- hasura/metadata/tables.yaml | 33 ++++++++++--------- .../down.sql | 4 +++ .../up.sql | 2 ++ .../down.sql | 3 ++ .../up.sql | 1 + .../down.sql | 4 +++ .../up.sql | 2 ++ 7 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/down.sql create mode 100644 hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/up.sql create mode 100644 hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/down.sql create mode 100644 hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/up.sql create mode 100644 hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/down.sql create mode 100644 hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/up.sql diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index 216ac8c48..9867b3f8e 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -2023,24 +2023,24 @@ - active: _eq: true columns: - - labor_rates - - percentage - created_at - - updated_at - employeeid - id + - labor_rates + - percentage - teamid + - updated_at select_permissions: - role: user permission: columns: - - labor_rates - - percentage - created_at - - updated_at - employeeid - id + - labor_rates + - percentage - teamid + - updated_at filter: employee_team: bodyshop: @@ -2055,13 +2055,13 @@ - role: user permission: columns: - - labor_rates - - percentage - created_at - - updated_at - employeeid - id + - labor_rates + - percentage - teamid + - updated_at filter: employee_team: bodyshop: @@ -2123,21 +2123,23 @@ _eq: true columns: - active - - name - - created_at - - updated_at - bodyshopid + - created_at - id + - max_load + - name + - updated_at select_permissions: - role: user permission: columns: - active - - name - - created_at - - updated_at - bodyshopid + - created_at - id + - max_load + - name + - updated_at filter: bodyshop: associations: @@ -2153,6 +2155,7 @@ columns: - active - bodyshopid + - max_load - name - updated_at filter: diff --git a/hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/down.sql b/hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/down.sql new file mode 100644 index 000000000..8df675f00 --- /dev/null +++ b/hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."employee_team_members" add column "max_load" numeric +-- not null default '10000'; diff --git a/hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/up.sql b/hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/up.sql new file mode 100644 index 000000000..7b49a8dcd --- /dev/null +++ b/hasura/migrations/1704401074280_alter_table_public_employee_team_members_add_column_max_load/up.sql @@ -0,0 +1,2 @@ +alter table "public"."employee_team_members" add column "max_load" numeric + not null default '10000'; diff --git a/hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/down.sql b/hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/down.sql new file mode 100644 index 000000000..a869e6890 --- /dev/null +++ b/hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/down.sql @@ -0,0 +1,3 @@ +alter table "public"."employee_team_members" alter column "max_load" set default '10000'::numeric; +alter table "public"."employee_team_members" alter column "max_load" drop not null; +alter table "public"."employee_team_members" add column "max_load" numeric; diff --git a/hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/up.sql b/hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/up.sql new file mode 100644 index 000000000..18bf59cf3 --- /dev/null +++ b/hasura/migrations/1704403786392_alter_table_public_employee_team_members_drop_column_max_load/up.sql @@ -0,0 +1 @@ +alter table "public"."employee_team_members" drop column "max_load" cascade; diff --git a/hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/down.sql b/hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/down.sql new file mode 100644 index 000000000..58a0f9b6d --- /dev/null +++ b/hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."employee_teams" add column "max_load" numeric +-- not null default '10000'; diff --git a/hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/up.sql b/hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/up.sql new file mode 100644 index 000000000..c55ba33d0 --- /dev/null +++ b/hasura/migrations/1704403846373_alter_table_public_employee_teams_add_column_max_load/up.sql @@ -0,0 +1,2 @@ +alter table "public"."employee_teams" add column "max_load" numeric + not null default '10000'; From fe3698980d5c81651288ed3aad1807366e5e7fa2 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 5 Jan 2024 13:09:15 -0800 Subject: [PATCH 8/8] IO-2514 Only Unique items in Menu --- .../production-list-columns.data.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/client/src/components/production-list-columns/production-list-columns.data.js b/client/src/components/production-list-columns/production-list-columns.data.js index d43433540..8e584aa2e 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.js +++ b/client/src/components/production-list-columns/production-list-columns.data.js @@ -6,6 +6,7 @@ import { Link } from "react-router-dom"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { TimeFormatter } from "../../utils/DateFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter"; +import { onlyUnique } from "../../utils/arrayHelper"; import { alphaSort, dateSort, statusSort } from "../../utils/sorters"; import JobAltTransportChange from "../job-at-change/job-at-change.component"; import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component"; @@ -548,12 +549,17 @@ const r = ({ technician, state, activeStatuses, data, bodyshop }) => { sortOrder: state.sortedInfo.columnKey === "estimator" && state.sortedInfo.order, filters: - data?.map((s) => { - return { - text: `${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim(), - value: [`${s.est_ct_fn || ""} ${s.est_ct_ln || ""}`.trim()], - }; - }) || [], + (data && + data + .map((j) => `${j.est_ct_fn || ""} ${j.est_ct_ln || ""}`.trim()) + .filter(onlyUnique) + .map((s) => { + return { + text: s || "N/A", + value: [s], + }; + })) || + [], onFilter: (value, record) => value.includes( `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim()