From 4e2ad3bc62b496527b1ade39b2ce070248ef3f29 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 16 Mar 2023 13:33:20 -0700 Subject: [PATCH] IO-2222 Service Side Generation of part price changes. --- bodyshop_translations.babel | 84 +++++++++++++++++++ .../job-detail-lines/job-lines.component.jsx | 33 ++++---- .../job-send-parts-price-change.component.jsx | 31 +++++++ client/src/translations/en_us/common.json | 2 + client/src/translations/es/common.json | 2 + client/src/translations/fr/common.json | 2 + server.js | 3 + server/ccc/partspricechange.js | 45 ++++++++++ server/graphql-client/queries.js | 16 ++++ 9 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 client/src/components/job-send-parts-price-change/job-send-parts-price-change.component.jsx create mode 100644 server/ccc/partspricechange.js diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 57c7a23e9..f48b6a8f2 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -20737,6 +20737,27 @@ + + sendpartspricechange + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + sendtodms false @@ -21183,6 +21204,27 @@ + + partspricechange + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + saving false @@ -42161,6 +42203,48 @@ + + purchase_return_ratio_grouped_by_vendor_detail + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + purchase_return_ratio_grouped_by_vendor_summary + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + purchases_by_cost_center_detail false 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..503e16201 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -1,12 +1,12 @@ import { DeleteFilled, + EditFilled, FilterFilled, + HomeOutlined, + MinusCircleTwoTone, + PlusCircleTwoTone, SyncOutlined, WarningFilled, - EditFilled, - PlusCircleTwoTone, - MinusCircleTwoTone, - HomeOutlined, } from "@ant-design/icons"; import { useMutation } from "@apollo/client"; import { @@ -38,13 +38,14 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re // import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container"; // import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container"; // import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container"; -import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; import _ from "lodash"; -import JobCreateIOU from "../job-create-iou/job-create-iou.component"; -import JobLinesExpander from "./job-lines-expander.component"; -import { selectBodyshop } from "../../redux/user/user.selectors"; import moment from "moment"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import JobCreateIOU from "../job-create-iou/job-create-iou.component"; import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component"; +import JobSendPartPriceChangeComponent from "../job-send-parts-price-change/job-send-parts-price-change.component"; +import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; +import JobLinesExpander from "./job-lines-expander.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -103,7 +104,9 @@ 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", + }), sortOrder: state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order, ellipsis: true, @@ -443,15 +446,6 @@ export function JobLinesComponent({ technician } onClick={() => { - // setPartsOrderContext({ - // actions: { refetch: refetch }, - // context: { - // jobId: job.id, - // job: job, - // linesToOrder: selectedLines, - // }, - // }); - setBillEnterContext({ actions: { refetch: refetch }, context: { @@ -558,6 +552,9 @@ export function JobLinesComponent({ > {t("joblines.actions.new")} + {bodyshop.region_config.toLowerCase().startsWith("ca") && ( + + )} { + setLoading(true); + try { + const ppcData = await axios.post("/job/ppc", { jobid: job.id }); + const result = axios.post("http://localhost:1337/ppc/", ppcData.data); + } catch (error) { + notification.open({ + type: "error", + message: t("jobs.errors.partspricechange", { + error: JSON.stringify(error), + }), + }); + } finally { + setLoading(false); + } + }; + + return ( + + ); +} diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 3d66cb704..9ecd62809 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1272,6 +1272,7 @@ "removefromproduction": "Remove from Production", "schedule": "Schedule", "sendcsi": "Send CSI", + "sendpartspricechange": "Send Parts Price Change", "sendtodms": "Send to DMS", "sync": "Sync", "uninvoice": "Uninvoice", @@ -1295,6 +1296,7 @@ "nojobselected": "No job is selected.", "noowner": "No owner associated.", "novehicle": "No vehicle associated.", + "partspricechange": "Error sending parts price change. {{error}}.", "saving": "Error encountered while saving record.", "scanimport": "Error importing job. {{message}}", "totalscalc": "Error while calculating new job totals.", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 0866895a5..3f5162101 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1272,6 +1272,7 @@ "removefromproduction": "", "schedule": "Programar", "sendcsi": "", + "sendpartspricechange": "", "sendtodms": "", "sync": "", "uninvoice": "", @@ -1295,6 +1296,7 @@ "nojobselected": "No hay trabajo seleccionado.", "noowner": "Ningún propietario asociado.", "novehicle": "No hay vehículo asociado.", + "partspricechange": "", "saving": "Se encontró un error al guardar el registro.", "scanimport": "", "totalscalc": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index e351dd7d0..2fd7bd329 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1272,6 +1272,7 @@ "removefromproduction": "", "schedule": "Programme", "sendcsi": "", + "sendpartspricechange": "", "sendtodms": "", "sync": "", "uninvoice": "", @@ -1295,6 +1296,7 @@ "nojobselected": "Aucun travail n'est sélectionné.", "noowner": "Aucun propriétaire associé.", "novehicle": "Aucun véhicule associé.", + "partspricechange": "", "saving": "Erreur rencontrée lors de la sauvegarde de l'enregistrement.", "scanimport": "", "totalscalc": "", diff --git a/server.js b/server.js index 95d0d376e..d0b1bde24 100644 --- a/server.js +++ b/server.js @@ -138,6 +138,9 @@ app.post("/job/totalsssu", fb.validateFirebaseIdToken, job.totalsSsu); app.post("/job/costing", fb.validateFirebaseIdToken, job.costing); app.post("/job/costingmulti", fb.validateFirebaseIdToken, job.costingmulti); +var ppc = require("./server/ccc/partspricechange"); +app.post("/job/ppc", fb.validateFirebaseIdToken, ppc.generatePpc); + //Scheduling var scheduling = require("./server/scheduling/scheduling-job"); app.post("/scheduling/job", fb.validateFirebaseIdToken, scheduling.job); diff --git a/server/ccc/partspricechange.js b/server/ccc/partspricechange.js new file mode 100644 index 000000000..14a23ac64 --- /dev/null +++ b/server/ccc/partspricechange.js @@ -0,0 +1,45 @@ +const path = require("path"); +const _ = require("lodash"); +const logger = require("../utils/logger"); +const queries = require("../graphql-client/queries"); +const GraphQLClient = require("graphql-request").GraphQLClient; +const moment = require("moment-timezone"); + +require("dotenv").config({ + path: path.resolve( + process.cwd(), + `.env.${process.env.NODE_ENV || "development"}` + ), +}); + +exports.generatePpc = async (req, res) => { + const { jobid } = req.body; + const BearerToken = req.headers.authorization; + logger.log("generate-ppc", "DEBUG", req.user.email, jobid, null); + + const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, { + headers: { + Authorization: BearerToken, + }, + }); + try { + const { jobs_by_pk: job } = await client + .setHeaders({ Authorization: BearerToken }) + .request(queries.GET_JOB_FOR_PPC, { + jobid: jobid, + }); + + const ReturnVal = { + ...job, + trans_type: "P", + create_dt: moment().tz(job.bodyshop.timezone).format("yyyyMMDD"), + create_tm: moment().tz(job.bodyshop.timezone).format("HHmmSS"), + incl_est: true, + joblines: job.joblines.map((jl) => ({ ...jl, tran_code: 2 })), + }; + + res.json(ReturnVal); + } catch (error) { + res.status(400).Send(JSON.stringify(error)); + } +}; diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 88ff022ac..a70d0d4ba 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -1718,3 +1718,19 @@ query GET_PBS_AP_ALLOCATIONS($billids: [uuid!]) { } } `; + +exports.GET_JOB_FOR_PPC = `query GET_JOB_FOR_PPC($jobid: uuid!) { + jobs_by_pk(id: $jobid) { + id + ciecaid + ro_number + joblines(where: {removed: {_eq: false}}) { + id + act_price + unq_seq + } + bodyshop { + timezone + } + } +}`;