diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 13e91e869..5bc83e3b8 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -37301,6 +37301,27 @@ + + inserting + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + diff --git a/client/src/components/card-payment-modal/card-payment-modal.component..jsx b/client/src/components/card-payment-modal/card-payment-modal.component..jsx index 15c4ffe3a..071e2a758 100644 --- a/client/src/components/card-payment-modal/card-payment-modal.component..jsx +++ b/client/src/components/card-payment-modal/card-payment-modal.component..jsx @@ -1,12 +1,15 @@ -import { useMutation, useQuery } from "@apollo/client"; +import { DeleteFilled } from "@ant-design/icons"; +import { useLazyQuery, useMutation } from "@apollo/client"; import { Button, Card, + Col, Form, Input, - InputNumber, Row, + Space, Spin, + Statistic, notification, } from "antd"; import axios from "axios"; @@ -17,7 +20,7 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { INSERT_PAYMENT_RESPONSE, - QUERY_RO_AND_OWNER_BY_JOB_PK, + QUERY_RO_AND_OWNER_BY_JOB_PKS, } from "../../graphql/payment_response.queries"; import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries"; import { insertAuditTrail } from "../../redux/application/application.actions"; @@ -25,9 +28,8 @@ import { toggleModalVisible } from "../../redux/modals/modals.actions"; import { selectCardPayment } from "../../redux/modals/modals.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings"; -import DataLabel from "../data-label/data-label.component"; +import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component"; import JobSearchSelectComponent from "../job-search-select/job-search-select.component"; -import LayoutFormRow from "../layout-form-row/layout-form-row.component"; const mapStateToProps = createStructuredSelector({ cardPaymentModal: selectCardPayment, @@ -49,18 +51,21 @@ const CardPaymentModalComponent = ({ const { context } = cardPaymentModal; const [form] = Form.useForm(); - const amount = Form.useWatch("amount", form); - const jobid = Form.useWatch("jobid", form); + const [loading, setLoading] = useState(false); const [insertPayment] = useMutation(INSERT_NEW_PAYMENT); const [insertPaymentResponse] = useMutation(INSERT_PAYMENT_RESPONSE); const { t } = useTranslation(); - const { data, refetch } = useQuery(QUERY_RO_AND_OWNER_BY_JOB_PK, { - variables: { jobid: context?.jobid ?? "" }, - skip: !context?.jobid, - }); + const [, { data, refetch, queryLoading }] = useLazyQuery( + QUERY_RO_AND_OWNER_BY_JOB_PKS, + { + variables: { jobids: [context.jobid] }, + skip: true, + } + ); + console.log("🚀 ~ file: card-payment-modal.component..jsx:61 ~ data:", data); //Initialize the intellipay window. const SetIntellipayCallbackFunctions = () => { console.log("*** Set IntelliPay callback functions."); @@ -76,69 +81,68 @@ const CardPaymentModalComponent = ({ window.intellipay.runOnNonApproval(async function (response) { // Mutate unsuccessful payment + + const { payments } = form.getFieldsValue(); + await insertPaymentResponse({ variables: { - paymentResponse: { - amount: response.amount, + paymentResponse: payments.map((payment) => ({ + amount: payment.amount, bodyshopid: bodyshop.id, - jobid: jobid || context.jobid, + jobid: payment.jobid, declinereason: response.declinereason, ext_paymentid: response.paymentid.toString(), successful: false, response, - }, + })), }, }); - insertAuditTrail({ - jobid: jobid || context?.jobid, - operation: AuditTrailMapping.failedpayment(), - }); + + payments.forEach((payment) => + insertAuditTrail({ + jobid: payment.jobid, + operation: AuditTrailMapping.failedpayment(), + }) + ); }); }; const handleFinish = async (values) => { try { - const paymentResult = await insertPayment({ + await insertPayment({ variables: { - paymentInput: { - amount: values.amount, + paymentInput: values.payments.map((payment) => ({ + amount: payment.amount, transactionid: (values.paymentResponse.paymentid || "").toString(), payer: t("payments.labels.customer"), type: values.paymentResponse.cardbrand, - jobid: values.jobid, + jobid: payment.jobid, date: moment(Date.now()), - }, + payment_responses: { + data: [ + { + amount: payment.amount, + bodyshopid: bodyshop.id, + + jobid: payment.jobid, + declinereason: values.paymentResponse.declinereason, + ext_paymentid: values.paymentResponse.paymentid.toString(), + successful: true, + response: values.paymentResponse, + }, + ], + }, + })), }, refetchQueries: ["GET_JOB_BY_PK"], - update(cache, { data }) { - cache.modify({ - id: cache.identify({ id: values.jobid, __typename: "jobs" }), - fields: { - payments(cachedPayments) { - return [...data.insert_payments.returning, ...cachedPayments]; - }, - }, - }); - }, - }); - - await insertPaymentResponse({ - variables: { - paymentResponse: { - amount: values.amount, - bodyshopid: bodyshop.id, - paymentid: paymentResult.data.insert_payments.returning[0].id, - jobid: values.jobid, - declinereason: values.paymentResponse.declinereason, - ext_paymentid: values.paymentResponse.paymentid.toString(), - successful: true, - response: values.paymentResponse, - }, - }, }); toggleModalVisible(); } catch (error) { console.error(error); + notification.open({ + type: "error", + message: t("payments.errors.inserting", { error: error.message }), + }); } finally { setLoading(false); } @@ -146,9 +150,16 @@ const CardPaymentModalComponent = ({ const handleIntelliPayCharge = async () => { setLoading(true); - try { - console.warn("*** Window.Intellipay", !!window.intellipay); + //Validate + try { + await form.validateFields(); + } catch (error) { + setLoading(false); + return; + } + + try { const response = await axios.post("/intellipay/lightbox_credentials", { bodyshop, refresh: !!window.intellipay, @@ -182,93 +193,175 @@ const CardPaymentModalComponent = ({ - - - { - refetch({ jobid: e }); - }} - /> - - + + {(fields, { add, remove, move }) => { + return ( + + {fields.map((field, index) => ( + + + + + + + + + + + + + + { + remove(field.name); + }} + /> + + + + ))} + + { + add(); + }} + style={{ width: "100%" }} + > + {t("general.actions.add")} + + + + ); + }} + - {/* Lighbox Input amount needs to be hidden */} - - - - {/* Lightbox payment response when it is completed */} - - + + prevValues.payments?.map((p) => p?.jobid).join() !== + curValues.payments?.map((p) => p?.jobid).join() + } + > + {() => { + console.log("Updating the owner info section."); + //If all of the job ids have been fileld in, then query and update the IP field. + const { payments } = form.getFieldsValue(); + if ( + payments?.length > 0 && + payments?.filter((p) => p?.jobid).length === payments?.length + ) { + console.log("**Calling refetch."); + refetch({ jobids: payments.map((p) => p.jobid) }); + } + console.log( + "Acc info", + data, + payments && data && data.jobs.length > 0 + ? data.jobs.map((j) => j.ro_number).join(", ") + : null + ); + return ( + <> + 0 + ? data.jobs.map((j) => j.ro_number).join(", ") + : null + } + hidden + /> + 0 + ? data.jobs.filter((j) => j.ownr_ea)[0]?.ownr_ea + : null + } + hidden + /> + > + ); + }} + + + prevValues.payments?.map((p) => p?.amount).join() !== + curValues.payments?.map((p) => p?.amount).join() + } + > + {() => { + const { payments } = form.getFieldsValue(); + const totalAmountToCharge = payments?.reduce((acc, val) => { + return acc + (val?.amount || 0); + }, 0); + + return ( + + + + 0)} + onClick={handleIntelliPayCharge} + > + {t("job_payments.buttons.proceedtopayment")} + + + ); + }} - - - - - - - - {t("job_payments.buttons.proceedtopayment")} - - {context?.balance && ( - - {context?.balance.toFormat()} - - )} - - + {/* Lightbox payment response when it is completed */} + + + diff --git a/client/src/components/card-payment-modal/card-payment-modal.container..jsx b/client/src/components/card-payment-modal/card-payment-modal.container..jsx index 547a0ab75..f33b7bc9e 100644 --- a/client/src/components/card-payment-modal/card-payment-modal.container..jsx +++ b/client/src/components/card-payment-modal/card-payment-modal.container..jsx @@ -43,7 +43,7 @@ function CardPaymentModalContainer({ {t("job_payments.buttons.goback")} , ]} - width="60%" + width="80%" destroyOnClose > diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index ec8e48104..8d180bdd1 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -254,7 +254,7 @@ function Header({ onClick={() => { setCardPaymentContext({ actions: {}, - context: null, + context: {}, }); }} icon={} diff --git a/client/src/components/payment-expanded-row/payment-expanded-row.component.jsx b/client/src/components/payment-expanded-row/payment-expanded-row.component.jsx index eaa0d20ed..a150eee78 100644 --- a/client/src/components/payment-expanded-row/payment-expanded-row.component.jsx +++ b/client/src/components/payment-expanded-row/payment-expanded-row.component.jsx @@ -1,5 +1,12 @@ import { useMutation, useQuery } from "@apollo/client"; -import { Button, Descriptions, InputNumber, Modal, notification } from "antd"; +import { + Button, + Descriptions, + InputNumber, + Modal, + Space, + notification, +} from "antd"; import axios from "axios"; import moment from "moment"; import React, { useState } from "react"; @@ -158,15 +165,17 @@ const PaymentExpandedRowComponent = ({ record, bodyshop }) => { {payment_response && ( - + + - showConfirm(payment_response)}> - {t("job_payments.buttons.refundpayment")} - + showConfirm(payment_response)}> + {t("job_payments.buttons.refundpayment")} + + )} diff --git a/client/src/graphql/payment_response.queries.js b/client/src/graphql/payment_response.queries.js index 8722e6cd8..a23d00dbb 100644 --- a/client/src/graphql/payment_response.queries.js +++ b/client/src/graphql/payment_response.queries.js @@ -28,16 +28,14 @@ export const QUERY_PAYMENT_RESPONSE_BY_PAYMENT_ID = gql` } `; -export const QUERY_RO_AND_OWNER_BY_JOB_PK = gql` - query QUERY_RO_AND_OWNER_BY_JOB_PK($jobid: uuid!) { - jobs_by_pk(id: $jobid) { +export const QUERY_RO_AND_OWNER_BY_JOB_PKS = gql` + query QUERY_RO_AND_OWNER_BY_JOB_PKS($jobids: [uuid!]!) { + jobs(where: { id: { _in: $jobids } }) { ro_number - owner { - ownr_fn - ownr_ln - ownr_ea - ownr_zip - } + ownr_fn + ownr_ln + ownr_ea + ownr_zip } } `; diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index d1a681b05..43321060f 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -2208,7 +2208,8 @@ }, "errors": { "exporting": "Error exporting payment(s). {{error}}", - "exporting-partner": "Error exporting to partner. Please check the partner interaction log for more errors." + "exporting-partner": "Error exporting to partner. Please check the partner interaction log for more errors.", + "inserting": "Error inserting payment. {{error}}" }, "fields": { "amount": "Amount", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 57ee1afdd..11e00e638 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -2208,7 +2208,8 @@ }, "errors": { "exporting": "", - "exporting-partner": "" + "exporting-partner": "", + "inserting": "" }, "fields": { "amount": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 3232958fe..c386076df 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -2208,7 +2208,8 @@ }, "errors": { "exporting": "", - "exporting-partner": "" + "exporting-partner": "", + "inserting": "" }, "fields": { "amount": "",