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
+ }
+ }
+}`;