From 3891fbefdf59f8b436c675ff295ed254710c6281 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Tue, 14 Mar 2023 08:41:26 -0700 Subject: [PATCH] IO-2215 Critical parts scanning --- .../job-detail-lines/job-lines.component.jsx | 7 +- .../shop-info/shop-info.component.jsx | 4 + .../shop-info/shop-info.parts-scan.jsx | 81 +++++++++++++++++++ client/src/graphql/bodyshop.queries.js | 2 + client/src/graphql/jobs.queries.js | 1 + hasura/metadata/tables.yaml | 25 ++++++ .../down.sql | 4 + .../up.sql | 2 + .../down.sql | 4 + .../up.sql | 2 + server/graphql-client/queries.js | 26 +++++- server/parts-scan/parts-scan.js | 59 ++++++++++++++ 12 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 client/src/components/shop-info/shop-info.parts-scan.jsx create mode 100644 hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/down.sql create mode 100644 hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/up.sql create mode 100644 hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/down.sql create mode 100644 hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/up.sql create mode 100644 server/parts-scan/parts-scan.js diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index 5097f668c..66dcc78d5 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -103,7 +103,12 @@ export function JobLinesComponent({ fixed: "left", key: "line_desc", sorter: (a, b) => alphaSort(a.line_desc, b.line_desc), - onCell: (record) => ({ className: record.manual_line && "job-line-manual" }), + onCell: (record) => ({ + className: record.manual_line && "job-line-manual", + style: { + ...(record.critical ? { boxShadow: " -.5em 0 0 #FFC107" } : {}), + }, + }), sortOrder: state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order, ellipsis: true, diff --git a/client/src/components/shop-info/shop-info.component.jsx b/client/src/components/shop-info/shop-info.component.jsx index df6410e6c..d166ae5f1 100644 --- a/client/src/components/shop-info/shop-info.component.jsx +++ b/client/src/components/shop-info/shop-info.component.jsx @@ -8,6 +8,7 @@ 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"; @@ -71,6 +72,9 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) { + + + ); diff --git a/client/src/components/shop-info/shop-info.parts-scan.jsx b/client/src/components/shop-info/shop-info.parts-scan.jsx new file mode 100644 index 000000000..317be28f2 --- /dev/null +++ b/client/src/components/shop-info/shop-info.parts-scan.jsx @@ -0,0 +1,81 @@ +import { DeleteFilled } from "@ant-design/icons"; +import { Button, Form, Input, Space } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component"; +import LayoutFormRow from "../layout-form-row/layout-form-row.component"; + +export default function ShopInfoPartsScan({ form }) { + const { t } = useTranslation(); + + return ( +
+ + + {(fields, { add, remove, move }) => { + return ( +
+ {fields.map((field, index) => ( + + + + + + + + + + + { + remove(field.name); + }} + /> + + + + + ))} + + + +
+ ); + }} +
+
+
+ ); +} diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index f1e141434..5c718420a 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -114,6 +114,7 @@ export const QUERY_BODYSHOP = gql` localmediatoken enforce_conversion_csr md_lost_sale_reasons + md_parts_scan employees { user_email id @@ -225,6 +226,7 @@ export const UPDATE_SHOP = gql` localmediatoken enforce_conversion_csr md_lost_sale_reasons + md_parts_scan employees { id first_name diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 028a7120e..dce7aff66 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -722,6 +722,7 @@ export const GET_JOB_BY_PK = gql` ioucreated convertedtolbr ah_detail_line + critical billlines(limit: 1, order_by: { bill: { date: desc } }) { id quantity diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index b5fd3b656..9fa1b4c3d 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -796,6 +796,13 @@ table: name: owners schema: public + - name: payment_responses + using: + foreign_key_constraint_on: + column: bodyshopid + table: + name: payment_response + schema: public - name: phonebooks using: foreign_key_constraint_on: @@ -889,6 +896,7 @@ - md_order_statuses - md_parts_locations - md_parts_order_comment + - md_parts_scan - md_payment_types - md_rbac - md_referral_sources @@ -982,6 +990,7 @@ - md_order_statuses - md_parts_locations - md_parts_order_comment + - md_parts_scan - md_payment_types - md_rbac - md_referral_sources @@ -2562,6 +2571,7 @@ - convertedtolbr - convertedtolbr_data - created_at + - critical - db_hrs - db_price - db_ref @@ -2639,6 +2649,7 @@ - convertedtolbr - convertedtolbr_data - created_at + - critical - db_hrs - db_price - db_ref @@ -2903,6 +2914,13 @@ table: name: parts_orders schema: public + - name: payment_responses + using: + foreign_key_constraint_on: + column: jobid + table: + name: payment_response + schema: public - name: payments using: foreign_key_constraint_on: @@ -4575,6 +4593,13 @@ table: name: exportlog schema: public + - name: payment_responses + using: + foreign_key_constraint_on: + column: paymentid + table: + name: payment_response + schema: public insert_permissions: - role: user permission: diff --git a/hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/down.sql b/hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/down.sql new file mode 100644 index 000000000..67066918f --- /dev/null +++ b/hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/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"."bodyshops" add column "md_parts_scan" jsonb +-- not null default jsonb_build_array(); diff --git a/hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/up.sql b/hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/up.sql new file mode 100644 index 000000000..3a6527e62 --- /dev/null +++ b/hasura/migrations/1678743865758_alter_table_public_bodyshops_add_column_md_parts_scan/up.sql @@ -0,0 +1,2 @@ +alter table "public"."bodyshops" add column "md_parts_scan" jsonb + not null default jsonb_build_array(); diff --git a/hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/down.sql b/hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/down.sql new file mode 100644 index 000000000..5d1159047 --- /dev/null +++ b/hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/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"."joblines" add column "critical" boolean +-- not null default 'false'; diff --git a/hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/up.sql b/hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/up.sql new file mode 100644 index 000000000..0e7b53284 --- /dev/null +++ b/hasura/migrations/1678744973891_alter_table_public_joblines_add_column_critical/up.sql @@ -0,0 +1,2 @@ +alter table "public"."joblines" add column "critical" boolean + not null default 'false'; diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index de12f518e..e71bf2e4a 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -906,7 +906,7 @@ exports.UPDATE_JOB = ` } `; -exports.GET_JOB_BY_PK = ` query GET_JOB_BY_PK($id: uuid!) { +exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) { jobs_by_pk(id: $id) { updated_at alt_transport @@ -1719,3 +1719,27 @@ query GET_PBS_AP_ALLOCATIONS($billids: [uuid!]) { } } `; + +exports.QUERY_PARTS_SCAN = `query QUERY_PARTS_SCAN ($id: uuid!) { + jobs_by_pk(id: $id) { + bodyshop { + id + md_parts_scan + } + joblines(where: {removed: {_eq: false}}) { + id + line_desc + critical + } + } +} +`; + +exports.UPDATE_PARTS_CRITICAL = `mutation UPDATE_PARTS_CRITICAL ($IdsToMarkCritical:[uuid!]!, $jobid: uuid!){ + critical: update_joblines(where:{id:{_in:$IdsToMarkCritical}}, _set:{critical: true}){ + affected_rows + } + notcritical: update_joblines(where:{id:{_nin:$IdsToMarkCritical}, jobid: {_eq: $jobid}}, _set:{critical: false}){ + affected_rows + } +}`; diff --git a/server/parts-scan/parts-scan.js b/server/parts-scan/parts-scan.js new file mode 100644 index 000000000..d3305f9c6 --- /dev/null +++ b/server/parts-scan/parts-scan.js @@ -0,0 +1,59 @@ +const Dinero = require("dinero.js"); +const queries = require("../graphql-client/queries"); +const { job } = require("../scheduling/scheduling-job"); +const GraphQLClient = require("graphql-request").GraphQLClient; +const logger = require("../utils/logger"); +// Dinero.defaultCurrency = "USD"; +// Dinero.globalLocale = "en-CA"; + +exports.partsScan = async function (req, res) { + const BearerToken = req.headers.authorization; + const { jobid } = req.body; + logger.log("job-parts-scan", "DEBUG", req.user?.email, jobid, null); + const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, { + headers: { + Authorization: BearerToken, + }, + }); + + try { + const data = await client + .setHeaders({ Authorization: BearerToken }) + .request(queries.QUERY_PARTS_SCAN, { + id: jobid, + }); + + const IdsToMarkCritical = []; + const RegExpressions = data.jobs_by_pk.bodyshop.md_parts_scan.map( + (r) => new RegExp(r.expression, r.flags) + ); + + data.jobs_by_pk.joblines.forEach((jobline) => { + RegExpressions.forEach((rExp) => { + if (jobline.line_desc.match(rExp)) { + console.log("Critical Parts Match", jobline.line_desc, rExp); + IdsToMarkCritical.push(jobline); + } + }); + }); + + console.log(IdsToMarkCritical); + + //Mark off ids not critical and critical. + + const result = await client + .setHeaders({ Authorization: BearerToken }) + .request(queries.UPDATE_PARTS_CRITICAL, { + IdsToMarkCritical: IdsToMarkCritical.map((i) => i.id), + jobid: jobid, + }); + + res.status(200).json(result); + } catch (error) { + logger.log("job-parts-scan-error", "ERROR", req.user.email, id, { + jobid: id, + error, + }); + res.status(503).send(); + } +};