({
dispatch(setModalContext({ context: context, modal: "payment" })),
});
-const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test");
-
export function JobPayments({
job,
jobRO,
@@ -94,23 +92,6 @@ export function JobPayments({
state.sortedInfo.columnKey === "transactionid" &&
state.sortedInfo.order,
},
- {
- title: t("payments.fields.stripeid"),
- dataIndex: "stripeid",
- key: "stripeid",
- render: (text, record) =>
- record.stripeid ? (
-
- {record.stripeid}
-
- ) : null,
- },
{
title: t("general.labels.actions"),
dataIndex: "actions",
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 fc39eb5de..0e1343438 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
@@ -166,6 +166,16 @@ export default function ScoreboardAddButton({
painthrs: 0,
}
);
+
+ //Add Labor Adjustments
+ v.painthrs = v.painthrs + (job.lbr_adjustments.LAR || 0);
+ v.bodyhrs =
+ v.bodyhrs +
+ Object.keys(job.lbr_adjustments)
+ .filter((key) => key !== "LAR")
+ .reduce((acc, val) => {
+ return acc + job.lbr_adjustments[val];
+ }, 0);
form.setFieldsValue({
date: new moment(),
bodyhrs: Math.round(v.bodyhrs * 10) / 10,
diff --git a/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx b/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx
index 2f5e5b39a..e20523880 100644
--- a/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx
+++ b/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx
@@ -9,6 +9,7 @@ import {
Space,
Switch,
} from "antd";
+import axios from "axios";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -18,7 +19,6 @@ import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
-import axios from "axios";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
@@ -83,7 +83,11 @@ export function JobsConvertButton({
layout="vertical"
form={form}
onFinish={handleConvert}
- initialValues={{ driveable: true, towin: false }}
+ initialValues={{
+ driveable: true,
+ towin: false,
+ employee_csr: job.employee_csr,
+ }}
>
>
)}
+ {bodyshop.enforce_conversion_csr && (
+
+
+ option.props.children
+ .toLowerCase()
+ .indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ {bodyshop.employees
+ .filter((emp) => emp.active)
+ .map((emp) => (
+
+ {`${emp.first_name} ${emp.last_name}`}
+
+ ))}
+
+
+ )}
setVisible(true)}
+ onClick={() => {
+ setVisible(true);
+ form.setFieldsValue({
+ driveable: true,
+ towin: false,
+ employee_csr: job.employee_csr,
+ });
+ }}
>
{t("jobs.actions.convert")}
diff --git a/client/src/components/payment-form/payment-form.component.jsx b/client/src/components/payment-form/payment-form.component.jsx
index 9458aece3..1c3c5f42d 100644
--- a/client/src/components/payment-form/payment-form.component.jsx
+++ b/client/src/components/payment-form/payment-form.component.jsx
@@ -1,12 +1,10 @@
import { useTreatments } from "@splitsoftware/splitio-react";
-import { CardElement } from "@stripe/react-stripe-js";
-import { Checkbox, Form, Input, Radio, Select } from "antd";
+import { Form, Input, Radio, Select } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
-import Alert from "../alert/alert.component";
import DatePickerFormItem from "../form-date-picker/form-date-picker.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobSearchSelect from "../job-search-select/job-search-select.component";
@@ -19,11 +17,9 @@ const mapStateToProps = createStructuredSelector({
export function PaymentFormComponent({
form,
- stripeStateArr,
bodyshop,
disabled,
}) {
- const [stripeState, setStripeState] = stripeStateArr;
const { Qb_Multi_Ar } = useTreatments(
["Qb_Multi_Ar"],
{},
@@ -31,9 +27,6 @@ export function PaymentFormComponent({
);
const { t } = useTranslation();
- const handleStripeChange = (e) => {
- setStripeState({ error: e.error, cardComplete: e.complete });
- };
return (
@@ -150,57 +143,6 @@ export function PaymentFormComponent({
-
-
-
-
-
- {!bodyshop.stripe_acct_id ? (
-
- {t("payments.labels.signup")}
-
- ) : null}
-
-
- {() => {
- if (form.getFieldValue("useStripe"))
- return (
-
- );
-
- return null;
- }}
-
- {stripeState.error ? (
-
- ) : null}
-
{
const { useStripe, sendby, ...paymentObj } = values;
- if (useStripe && !cardValid) return;
-
- if ((useStripe && !stripe) || !elements) {
- // Stripe.js has not yet loaded.
- // Make sure to disable form submission until Stripe.js has loaded.
- return;
- }
setLoading(true);
try {
- let stripePayment;
- if (useStripe && bodyshop.stripe_acct_id) {
- logImEXEvent("payment_stripe_attempt");
-
- const secretKey = await axios.post("/stripe/payment", {
- amount: Math.round(values.amount * 100),
- stripe_acct_id: bodyshop.stripe_acct_id,
- });
-
- const { data } = await client.query({
- query: GET_JOB_INFO_FOR_STRIPE,
- variables: { jobid: values.jobid },
- });
-
- stripePayment = await stripe.confirmCardPayment(
- secretKey.data.clientSecret,
- {
- payment_method: {
- card: elements.getElement(CardElement),
- billing_details: {
- name: `${data.jobs_by_pk.ownr_fn || ""} ${
- data.jobs_by_pk.ownr_ln || ""
- } ${data.jobs_by_pk.ownr_co_nm || ""}`,
- email: data.jobs_by_pk.ownr_ea,
- phone: data.jobs_by_pk.ownr_ph1,
- },
- },
- }
- );
-
- if (stripePayment.paymentIntent.status === "succeeded") {
- notification["success"]({ message: t("payments.successes.stripe") });
- } else {
- notification["error"]({ message: t("payments.errors.stripe") });
- throw new Error();
- }
- }
- logImEXEvent("payment_insert");
-
if (!context || (context && !context.id)) {
const newPayment = await insertPayment({
variables: {
paymentInput: {
...paymentObj,
- stripeid:
- stripePayment &&
- stripePayment.paymentIntent &&
- stripePayment.paymentIntent.id,
},
},
});
@@ -236,11 +174,7 @@ function PaymentModalContainer({
layout="vertical"
initialValues={context || {}}
>
-
+
);
@@ -250,15 +184,3 @@ export default connect(
mapStateToProps,
mapDispatchToProps
)(PaymentModalContainer);
-
-// const pr = stripe.paymentRequest({
-// country: "CA",
-// currency: "CAD",
-// total: {
-// label: "Demo total",
-// amount: 1099,
-// },
-// requestPayerName: true,
-// requestPayerEmail: true,
-// });
-// console.log("handleFinish -> pr", pr);
diff --git a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx
index 2ce99d870..50b3d2b98 100644
--- a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx
+++ b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx
@@ -16,8 +16,6 @@ import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
-const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test");
-
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
@@ -125,23 +123,6 @@ export function PaymentsListPaginated({
dataIndex: "transactionid",
key: "transactionid",
},
- {
- title: t("payments.fields.stripeid"),
- dataIndex: "stripeid",
- key: "stripeid",
- render: (text, record) =>
- record.stripeid ? (
-
- {record.stripeid}
-
- ) : null,
- },
{
title: t("payments.fields.created_at"),
dataIndex: "created_at",
diff --git a/client/src/components/print-center-jobs-labels/print-center-jobs-labels.component.jsx b/client/src/components/print-center-jobs-labels/print-center-jobs-labels.component.jsx
index 182618579..5bd0f15e5 100644
--- a/client/src/components/print-center-jobs-labels/print-center-jobs-labels.component.jsx
+++ b/client/src/components/print-center-jobs-labels/print-center-jobs-labels.component.jsx
@@ -1,4 +1,12 @@
-import { Button, Card, Form, InputNumber, Popover, Radio } from "antd";
+import {
+ Button,
+ Card,
+ Form,
+ InputNumber,
+ notification,
+ Popover,
+ Radio,
+} from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -27,7 +35,6 @@ export function PrintCenterJobsLabels({ bodyshop, jobId }) {
const handleOk = (e) => {
e.stopPropagation();
form.submit();
- setIsModalVisible(false);
};
const handleCancel = () => {
@@ -37,18 +44,24 @@ export function PrintCenterJobsLabels({ bodyshop, jobId }) {
const handleFinish = async ({ template, ...values }) => {
const { sendtype, ...restVals } = values;
setLoading(true);
- await GenerateDocument(
- {
- name: TemplateList("job_special")[template].key,
- variables: { id: jobId },
- context: restVals,
- },
- {},
- "p",
- jobId
- );
- setLoading(false);
- setIsModalVisible(false);
+ try {
+ await GenerateDocument(
+ {
+ name: TemplateList("job_special")[template].key,
+ variables: { id: jobId },
+ context: restVals,
+ },
+ {},
+ "p",
+ jobId
+ );
+ setIsModalVisible(false);
+ } catch (error) {
+ notification.open({ type: "error", message: JSON.stringify(error) });
+ } finally {
+ setLoading(false);
+ }
+
form.resetFields();
};
@@ -60,7 +73,15 @@ export function PrintCenterJobsLabels({ bodyshop, jobId }) {
layout="vertical"
form={form}
>
-
+
{t("printcenter.jobs.parts_label_multiple")}
@@ -71,14 +92,24 @@ export function PrintCenterJobsLabels({ bodyshop, jobId }) {
diff --git a/client/src/components/schedule-ats-summary/schedule-ats-summary.component.jsx b/client/src/components/schedule-ats-summary/schedule-ats-summary.component.jsx
new file mode 100644
index 000000000..6362e12e3
--- /dev/null
+++ b/client/src/components/schedule-ats-summary/schedule-ats-summary.component.jsx
@@ -0,0 +1,48 @@
+import { Space } from "antd";
+import React, { useMemo } from "react";
+import { useTranslation } from "react-i18next";
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectScheduleLoad } from "../../redux/application/application.selectors";
+const mapStateToProps = createStructuredSelector({
+ //currentUser: selectCurrentUser
+ scheduleLoad: selectScheduleLoad,
+});
+const mapDispatchToProps = (dispatch) => ({
+ //setUserLanguage: language => dispatch(setUserLanguage(language))
+});
+
+export function ScheduleAtsSummary({ scheduleLoad, appointments }) {
+ const { t } = useTranslation();
+
+ const atsSummary = useMemo(() => {
+ let atsSummary = {};
+ if (!appointments || appointments.length === 0) {
+ return {};
+ }
+ appointments
+ .filter((a) => a.isintake)
+ .forEach((a) => {
+ if (!a.job.alt_transport) return;
+ if (!atsSummary[a.job.alt_transport]) {
+ atsSummary[a.job.alt_transport] = 1;
+ } else {
+ atsSummary[a.job.alt_transport] = atsSummary[a.job.alt_transport] + 1;
+ }
+ });
+ return atsSummary;
+ }, [appointments]);
+
+ if (Object.keys(atsSummary).length > 0)
+ return (
+
+ {t("schedule.labels.atssummary")}
+ {Object.keys(atsSummary).map((key) => (
+ {`${key}: ${atsSummary[key]}`}
+ ))}
+
+ );
+
+ return null;
+}
+export default connect(mapStateToProps, mapDispatchToProps)(ScheduleAtsSummary);
diff --git a/client/src/components/schedule-calendar/schedule-calendar.component.jsx b/client/src/components/schedule-calendar/schedule-calendar.component.jsx
index bbe5c61ad..27830beff 100644
--- a/client/src/components/schedule-calendar/schedule-calendar.component.jsx
+++ b/client/src/components/schedule-calendar/schedule-calendar.component.jsx
@@ -3,6 +3,7 @@ import { Button, Card, Checkbox, Col, PageHeader, Row, Space } from "antd";
import { t } from "i18next";
import React, { useMemo } from "react";
import useLocalStorage from "../../utils/useLocalStorage";
+import ScheduleAtsSummary from "../schedule-ats-summary/schedule-ats-summary.component";
import ScheduleCalendarWrapperComponent from "../schedule-calendar-wrapper/scheduler-calendar-wrapper.component";
import ScheduleModal from "../schedule-job-modal/schedule-job-modal.container";
import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.component";
@@ -35,6 +36,7 @@ export default function ScheduleCalendarComponent({ data, refetch }) {
+
{
diff --git a/client/src/components/shop-info/shop-info.general.component.jsx b/client/src/components/shop-info/shop-info.general.component.jsx
index f6f2ba641..8d9a63706 100644
--- a/client/src/components/shop-info/shop-info.general.component.jsx
+++ b/client/src/components/shop-info/shop-info.general.component.jsx
@@ -466,6 +466,13 @@ export default function ShopInfoGeneral({ form }) {
>
+
+
+
-
+
}
persistor={persistor}
diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx
index 548e9dcf2..7a71f2cd1 100644
--- a/client/src/pages/manage/manage.page.component.jsx
+++ b/client/src/pages/manage/manage.page.component.jsx
@@ -1,5 +1,3 @@
-import { Elements } from "@stripe/react-stripe-js";
-import { loadStripe } from "@stripe/stripe-js";
import { BackTop, Layout } from "antd";
import preval from "preval.macro";
import React, { lazy, Suspense, useEffect } from "react";
@@ -170,18 +168,6 @@ const DmsPayables = lazy(() =>
const { Content, Footer } = Layout;
-const stripePromise = new Promise((resolve, reject) => {
- // client.query({ query: QUERY_STRIPE_ID }).then((resp) => {
- // if (resp.data.bodyshops[0])
- resolve(
- loadStripe(process.env.REACT_APP_STRIPE_PUBLIC_KEY, {
- stripeAccount: "No Stripe Id Resolve",
- })
- );
- // reject();
- // });
-});
-
const mapStateToProps = createStructuredSelector({
conflict: selectInstanceConflict,
bodyshop: selectBodyshop,
@@ -207,9 +193,9 @@ export function Manage({ match, conflict, bodyshop }) {
}
>
-
+
-
+
diff --git a/client/src/pages/mobile-payment/mobile-payment.component.jsx b/client/src/pages/mobile-payment/mobile-payment.component.jsx
index da20a35db..0e2ee0ae3 100644
--- a/client/src/pages/mobile-payment/mobile-payment.component.jsx
+++ b/client/src/pages/mobile-payment/mobile-payment.component.jsx
@@ -1,81 +1,81 @@
-import {
- PaymentRequestButtonElement,
- useStripe,
-} from "@stripe/react-stripe-js";
-import React, { useEffect, useState } from "react";
+// import {
+// PaymentRequestButtonElement,
+// useStripe,
+// } from "@stripe/react-stripe-js";
+// import React, { useEffect, useState } from "react";
-export default function MobilePaymentComponent() {
- const stripe = useStripe();
+// export default function MobilePaymentComponent() {
+// const stripe = useStripe();
- const [paymentRequest, setPaymentRequest] = useState(null);
- useEffect(() => {
- if (stripe) {
- const pr = stripe.paymentRequest({
- country: "CA",
- displayItems: [{ label: "Deductible", amount: 1 }],
- currency: "cad",
- total: {
- label: "Demo total",
- amount: 1,
- },
- requestPayerName: true,
- requestPayerEmail: true,
- });
+// const [paymentRequest, setPaymentRequest] = useState(null);
+// useEffect(() => {
+// if (stripe) {
+// const pr = stripe.paymentRequest({
+// country: "CA",
+// displayItems: [{ label: "Deductible", amount: 1 }],
+// currency: "cad",
+// total: {
+// label: "Demo total",
+// amount: 1,
+// },
+// requestPayerName: true,
+// requestPayerEmail: true,
+// });
- // Check the availability of the Payment Request API.
- pr.canMakePayment().then((result) => {
- if (result) {
- setPaymentRequest(pr);
- } else {
- // var details = {
- // total: { label: "", amount: { currency: "CAD", value: "0.00" } },
- // };
- // new PaymentRequest(
- // [{ supportedMethods: ["basic-card"] }],
- // {}
- // // details
- // ).show();
- }
- });
- }
- }, [stripe]);
+// // Check the availability of the Payment Request API.
+// pr.canMakePayment().then((result) => {
+// if (result) {
+// setPaymentRequest(pr);
+// } else {
+// // var details = {
+// // total: { label: "", amount: { currency: "CAD", value: "0.00" } },
+// // };
+// // new PaymentRequest(
+// // [{ supportedMethods: ["basic-card"] }],
+// // {}
+// // // details
+// // ).show();
+// }
+// });
+// }
+// }, [stripe]);
- if (paymentRequest) {
- paymentRequest.on("paymentmethod", async (ev) => {
- //Call server side to get the client secret
- // Confirm the PaymentIntent without handling potential next actions (yet).
- const { error: confirmError } = await stripe.confirmCardPayment(
- "clientSecret",
- { payment_method: ev.paymentMethod.id },
- { handleActions: false }
- );
+// if (paymentRequest) {
+// paymentRequest.on("paymentmethod", async (ev) => {
+// //Call server side to get the client secret
+// // Confirm the PaymentIntent without handling potential next actions (yet).
+// const { error: confirmError } = await stripe.confirmCardPayment(
+// "clientSecret",
+// { payment_method: ev.paymentMethod.id },
+// { handleActions: false }
+// );
- if (confirmError) {
- // Report to the browser that the payment failed, prompting it to
- // re-show the payment interface, or show an error message and close
- // the payment interface.
- ev.complete("fail");
- } else {
- // Report to the browser that the confirmation was successful, prompting
- // it to close the browser payment method collection interface.
- ev.complete("success");
- // Let Stripe.js handle the rest of the payment flow.
- const {
- error, //paymentIntent
- } = await stripe.confirmCardPayment("clientSecret");
- if (error) {
- // The payment failed -- ask your customer for a new payment method.
- } else {
- // The payment has succeeded.
- }
- }
- });
- return (
-
- );
- }
+// if (confirmError) {
+// // Report to the browser that the payment failed, prompting it to
+// // re-show the payment interface, or show an error message and close
+// // the payment interface.
+// ev.complete("fail");
+// } else {
+// // Report to the browser that the confirmation was successful, prompting
+// // it to close the browser payment method collection interface.
+// ev.complete("success");
+// // Let Stripe.js handle the rest of the payment flow.
+// const {
+// error, //paymentIntent
+// } = await stripe.confirmCardPayment("clientSecret");
+// if (error) {
+// // The payment failed -- ask your customer for a new payment method.
+// } else {
+// // The payment has succeeded.
+// }
+// }
+// });
+// return (
+//
+// );
+// }
- return
;
-}
+// return
;
+// }
diff --git a/client/src/pages/mobile-payment/mobile-payment.container.jsx b/client/src/pages/mobile-payment/mobile-payment.container.jsx
index 7c44dd12d..a87e92b8b 100644
--- a/client/src/pages/mobile-payment/mobile-payment.container.jsx
+++ b/client/src/pages/mobile-payment/mobile-payment.container.jsx
@@ -1,23 +1,23 @@
-import { Elements } from "@stripe/react-stripe-js";
-import { loadStripe } from "@stripe/stripe-js";
-import React from "react";
-import MobilePaymentComponent from "./mobile-payment.component";
+// import { Elements } from "@stripe/react-stripe-js";
+// import { loadStripe } from "@stripe/stripe-js";
+// import React from "react";
+// import MobilePaymentComponent from "./mobile-payment.component";
-const stripePromise = new Promise((resolve, reject) => {
- resolve(
- loadStripe(process.env.REACT_APP_STRIPE_PUBLIC_KEY, {
- stripeAccount: "acct_1Fa7lFIEahEZW8b4",
- })
- );
-});
+// const stripePromise = new Promise((resolve, reject) => {
+// resolve(
+// loadStripe(process.env.REACT_APP_STRIPE_PUBLIC_KEY, {
+// stripeAccount: "acct_1Fa7lFIEahEZW8b4",
+// })
+// );
+// });
-export default function MobilePaymentContainer() {
- return (
-
- The mobile payment container.
-
-
-
-
- );
-}
+// export default function MobilePaymentContainer() {
+// return (
+//
+// The mobile payment container.
+//
+//
+//
+//
+// );
+// }
diff --git a/client/src/redux/application/application.sagas.js b/client/src/redux/application/application.sagas.js
index 70d5c4115..72a6806a0 100644
--- a/client/src/redux/application/application.sagas.js
+++ b/client/src/redux/application/application.sagas.js
@@ -136,10 +136,6 @@ export function* calculateScheduleLoad({ payload: end }) {
}
});
- console.log(
- "🚀 ~ file: application.sagas.js:160 ~ function*calculateScheduleLoad ~ load.productionTotal",
- load.productionTotal
- );
//Propagate the expected load to each day.
const range = Math.round(moment.duration(end.diff(today)).asDays());
for (var day = 0; day < range; day++) {
@@ -175,6 +171,7 @@ export function* calculateScheduleLoad({ payload: end }) {
(load[current].hoursOut || 0);
}
}
+
yield put(setProblemJobs(problemJobs));
yield put(scheduleLoadSuccess(load));
} catch (error) {
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index 6abca68d5..fe220d576 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -279,6 +279,7 @@
},
"email": "General Shop Email",
"enforce_class": "Enforce Class on Conversion?",
+ "enforce_conversion_csr": "Enforce CSR on Conversion?",
"enforce_referral": "Enforce Referrals",
"federal_tax_id": "Federal Tax ID (GST/HST)",
"ignoreblockeddays": "Scoreboard - Ignore Blocked Days",
@@ -2500,6 +2501,7 @@
},
"schedule": {
"labels": {
+ "atssummary": "ATS Summary",
"employeevacation": "Employee Vacations",
"intake": "Intake Events",
"manual": "Manual Events",
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index 16b1a2a93..7bffa8281 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -279,6 +279,7 @@
},
"email": "",
"enforce_class": "",
+ "enforce_conversion_csr": "",
"enforce_referral": "",
"federal_tax_id": "",
"ignoreblockeddays": "",
@@ -2500,6 +2501,7 @@
},
"schedule": {
"labels": {
+ "atssummary": "",
"employeevacation": "",
"intake": "",
"manual": "",
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index d11e9091a..e2c5a5be2 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -279,6 +279,7 @@
},
"email": "",
"enforce_class": "",
+ "enforce_conversion_csr": "",
"enforce_referral": "",
"federal_tax_id": "",
"ignoreblockeddays": "",
@@ -2500,6 +2501,7 @@
},
"schedule": {
"labels": {
+ "atssummary": "",
"employeevacation": "",
"intake": "",
"manual": "",
diff --git a/client/yarn.lock b/client/yarn.lock
index 5a8eb4654..06299b70d 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -2178,20 +2178,21 @@
estree-walker "^1.0.1"
picomatch "^2.2.2"
-"@sentry/browser@7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.7.0.tgz#7810ee98d4969bd0367e29ac0af6c5779db7e6c4"
- integrity sha512-oyzpWcsjVZTaf14zAL89Ng1DUHlbjN+V8pl8dR9Y9anphbzL5BK9p0fSK4kPIrO4GukK+XrKnLJDPuE/o7WR3g==
+"@sentry/browser@7.28.1":
+ version "7.28.1"
+ resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.28.1.tgz#c8086e26079809aa401a05d9b4a6e4df63a9c965"
+ integrity sha512-N8j93IcrWKWorfJ5D+RSKVAvcR4S5tIcZ/HvFPMrQWnfVa/jtJcrKThdjZYteA0wjmPiy8/D3KA8nB91yulBPA==
dependencies:
- "@sentry/core" "7.7.0"
- "@sentry/types" "7.7.0"
- "@sentry/utils" "7.7.0"
+ "@sentry/core" "7.28.1"
+ "@sentry/replay" "7.28.1"
+ "@sentry/types" "7.28.1"
+ "@sentry/utils" "7.28.1"
tslib "^1.9.3"
-"@sentry/cli@^1.74.4":
- version "1.74.5"
- resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.74.5.tgz#4a5c622913087c9ab6f82994da9a7526423779b8"
- integrity sha512-Ze1ec306ZWHtrxKypOJ8nhtFqkrx2f/6bRH+DcJzEQ3bBePQ0ZnqJTTe4BBHADYBtxFIaUWzCZ6DquLz2Zv/sw==
+"@sentry/cli@^1.74.6":
+ version "1.74.6"
+ resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.74.6.tgz#c4f276e52c6f5e8c8d692845a965988068ebc6f5"
+ integrity sha512-pJ7JJgozyjKZSTjOGi86chIngZMLUlYt2HOog+OJn+WGvqEkVymu8m462j1DiXAnex9NspB4zLLNuZ/R6rTQHg==
dependencies:
https-proxy-agent "^5.0.0"
mkdirp "^0.5.5"
@@ -2201,65 +2202,65 @@
proxy-from-env "^1.1.0"
which "^2.0.2"
-"@sentry/core@7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.7.0.tgz#1a2d477897552d179380f7c54c7d81a4e98ea29a"
- integrity sha512-Z15ACiuiFINFcK4gbMrnejLn4AVjKBPJOWKrrmpIe8mh+Y9diOuswt5mMUABs+jhpZvqht3PBLLGBL0WMsYMYA==
+"@sentry/core@7.28.1":
+ version "7.28.1"
+ resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.28.1.tgz#c712ce17469b18b01606108817be24a99ed2116e"
+ integrity sha512-7wvnuvn/mrAfcugWoCG/3pqDIrUgH5t+HisMJMGw0h9Tc33KqrmqMDCQVvjlrr2pWrw/vuUCFdm8CbUHJ832oQ==
dependencies:
- "@sentry/hub" "7.7.0"
- "@sentry/types" "7.7.0"
- "@sentry/utils" "7.7.0"
+ "@sentry/types" "7.28.1"
+ "@sentry/utils" "7.28.1"
tslib "^1.9.3"
-"@sentry/hub@7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-7.7.0.tgz#9ad3471cf5ecaf1a9d3a3a04ca2515ffec9e2c09"
- integrity sha512-6gydK234+a0nKhBRDdIJ7Dp42CaiW2juTiHegUVDq+482balVzbZyEAmESCmuzKJhx5BhlCElVxs/cci1NjMpg==
+"@sentry/react@^7.28.1":
+ version "7.28.1"
+ resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.28.1.tgz#79531b98176765a788cdf7f8f09b8ba713a95cfb"
+ integrity sha512-sFKK7uDREh84GyJcXDNuiQQ5VhLx7XJTOAdELxLv4HEI6BxbBRz0zNRQiKamTRkz9NmL7bZtld5TfbpOo9kijg==
dependencies:
- "@sentry/types" "7.7.0"
- "@sentry/utils" "7.7.0"
- tslib "^1.9.3"
-
-"@sentry/react@^7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.7.0.tgz#a519dd727f863c1abf1a77beac01a3336c856828"
- integrity sha512-93Khad3YAln6mKU9E15QH09XC1ARIOpNTRpnBl6AGl3bVhSdLExsbKDLa7Rx0mW2j4z/prOC6VEHf5mBvg4mPg==
- dependencies:
- "@sentry/browser" "7.7.0"
- "@sentry/types" "7.7.0"
- "@sentry/utils" "7.7.0"
+ "@sentry/browser" "7.28.1"
+ "@sentry/types" "7.28.1"
+ "@sentry/utils" "7.28.1"
hoist-non-react-statics "^3.3.2"
tslib "^1.9.3"
-"@sentry/tracing@^7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.7.0.tgz#67324b755a28e115289755e44a0b8b467a63d0b2"
- integrity sha512-HNmvTwemuc21q/K6HXsSp9njkne6N1JQ71TB+QGqYU5VtxsVgYSUhhYqV6WcHz7LK4Hj6TvNFoeu69/rO0ysgw==
+"@sentry/replay@7.28.1":
+ version "7.28.1"
+ resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.28.1.tgz#fbdd377923e082423b95e3f128cb9af9451aca70"
+ integrity sha512-Os0PzMjKlwtHwzTU0kfVzGzsi4Vaj3g2arCl4Qnr3b6kYTb9WOFZo/n/v56ss7Z+nZG3K8W5PisoD4MRsRJRig==
dependencies:
- "@sentry/hub" "7.7.0"
- "@sentry/types" "7.7.0"
- "@sentry/utils" "7.7.0"
+ "@sentry/core" "7.28.1"
+ "@sentry/types" "7.28.1"
+ "@sentry/utils" "7.28.1"
+
+"@sentry/tracing@^7.28.1":
+ version "7.28.1"
+ resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.28.1.tgz#d276e4d17a79190a88112696c73de12c209607a1"
+ integrity sha512-uWspnuz+7FyW8ES5lRaVA7O/YJSzMlSkvBFtgzaoKmdaueokU/sRLwlCsrdgwavG1wpm79df7R1iiSeqhaXDlw==
+ dependencies:
+ "@sentry/core" "7.28.1"
+ "@sentry/types" "7.28.1"
+ "@sentry/utils" "7.28.1"
tslib "^1.9.3"
-"@sentry/types@7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.7.0.tgz#dd6bd3d119d7efea0e85dbaa4b17de1c22b63c7a"
- integrity sha512-4x8O7uerSGLnYC10krHl9t8h7xXHn5FextqKYbTCXCnx2hC8D+9lz8wcbQAFo0d97wiUYqI8opmEgFVGx7c5hQ==
+"@sentry/types@7.28.1":
+ version "7.28.1"
+ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.28.1.tgz#9018b4c152b475de9bedd267237393d3c9b1253d"
+ integrity sha512-DvSplMVrVEmOzR2M161V5+B8Up3vR71xMqJOpWTzE9TqtFJRGPtqT/5OBsNJJw1+/j2ssMcnKwbEo9Q2EGeS6g==
-"@sentry/utils@7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.7.0.tgz#013e3097c4268a76de578494c7df999635fb0ad4"
- integrity sha512-fD+ROSFpeJlK7bEvUT2LOW7QqgjBpXJwVISKZ0P2fuzclRC3KoB2pbZgBM4PXMMTiSzRGWhvfRRjBiBvQJBBJQ==
+"@sentry/utils@7.28.1":
+ version "7.28.1"
+ resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.28.1.tgz#0a7b6aa4b09e91e4d1aded2a8c8dbaf818cee96e"
+ integrity sha512-75/jzLUO9HH09iC9TslNimGbxOP3jgn89P+q7uR+rp2fJfRExHVeKJZQdK0Ij4/SmE7TJ3Uh2r154N0INZEx1g==
dependencies:
- "@sentry/types" "7.7.0"
+ "@sentry/types" "7.28.1"
tslib "^1.9.3"
-"@sentry/webpack-plugin@^1.19.0":
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.19.0.tgz#2b134318f1552ba7f3e3f9c83c71a202095f7a44"
- integrity sha512-qSpdgdGMtdzagGveSWgo2b+t8PdPUscuOjbOyWCsJme9jlTFnNk0rX7JEA55OUozikKHM/+vVh08USLBnPboZw==
+"@sentry/webpack-plugin@^1.20.0":
+ version "1.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.20.0.tgz#e7add76122708fb6b4ee7951294b521019720e58"
+ integrity sha512-Ssj1mJVFsfU6vMCOM2d+h+KQR7QHSfeIP16t4l20Uq/neqWXZUQ2yvQfe4S3BjdbJXz/X4Rw8Hfy1Sd0ocunYw==
dependencies:
- "@sentry/cli" "^1.74.4"
+ "@sentry/cli" "^1.74.6"
+ webpack-sources "^2.0.0 || ^3.0.0"
"@sinonjs/commons@^1.7.0":
version "1.8.3"
@@ -14615,6 +14616,11 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0, webpack-
source-list-map "^2.0.0"
source-map "~0.6.1"
+"webpack-sources@^2.0.0 || ^3.0.0":
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
webpack@4.44.2:
version "4.44.2"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72"
diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml
index 79a4dad70..288fd4242 100644
--- a/hasura/metadata/tables.yaml
+++ b/hasura/metadata/tables.yaml
@@ -855,6 +855,7 @@
- deliverchecklist
- email
- enforce_class
+ - enforce_conversion_csr
- enforce_referral
- entegral_configuration
- entegral_id
@@ -951,6 +952,7 @@
- deliverchecklist
- email
- enforce_class
+ - enforce_conversion_csr
- enforce_referral
- federal_tax_id
- id
diff --git a/hasura/migrations/1672695435314_alter_table_public_bodyshops_add_column_enforce_conversion_csr/down.sql b/hasura/migrations/1672695435314_alter_table_public_bodyshops_add_column_enforce_conversion_csr/down.sql
new file mode 100644
index 000000000..be3dbfc5d
--- /dev/null
+++ b/hasura/migrations/1672695435314_alter_table_public_bodyshops_add_column_enforce_conversion_csr/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 "enforce_conversion_csr" boolean
+-- null default 'false';
diff --git a/hasura/migrations/1672695435314_alter_table_public_bodyshops_add_column_enforce_conversion_csr/up.sql b/hasura/migrations/1672695435314_alter_table_public_bodyshops_add_column_enforce_conversion_csr/up.sql
new file mode 100644
index 000000000..7d5b2c079
--- /dev/null
+++ b/hasura/migrations/1672695435314_alter_table_public_bodyshops_add_column_enforce_conversion_csr/up.sql
@@ -0,0 +1,2 @@
+alter table "public"."bodyshops" add column "enforce_conversion_csr" boolean
+ null default 'false';
diff --git a/server/accounting/qb-receivables-lines.js b/server/accounting/qb-receivables-lines.js
index 9f6612dd2..fa637e38e 100644
--- a/server/accounting/qb-receivables-lines.js
+++ b/server/accounting/qb-receivables-lines.js
@@ -654,9 +654,9 @@ exports.default = function ({
if (qbo) {
InvoiceLineAdd.push({
DetailType: "SalesItemLineDetail",
- Amount: Dinero({ amount: (payer.amount || 0) * 100 * -1 }).toFormat(
- DineroQbFormat
- ),
+ Amount: Dinero({
+ amount: Math.round((payer.amount || 0) * 100) * -1,
+ }).toFormat(DineroQbFormat),
SalesItemLineDetail: {
...(jobs_by_pk.class
? { ClassRef: { value: classes[jobs_by_pk.class] } }
@@ -687,9 +687,9 @@ exports.default = function ({
FullName: responsibilityCenters.qb_multiple_payers?.accountitem,
},
Desc: `${payer.name} Liability`,
- Amount: Dinero({ amount: (payer.amount || 0) * 100 * -1 }).toFormat(
- DineroQbFormat
- ),
+ Amount: Dinero({
+ amount: Math.round((payer.amount || 0) * 100) * -1,
+ }).toFormat(DineroQbFormat),
});
}
});