From 97f1be9d6f353b60372934a0db20a89308654810 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 28 Sep 2021 10:59:18 -0700 Subject: [PATCH 1/3] IO-1390 Resolve breaking import changes from Hasura. --- .../jobs-available-table.container.jsx | 83 ++++++++++--------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/client/src/components/jobs-available-table/jobs-available-table.container.jsx b/client/src/components/jobs-available-table/jobs-available-table.container.jsx index b4758f361..86efbfc66 100644 --- a/client/src/components/jobs-available-table/jobs-available-table.container.jsx +++ b/client/src/components/jobs-available-table/jobs-available-table.container.jsx @@ -140,16 +140,17 @@ export function JobsAvailableContainer({ : {}), }; + if (selectedOwner) { + newJob.ownerid = selectedOwner; + delete newJob.owner; + } + if (newJob.vehicleid) { + delete newJob.vehicle; + } + insertNewJob({ variables: { - job: selectedOwner - ? Object.assign( - {}, - newJob, - { owner: null }, - { ownerid: selectedOwner } - ) - : newJob, + job: newJob, }, }) .then((r) => { @@ -199,11 +200,10 @@ export function JobsAvailableContainer({ message: t("jobs.errors.creating", { error: "No job data present." }), }); } else { - //IO-539 Check for Parts Rate on PAL for SGI use case. - await CheckTaxRates(estData, bodyshop); - //create upsert job let supp = replaceEmpty({ ...estData.est_data }); + //IO-539 Check for Parts Rate on PAL for SGI use case. + await CheckTaxRates(supp, bodyshop); delete supp.owner; delete supp.vehicle; @@ -391,101 +391,104 @@ function replaceEmpty(someObj, replaceValue = null) { value === "" ? replaceValue || null : value; //^ because you seem to want to replace (strings) "null" or "undefined" too const temp = JSON.stringify(someObj, replacer); - console.log("Parsed", JSON.parse(temp)); return JSON.parse(temp); } async function CheckTaxRates(estData, bodyshop) { + console.log( + "🚀 ~ file: jobs-available-table.container.jsx ~ line 398 ~ estData", + estData + ); //LKQ Check if ( - !estData.est_data.parts_tax_rates?.PAL || - estData.est_data.parts_tax_rates?.PAL?.prt_tax_rt === null || - estData.est_data.parts_tax_rates?.PAL?.prt_tax_rt === 0 + !estData.parts_tax_rates?.PAL || + estData.parts_tax_rates?.PAL?.prt_tax_rt === null || + estData.parts_tax_rates?.PAL?.prt_tax_rt === 0 ) { const res = await confirmDialog( `ImEX Online has detected that there is a missing tax rate for LKQ parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.` ); if (res) { - if (!estData.est_data.parts_tax_rates.PAL) { - estData.est_data.parts_tax_rates.PAL = { + if (!estData.parts_tax_rates.PAL) { + estData.parts_tax_rates.PAL = { prt_discp: 0, prt_mktyp: true, prt_mkupp: 0, prt_type: "PAL", }; } - estData.est_data.parts_tax_rates.PAL.prt_tax_rt = + estData.parts_tax_rates.PAL.prt_tax_rt = bodyshop.bill_tax_rates.state_tax_rate / 100; - estData.est_data.parts_tax_rates.PAL.prt_tax_in = true; + estData.parts_tax_rates.PAL.prt_tax_in = true; } } //PAC Check if ( - !estData.est_data.parts_tax_rates?.PAC || - estData.est_data.parts_tax_rates?.PAC?.prt_tax_rt === null || - estData.est_data.parts_tax_rates?.PAC?.prt_tax_rt === 0 + !estData.parts_tax_rates?.PAC || + estData.parts_tax_rates?.PAC?.prt_tax_rt === null || + estData.parts_tax_rates?.PAC?.prt_tax_rt === 0 ) { const res = await confirmDialog( `ImEX Online has detected that there is a missing tax rate for rechromed parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.` ); if (res) { - if (!estData.est_data.parts_tax_rates.PAC) { - estData.est_data.parts_tax_rates.PAC = { + if (!estData.parts_tax_rates.PAC) { + estData.parts_tax_rates.PAC = { prt_discp: 0, prt_mktyp: true, prt_mkupp: 0, prt_type: "PAC", }; } - estData.est_data.parts_tax_rates.PAC.prt_tax_rt = + estData.parts_tax_rates.PAC.prt_tax_rt = bodyshop.bill_tax_rates.state_tax_rate / 100; - estData.est_data.parts_tax_rates.PAC.prt_tax_in = true; + estData.parts_tax_rates.PAC.prt_tax_in = true; } } //PAM Check if ( - !estData.est_data.parts_tax_rates?.PAM || - estData.est_data.parts_tax_rates?.PAM?.prt_tax_rt === null || - estData.est_data.parts_tax_rates?.PAM?.prt_tax_rt === 0 + !estData.parts_tax_rates?.PAM || + estData.parts_tax_rates?.PAM?.prt_tax_rt === null || + estData.parts_tax_rates?.PAM?.prt_tax_rt === 0 ) { const res = await confirmDialog( `ImEX Online has detected that there is a missing tax rate for remanufactured parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.` ); if (res) { - if (!estData.est_data.parts_tax_rates.PAM) { - estData.est_data.parts_tax_rates.PAM = { + if (!estData.parts_tax_rates.PAM) { + estData.parts_tax_rates.PAM = { prt_discp: 0, prt_mktyp: true, prt_mkupp: 0, prt_type: "PAM", }; } - estData.est_data.parts_tax_rates.PAM.prt_tax_rt = + estData.parts_tax_rates.PAM.prt_tax_rt = bodyshop.bill_tax_rates.state_tax_rate / 100; - estData.est_data.parts_tax_rates.PAM.prt_tax_in = true; + estData.parts_tax_rates.PAM.prt_tax_in = true; } } if ( - !estData.est_data.parts_tax_rates?.PAR || - estData.est_data.parts_tax_rates?.PAR?.prt_tax_rt === null || - estData.est_data.parts_tax_rates?.PAR?.prt_tax_rt === 0 + !estData.parts_tax_rates?.PAR || + estData.parts_tax_rates?.PAR?.prt_tax_rt === null || + estData.parts_tax_rates?.PAR?.prt_tax_rt === 0 ) { const res = await confirmDialog( `ImEX Online has detected that there is a missing tax rate for recored parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.` ); if (res) { - if (!estData.est_data.parts_tax_rates.PAR) { - estData.est_data.parts_tax_rates.PAR = { + if (!estData.parts_tax_rates.PAR) { + estData.parts_tax_rates.PAR = { prt_discp: 0, prt_mktyp: true, prt_mkupp: 0, prt_type: "PAR", }; } - estData.est_data.parts_tax_rates.PAR.prt_tax_rt = + estData.parts_tax_rates.PAR.prt_tax_rt = bodyshop.bill_tax_rates.state_tax_rate / 100; - estData.est_data.parts_tax_rates.PAR.prt_tax_in = true; + estData.parts_tax_rates.PAR.prt_tax_in = true; } } } From aa410d6847657d9fcb94d91f98ff001ea1e8de40 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 28 Sep 2021 11:45:12 -0700 Subject: [PATCH 2/3] IO-1283 IO-1371 Updates to add to scoreboard button. --- .../job-scoreboard-add-button.component.jsx | 157 ++++++++++++------ client/src/graphql/scoreboard.queries.js | 11 ++ 2 files changed, 115 insertions(+), 53 deletions(-) diff --git a/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx b/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx index 9f1f12e0e..846950eaa 100644 --- a/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx +++ b/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx @@ -1,11 +1,24 @@ -import { useMutation } from "@apollo/client"; -import { Button, Card, Form, InputNumber, notification, Popover } from "antd"; +import { useMutation, useLazyQuery } from "@apollo/client"; +import { + Button, + Card, + Form, + InputNumber, + notification, + Popover, + Space, +} from "antd"; import moment from "moment"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { logImEXEvent } from "../../firebase/firebase.utils"; -import { INSERT_SCOREBOARD_ENTRY } from "../../graphql/scoreboard.queries"; +import { + INSERT_SCOREBOARD_ENTRY, + QUERY_SCOREBOARD_ENTRY, + UPDATE_SCOREBOARD_ENTRY, +} from "../../graphql/scoreboard.queries"; import FormDatePicker from "../form-date-picker/form-date-picker.component"; +import LoadingSpinner from "../loading-spinner/loading-spinner.component"; export default function ScoreboardAddButton({ job, @@ -14,17 +27,46 @@ export default function ScoreboardAddButton({ }) { const { t } = useTranslation(); const [insertScoreboardEntry] = useMutation(INSERT_SCOREBOARD_ENTRY); + const [updateScoreboardEntry] = useMutation(UPDATE_SCOREBOARD_ENTRY); const [loading, setLoading] = useState(false); const [form] = Form.useForm(); const [visibility, setVisibility] = useState(false); + const [callQuery, { loading: entryLoading, data: entryData }] = useLazyQuery( + QUERY_SCOREBOARD_ENTRY + ); + + useEffect(() => { + if (visibility) { + callQuery({ variables: { jobid: job.id } }); + } + }, [visibility, job.id, callQuery]); + + useEffect(() => { + console.log("UE", entryData); + if (entryData && entryData.scoreboard && entryData.scoreboard[0]) { + console.log("Setting FOrm"); + form.setFieldsValue(entryData.scoreboard[0]); + } + }, [entryData, form]); const handleFinish = async (values) => { logImEXEvent("job_close_add_to_scoreboard"); setLoading(true); - const result = await insertScoreboardEntry({ - variables: { sbInput: [{ jobid: job.id, ...values }] }, - }); + let result; + + if (entryData && entryData.scoreboard && entryData.scoreboard[0]) { + result = await updateScoreboardEntry({ + variables: { + sbId: entryData.scoreboard[0].id, + sbInput: values, + }, + }); + } else { + result = await insertScoreboardEntry({ + variables: { sbInput: [{ jobid: job.id, ...values }] }, + }); + } if (!!result.errors) { notification["error"]({ @@ -44,53 +86,62 @@ export default function ScoreboardAddButton({ const overlay = (
-
- + ) : ( + - - - - - - - - + + + + + + + + + - -
+ + + + + + )}
); @@ -99,7 +150,7 @@ export default function ScoreboardAddButton({ setLoading(true); const v = job.joblines.reduce( (acc, val) => { - if (val.mod_lbr_ty === "LAB") + if (val.mod_lbr_ty !== "LAR") acc = { ...acc, bodyhrs: acc.bodyhrs + val.mod_lb_hrs }; if (val.mod_lbr_ty === "LAR") acc = { ...acc, painthrs: acc.painthrs + val.mod_lb_hrs }; diff --git a/client/src/graphql/scoreboard.queries.js b/client/src/graphql/scoreboard.queries.js index 1132fd65d..e2b5794d5 100644 --- a/client/src/graphql/scoreboard.queries.js +++ b/client/src/graphql/scoreboard.queries.js @@ -51,3 +51,14 @@ export const UPDATE_SCOREBOARD_ENTRY = gql` } } `; + +export const QUERY_SCOREBOARD_ENTRY = gql` + query QUERY_SCOREBOARD_ENTRY($jobid: uuid!) { + scoreboard(where: { jobid: { _eq: $jobid } }) { + bodyhrs + date + id + painthrs + } + } +`; From eb58274f90d01900b38b431909d5a82d27d701b7 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 28 Sep 2021 13:19:02 -0700 Subject: [PATCH 3/3] IO-1391 Scoreboard Improvements --- .../scoreboard-chart.component.jsx | 20 +++-- .../scoreboard-display.component.jsx | 77 ++++++++++++++++++- .../scoreboard-targets-table.util.js | 6 +- client/src/graphql/scoreboard.queries.js | 20 +++++ 4 files changed, 110 insertions(+), 13 deletions(-) diff --git a/client/src/components/scoreboard-chart/scoreboard-chart.component.jsx b/client/src/components/scoreboard-chart/scoreboard-chart.component.jsx index b39d70d5b..7b1fd410e 100644 --- a/client/src/components/scoreboard-chart/scoreboard-chart.component.jsx +++ b/client/src/components/scoreboard-chart/scoreboard-chart.component.jsx @@ -18,6 +18,11 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util"; import _ from "lodash"; + +const graphProps = { + strokeWidth: 3, +}; + const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, }); @@ -51,7 +56,7 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) { } const theValue = { - date: moment(val).format("D dd"), + date: moment(val).format("D ddd"), paintHrs: _.round(dayhrs.painthrs, 1), bodyHrs: _.round(dayhrs.bodyhrs, 1), accTargetHrs: _.round( @@ -81,36 +86,37 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) { margin={{ top: 20, right: 20, bottom: 20, left: 20 }} > - - + + diff --git a/client/src/components/scoreboard-display/scoreboard-display.component.jsx b/client/src/components/scoreboard-display/scoreboard-display.component.jsx index 6c126c736..29b3065cc 100644 --- a/client/src/components/scoreboard-display/scoreboard-display.component.jsx +++ b/client/src/components/scoreboard-display/scoreboard-display.component.jsx @@ -1,12 +1,33 @@ import { Col, Row } from "antd"; -import React from "react"; +import React, { useEffect } from "react"; import ScoreboardChart from "../scoreboard-chart/scoreboard-chart.component"; import ScoreboardLastDays from "../scoreboard-last-days/scoreboard-last-days.component"; import ScoreboardTargetsTable from "../scoreboard-targets-table/scoreboard-targets-table.component"; -export default function ScoreboardDisplayComponent({ scoreboardSubscription }) { - const { data } = scoreboardSubscription; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import moment from "moment"; +import { useApolloClient } from "@apollo/client"; +import { GET_BLOCKED_DAYS } from "../../graphql/scoreboard.queries"; +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser + bodyshop: selectBodyshop, +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect( + mapStateToProps, + mapDispatchToProps +)(ScoreboardDisplayComponent); +export function ScoreboardDisplayComponent({ + bodyshop, + scoreboardSubscription, +}) { + const { data } = scoreboardSubscription; + const client = useApolloClient(); const scoreBoardlist = (data && data.scoreboard) || []; const sbEntriesByDate = {}; @@ -19,6 +40,29 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) { sbEntriesByDate[entryDate].push(i); }); + useEffect(() => { + //Update the locals. + async function setMomentSettings() { + const { + data: { appointments }, + } = await client.query({ + query: GET_BLOCKED_DAYS, + variables: { + start: moment().startOf("month"), + end: moment().endOf("month"), + }, + }); + + moment.updateLocale("ca", { + workingWeekdays: translateSettingsToWorkingDays(bodyshop.workingdays), + holidays: appointments.map((h) => moment(h.start).format("MM-DD-YYYY")), + holidayFormat: "MM-DD-YYYY", + }); + } + + setMomentSettings(); + }, [client, bodyshop]); + return ( @@ -35,3 +79,30 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) { ); } + +function translateSettingsToWorkingDays(workingdays) { + const days = []; + + if (workingdays.monday) { + days.push(1); + } + if (workingdays.tuesday) { + days.push(2); + } + if (workingdays.wednesday) { + days.push(3); + } + if (workingdays.thursday) { + days.push(4); + } + if (workingdays.friday) { + days.push(5); + } + if (workingdays.saturday) { + days.push(6); + } + if (workingdays.sunday) { + days.push(0); + } + return days; +} diff --git a/client/src/components/scoreboard-targets-table/scoreboard-targets-table.util.js b/client/src/components/scoreboard-targets-table/scoreboard-targets-table.util.js index 47d40c759..97f1813b9 100644 --- a/client/src/components/scoreboard-targets-table/scoreboard-targets-table.util.js +++ b/client/src/components/scoreboard-targets-table/scoreboard-targets-table.util.js @@ -1,8 +1,8 @@ import moment from "moment-business-days"; -moment.updateLocale("ca", { - workingWeekdays: [1, 2, 3, 4, 5], -}); +// moment.updateLocale("ca", { +// workingWeekdays: [1, 2, 3, 4, 5, 6], +// }); export const CalculateWorkingDaysThisMonth = () => { return moment().endOf("month").businessDaysIntoMonth(); diff --git a/client/src/graphql/scoreboard.queries.js b/client/src/graphql/scoreboard.queries.js index e2b5794d5..16a1c6103 100644 --- a/client/src/graphql/scoreboard.queries.js +++ b/client/src/graphql/scoreboard.queries.js @@ -62,3 +62,23 @@ export const QUERY_SCOREBOARD_ENTRY = gql` } } `; + +export const GET_BLOCKED_DAYS = gql` + query GET_BLOCKED_DAYS($start: timestamptz, $end: timestamptz) { + appointments( + where: { + _and: [ + { block: { _eq: true } } + { canceled: { _eq: false } } + { start: { _gte: $start } } + { end: { _lte: $end } } + ] + } + ) { + id + block + start + end + } + } +`;