diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 6cd6a8469..412419163 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -4509,6 +4509,27 @@ + + enforce_conversion_csr + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + enforce_referral false @@ -42381,6 +42402,27 @@ labels + + atssummary + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + employeevacation false diff --git a/client/package.json b/client/package.json index c6eda0caa..0d61af0eb 100644 --- a/client/package.json +++ b/client/package.json @@ -9,11 +9,9 @@ "@craco/craco": "^6.4.5", "@fingerprintjs/fingerprintjs": "^3.3.3", "@jsreport/browser-client": "^3.1.0", - "@sentry/react": "^7.7.0", - "@sentry/tracing": "^7.7.0", + "@sentry/react": "^7.28.1", + "@sentry/tracing": "^7.28.1", "@splitsoftware/splitio-react": "^1.6.0", - "@stripe/react-stripe-js": "^1.9.0", - "@stripe/stripe-js": "^1.32.0", "@tanem/react-nprogress": "^5.0.8", "antd": "^4.22.3", "apollo-link-logger": "^2.0.0", @@ -119,7 +117,7 @@ "react-error-overlay": "6.0.9" }, "devDependencies": { - "@sentry/webpack-plugin": "^1.19.0", + "@sentry/webpack-plugin": "^1.20.0", "@testing-library/cypress": "^8.0.3", "cypress": "^10.3.1", "eslint-plugin-cypress": "^2.12.1", diff --git a/client/src/components/_test/paymentMethod.jsx b/client/src/components/_test/paymentMethod.jsx index c90fef0a7..8e722cc0b 100644 --- a/client/src/components/_test/paymentMethod.jsx +++ b/client/src/components/_test/paymentMethod.jsx @@ -1,8 +1,4 @@ -import { - PaymentRequestButtonElement, - useStripe, -} from "@stripe/react-stripe-js"; -import React, { useEffect, useState } from "react"; +import React from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.utils"; @@ -19,49 +15,6 @@ const mapDispatchToProps = (dispatch) => ({ }); function Test({ bodyshop, setEmailOptions }) { - const stripe = useStripe(); - - const [paymentRequest, setPaymentRequest] = useState(null); - useEffect(() => { - if (stripe) { - const pr = stripe.paymentRequest({ - country: "CA", - displayItems: [{ label: "Deductible", amount: 1099 }], - currency: "cad", - total: { - label: "Demo total", - amount: 1099, - }, - 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]); - - if (paymentRequest) { - return ( -
- -
- ); - } - return (
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), }); } });