@@ -37301,6 +37301,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>inserting</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import { useMutation, useQuery } from "@apollo/client";
|
import { DeleteFilled } from "@ant-design/icons";
|
||||||
|
import { useLazyQuery, useMutation } from "@apollo/client";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
Col,
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
|
||||||
Row,
|
Row,
|
||||||
|
Space,
|
||||||
Spin,
|
Spin,
|
||||||
|
Statistic,
|
||||||
notification,
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
@@ -17,7 +20,7 @@ import { connect } from "react-redux";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import {
|
import {
|
||||||
INSERT_PAYMENT_RESPONSE,
|
INSERT_PAYMENT_RESPONSE,
|
||||||
QUERY_RO_AND_OWNER_BY_JOB_PK,
|
QUERY_RO_AND_OWNER_BY_JOB_PKS,
|
||||||
} from "../../graphql/payment_response.queries";
|
} from "../../graphql/payment_response.queries";
|
||||||
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
|
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
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 { selectCardPayment } from "../../redux/modals/modals.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
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 JobSearchSelectComponent from "../job-search-select/job-search-select.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
cardPaymentModal: selectCardPayment,
|
cardPaymentModal: selectCardPayment,
|
||||||
@@ -49,18 +51,21 @@ const CardPaymentModalComponent = ({
|
|||||||
const { context } = cardPaymentModal;
|
const { context } = cardPaymentModal;
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const amount = Form.useWatch("amount", form);
|
|
||||||
const jobid = Form.useWatch("jobid", form);
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [insertPayment] = useMutation(INSERT_NEW_PAYMENT);
|
const [insertPayment] = useMutation(INSERT_NEW_PAYMENT);
|
||||||
const [insertPaymentResponse] = useMutation(INSERT_PAYMENT_RESPONSE);
|
const [insertPaymentResponse] = useMutation(INSERT_PAYMENT_RESPONSE);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { data, refetch } = useQuery(QUERY_RO_AND_OWNER_BY_JOB_PK, {
|
const [, { data, refetch, queryLoading }] = useLazyQuery(
|
||||||
variables: { jobid: context?.jobid ?? "" },
|
QUERY_RO_AND_OWNER_BY_JOB_PKS,
|
||||||
skip: !context?.jobid,
|
{
|
||||||
});
|
variables: { jobids: [context.jobid] },
|
||||||
|
skip: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("🚀 ~ file: card-payment-modal.component..jsx:61 ~ data:", data);
|
||||||
//Initialize the intellipay window.
|
//Initialize the intellipay window.
|
||||||
const SetIntellipayCallbackFunctions = () => {
|
const SetIntellipayCallbackFunctions = () => {
|
||||||
console.log("*** Set IntelliPay callback functions.");
|
console.log("*** Set IntelliPay callback functions.");
|
||||||
@@ -76,69 +81,68 @@ const CardPaymentModalComponent = ({
|
|||||||
|
|
||||||
window.intellipay.runOnNonApproval(async function (response) {
|
window.intellipay.runOnNonApproval(async function (response) {
|
||||||
// Mutate unsuccessful payment
|
// Mutate unsuccessful payment
|
||||||
|
|
||||||
|
const { payments } = form.getFieldsValue();
|
||||||
|
|
||||||
await insertPaymentResponse({
|
await insertPaymentResponse({
|
||||||
variables: {
|
variables: {
|
||||||
paymentResponse: {
|
paymentResponse: payments.map((payment) => ({
|
||||||
amount: response.amount,
|
amount: payment.amount,
|
||||||
bodyshopid: bodyshop.id,
|
bodyshopid: bodyshop.id,
|
||||||
jobid: jobid || context.jobid,
|
jobid: payment.jobid,
|
||||||
declinereason: response.declinereason,
|
declinereason: response.declinereason,
|
||||||
ext_paymentid: response.paymentid.toString(),
|
ext_paymentid: response.paymentid.toString(),
|
||||||
successful: false,
|
successful: false,
|
||||||
response,
|
response,
|
||||||
},
|
})),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
insertAuditTrail({
|
|
||||||
jobid: jobid || context?.jobid,
|
payments.forEach((payment) =>
|
||||||
operation: AuditTrailMapping.failedpayment(),
|
insertAuditTrail({
|
||||||
});
|
jobid: payment.jobid,
|
||||||
|
operation: AuditTrailMapping.failedpayment(),
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (values) => {
|
||||||
try {
|
try {
|
||||||
const paymentResult = await insertPayment({
|
await insertPayment({
|
||||||
variables: {
|
variables: {
|
||||||
paymentInput: {
|
paymentInput: values.payments.map((payment) => ({
|
||||||
amount: values.amount,
|
amount: payment.amount,
|
||||||
transactionid: (values.paymentResponse.paymentid || "").toString(),
|
transactionid: (values.paymentResponse.paymentid || "").toString(),
|
||||||
payer: t("payments.labels.customer"),
|
payer: t("payments.labels.customer"),
|
||||||
type: values.paymentResponse.cardbrand,
|
type: values.paymentResponse.cardbrand,
|
||||||
jobid: values.jobid,
|
jobid: payment.jobid,
|
||||||
date: moment(Date.now()),
|
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"],
|
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();
|
toggleModalVisible();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
notification.open({
|
||||||
|
type: "error",
|
||||||
|
message: t("payments.errors.inserting", { error: error.message }),
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@@ -146,9 +150,16 @@ const CardPaymentModalComponent = ({
|
|||||||
|
|
||||||
const handleIntelliPayCharge = async () => {
|
const handleIntelliPayCharge = async () => {
|
||||||
setLoading(true);
|
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", {
|
const response = await axios.post("/intellipay/lightbox_credentials", {
|
||||||
bodyshop,
|
bodyshop,
|
||||||
refresh: !!window.intellipay,
|
refresh: !!window.intellipay,
|
||||||
@@ -182,93 +193,175 @@ const CardPaymentModalComponent = ({
|
|||||||
<Form
|
<Form
|
||||||
onFinish={handleFinish}
|
onFinish={handleFinish}
|
||||||
form={form}
|
form={form}
|
||||||
initialValues={{ jobid: context?.jobid }}
|
layout="vertical"
|
||||||
|
initialValues={{
|
||||||
|
payments: context.jobid ? [{ jobid: context.jobid }] : [],
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<LayoutFormRow grow noDivider>
|
<Form.List name={["payments"]}>
|
||||||
<Form.Item
|
{(fields, { add, remove, move }) => {
|
||||||
name="jobid"
|
return (
|
||||||
label={t("bills.fields.ro_number")}
|
<div>
|
||||||
rules={[
|
{fields.map((field, index) => (
|
||||||
{
|
<Form.Item key={field.key}>
|
||||||
required: true,
|
<Row gutter={[16, 16]}>
|
||||||
// message: t("general.validation.required"),
|
<Col span={16}>
|
||||||
},
|
<Form.Item
|
||||||
]}
|
key={`${index}jobid`}
|
||||||
>
|
label={t("jobs.fields.ro_number")}
|
||||||
<JobSearchSelectComponent
|
name={[field.name, "jobid"]}
|
||||||
disabled={context?.jobid}
|
rules={[
|
||||||
notExported={false}
|
{
|
||||||
clm_no
|
required: true,
|
||||||
onChange={(e) => {
|
//message: t("general.validation.required"),
|
||||||
refetch({ jobid: e });
|
},
|
||||||
}}
|
]}
|
||||||
/>
|
>
|
||||||
</Form.Item>
|
<JobSearchSelectComponent
|
||||||
</LayoutFormRow>
|
notExported={false}
|
||||||
|
clm_no
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Form.Item
|
||||||
|
key={`${index}amount`}
|
||||||
|
label={t("payments.fields.amount")}
|
||||||
|
name={[field.name, "amount"]}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<CurrencyFormItemComponent />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={2}>
|
||||||
|
<DeleteFilled
|
||||||
|
style={{ margin: "1rem" }}
|
||||||
|
onClick={() => {
|
||||||
|
remove(field.name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form.Item>
|
||||||
|
))}
|
||||||
|
<Form.Item>
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
onClick={() => {
|
||||||
|
add();
|
||||||
|
}}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
>
|
||||||
|
{t("general.actions.add")}
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Form.List>
|
||||||
|
|
||||||
{/* Lighbox Input amount needs to be hidden */}
|
<Form.Item
|
||||||
<Input
|
shouldUpdate={(prevValues, curValues) =>
|
||||||
className="ipayfield"
|
prevValues.payments?.map((p) => p?.jobid).join() !==
|
||||||
data-ipayname="amount"
|
curValues.payments?.map((p) => p?.jobid).join()
|
||||||
type="hidden"
|
}
|
||||||
value={amount}
|
>
|
||||||
hidden
|
{() => {
|
||||||
/>
|
console.log("Updating the owner info section.");
|
||||||
<Input
|
//If all of the job ids have been fileld in, then query and update the IP field.
|
||||||
className="ipayfield"
|
const { payments } = form.getFieldsValue();
|
||||||
data-ipayname="account"
|
if (
|
||||||
type="hidden"
|
payments?.length > 0 &&
|
||||||
value={data?.jobs_by_pk.ro_number}
|
payments?.filter((p) => p?.jobid).length === payments?.length
|
||||||
hidden
|
) {
|
||||||
/>
|
console.log("**Calling refetch.");
|
||||||
<Input
|
refetch({ jobids: payments.map((p) => p.jobid) });
|
||||||
className="ipayfield"
|
}
|
||||||
data-ipayname="email"
|
console.log(
|
||||||
type="hidden"
|
"Acc info",
|
||||||
value={data?.jobs_by_pk.owner.ownr_ea}
|
data,
|
||||||
hidden
|
payments && data && data.jobs.length > 0
|
||||||
/>
|
? data.jobs.map((j) => j.ro_number).join(", ")
|
||||||
{/* Lightbox payment response when it is completed */}
|
: null
|
||||||
<Form.Item name="paymentResponse" hidden>
|
);
|
||||||
<Input type="hidden" value={amount} />
|
return (
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
className="ipayfield"
|
||||||
|
data-ipayname="account"
|
||||||
|
//type="hidden"
|
||||||
|
value={
|
||||||
|
payments && data && data.jobs.length > 0
|
||||||
|
? data.jobs.map((j) => j.ro_number).join(", ")
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
className="ipayfield"
|
||||||
|
data-ipayname="email"
|
||||||
|
// type="hidden"
|
||||||
|
value={
|
||||||
|
payments && data && data.jobs.length > 0
|
||||||
|
? data.jobs.filter((j) => j.ownr_ea)[0]?.ownr_ea
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
shouldUpdate={(prevValues, curValues) =>
|
||||||
|
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 (
|
||||||
|
<Space style={{ float: "right" }}>
|
||||||
|
<Statistic
|
||||||
|
title="Amount To Charge"
|
||||||
|
value={totalAmountToCharge}
|
||||||
|
precision={2}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
className="ipayfield"
|
||||||
|
data-ipayname="amount"
|
||||||
|
//type="hidden"
|
||||||
|
value={totalAmountToCharge?.toFixed(2)}
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
// data-ipayname="submit"
|
||||||
|
className="ipayfield"
|
||||||
|
loading={queryLoading || loading}
|
||||||
|
disabled={!(totalAmountToCharge > 0)}
|
||||||
|
onClick={handleIntelliPayCharge}
|
||||||
|
>
|
||||||
|
{t("job_payments.buttons.proceedtopayment")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<LayoutFormRow grow>
|
{/* Lightbox payment response when it is completed */}
|
||||||
<Form.Item
|
<Form.Item name="paymentResponse" hidden>
|
||||||
label="Amount"
|
<Input type="hidden" />
|
||||||
name="amount"
|
</Form.Item>
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
// message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Row justify="space-around">
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
// data-ipayname="submit"
|
|
||||||
className="ipayfield"
|
|
||||||
disabled={!amount || !jobid}
|
|
||||||
onClick={handleIntelliPayCharge}
|
|
||||||
>
|
|
||||||
{t("job_payments.buttons.proceedtopayment")}
|
|
||||||
</Button>
|
|
||||||
{context?.balance && (
|
|
||||||
<DataLabel
|
|
||||||
valueStyle={{
|
|
||||||
color: context?.balance.getAmount() !== 0 ? "red" : "green",
|
|
||||||
}}
|
|
||||||
label={t("payments.labels.balance")}
|
|
||||||
>
|
|
||||||
{context?.balance.toFormat()}
|
|
||||||
</DataLabel>
|
|
||||||
)}
|
|
||||||
</Row>
|
|
||||||
</LayoutFormRow>
|
|
||||||
</Form>
|
</Form>
|
||||||
</Spin>
|
</Spin>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ function CardPaymentModalContainer({
|
|||||||
{t("job_payments.buttons.goback")}
|
{t("job_payments.buttons.goback")}
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
width="60%"
|
width="80%"
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<CardPaymentModalComponent />
|
<CardPaymentModalComponent />
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ function Header({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCardPaymentContext({
|
setCardPaymentContext({
|
||||||
actions: {},
|
actions: {},
|
||||||
context: null,
|
context: {},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
icon={<Icon component={FaCreditCard} />}
|
icon={<Icon component={FaCreditCard} />}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
useApolloClient,
|
useApolloClient,
|
||||||
useLazyQuery,
|
useLazyQuery,
|
||||||
useMutation,
|
useMutation,
|
||||||
useQuery
|
useQuery,
|
||||||
} from "@apollo/client";
|
} from "@apollo/client";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import { Col, notification, Row } from "antd";
|
import { Col, notification, Row } from "antd";
|
||||||
@@ -20,7 +20,7 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
|||||||
import {
|
import {
|
||||||
DELETE_AVAILABLE_JOB,
|
DELETE_AVAILABLE_JOB,
|
||||||
QUERY_AVAILABLE_JOBS,
|
QUERY_AVAILABLE_JOBS,
|
||||||
QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK
|
QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK,
|
||||||
} from "../../graphql/available-jobs.queries";
|
} from "../../graphql/available-jobs.queries";
|
||||||
import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
|
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
|
||||||
@@ -28,7 +28,7 @@ import { SEARCH_VEHICLE_BY_VIN } from "../../graphql/vehicles.queries";
|
|||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import {
|
import {
|
||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
import confirmDialog from "../../utils/asyncConfirm";
|
import confirmDialog from "../../utils/asyncConfirm";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
@@ -135,6 +135,7 @@ export function JobsAvailableContainer({
|
|||||||
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
|
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
|
||||||
job_totals: newTotals,
|
job_totals: newTotals,
|
||||||
date_open: moment(),
|
date_open: moment(),
|
||||||
|
status: bodyshop.md_ro_statuses.default_imported,
|
||||||
notes: {
|
notes: {
|
||||||
data: {
|
data: {
|
||||||
created_by: currentUser.email,
|
created_by: currentUser.email,
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ export function JobsCloseExportButton({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "jobsuccessexport",
|
key: "jobsuccessexport",
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ export function JobsExportAllButton({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "jobsuccessexport",
|
key: "jobsuccessexport",
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ export function PayableExportAll({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "billsuccessexport",
|
key: "billsuccessexport",
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ export function PayableExportButton({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "billsuccessexport",
|
key: "billsuccessexport",
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
import React, { useState } from "react";
|
|
||||||
import { useMutation, useQuery } from "@apollo/client";
|
import { useMutation, useQuery } from "@apollo/client";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Descriptions,
|
||||||
|
InputNumber,
|
||||||
|
Modal,
|
||||||
|
Space,
|
||||||
|
notification,
|
||||||
|
} from "antd";
|
||||||
|
import axios from "axios";
|
||||||
|
import moment from "moment";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
GET_REFUNDABLE_AMOUNT_BY_JOBID,
|
GET_REFUNDABLE_AMOUNT_BY_JOBID,
|
||||||
INSERT_PAYMENT_RESPONSE,
|
INSERT_PAYMENT_RESPONSE,
|
||||||
QUERY_PAYMENT_RESPONSE_BY_PAYMENT_ID,
|
QUERY_PAYMENT_RESPONSE_BY_PAYMENT_ID,
|
||||||
} from "../../graphql/payment_response.queries";
|
} from "../../graphql/payment_response.queries";
|
||||||
import { Button, Descriptions, InputNumber, Modal, notification } from "antd";
|
|
||||||
import moment from "moment";
|
|
||||||
import axios from "axios";
|
|
||||||
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
|
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
|
||||||
import { useTranslation } from "react-i18next";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
|
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||||
|
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
|
|
||||||
@@ -137,10 +146,10 @@ const PaymentExpandedRowComponent = ({ record, bodyshop }) => {
|
|||||||
{payment_response?.response?.nameOnCard ?? ""}
|
{payment_response?.response?.nameOnCard ?? ""}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label={t("job_payments.titles.amount")}>
|
<Descriptions.Item label={t("job_payments.titles.amount")}>
|
||||||
{record.amount}
|
<CurrencyFormatter>{record.amount}</CurrencyFormatter>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label={t("job_payments.titles.dateOfPayment")}>
|
<Descriptions.Item label={t("job_payments.titles.dateOfPayment")}>
|
||||||
{moment(record.created_at).format("YYYY-MM-DD HH:mm:ss")}
|
{<DateTimeFormatter>{record.created_at}</DateTimeFormatter>}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label={t("job_payments.titles.transactionid")}>
|
<Descriptions.Item label={t("job_payments.titles.transactionid")}>
|
||||||
{record.transactionid}
|
{record.transactionid}
|
||||||
@@ -151,17 +160,22 @@ const PaymentExpandedRowComponent = ({ record, bodyshop }) => {
|
|||||||
<Descriptions.Item label={t("job_payments.titles.paymenttype")}>
|
<Descriptions.Item label={t("job_payments.titles.paymenttype")}>
|
||||||
{record.type}
|
{record.type}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label={t("job_payments.titles.paymentnum")}>
|
||||||
|
{record.paymentnum}
|
||||||
|
</Descriptions.Item>
|
||||||
{payment_response && (
|
{payment_response && (
|
||||||
<Descriptions.Item label={t("job_payments.titles.refundamount")}>
|
<Descriptions.Item label={t("job_payments.titles.refundamount")}>
|
||||||
<InputNumber
|
<Space>
|
||||||
onChange={setRefundAmount}
|
<InputNumber
|
||||||
max={max_refundable_amount}
|
onChange={setRefundAmount}
|
||||||
min={0}
|
max={max_refundable_amount}
|
||||||
/>
|
min={0}
|
||||||
|
/>
|
||||||
|
|
||||||
<Button onClick={() => showConfirm(payment_response)}>
|
<Button onClick={() => showConfirm(payment_response)}>
|
||||||
{t("job_payments.buttons.refundpayment")}
|
{t("job_payments.buttons.refundpayment")}
|
||||||
</Button>
|
</Button>
|
||||||
|
</Space>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
)}
|
)}
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ export function PaymentExportButton({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "paymentsuccessexport",
|
key: "paymentsuccessexport",
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ export function PaymentsExportAllButton({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "paymentsuccessexport",
|
key: "paymentsuccessexport",
|
||||||
|
|||||||
@@ -574,7 +574,6 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
est_co_nm
|
est_co_nm
|
||||||
est_ct_fn
|
est_ct_fn
|
||||||
est_ct_ln
|
est_ct_ln
|
||||||
|
|
||||||
est_ph1
|
est_ph1
|
||||||
est_ea
|
est_ea
|
||||||
selling_dealer
|
selling_dealer
|
||||||
@@ -746,6 +745,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
jobid
|
jobid
|
||||||
amount
|
amount
|
||||||
payer
|
payer
|
||||||
|
paymentnum
|
||||||
created_at
|
created_at
|
||||||
transactionid
|
transactionid
|
||||||
memo
|
memo
|
||||||
|
|||||||
@@ -28,16 +28,14 @@ export const QUERY_PAYMENT_RESPONSE_BY_PAYMENT_ID = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const QUERY_RO_AND_OWNER_BY_JOB_PK = gql`
|
export const QUERY_RO_AND_OWNER_BY_JOB_PKS = gql`
|
||||||
query QUERY_RO_AND_OWNER_BY_JOB_PK($jobid: uuid!) {
|
query QUERY_RO_AND_OWNER_BY_JOB_PKS($jobids: [uuid!]!) {
|
||||||
jobs_by_pk(id: $jobid) {
|
jobs(where: { id: { _in: $jobids } }) {
|
||||||
ro_number
|
ro_number
|
||||||
owner {
|
ownr_fn
|
||||||
ownr_fn
|
ownr_ln
|
||||||
ownr_ln
|
ownr_ea
|
||||||
ownr_ea
|
ownr_zip
|
||||||
ownr_zip
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1211,6 +1211,7 @@
|
|||||||
"payer": "Payer",
|
"payer": "Payer",
|
||||||
"payername": "Payer Name",
|
"payername": "Payer Name",
|
||||||
"paymentid": "Payment Reference ID",
|
"paymentid": "Payment Reference ID",
|
||||||
|
"paymentnum": "Payment Number",
|
||||||
"paymenttype": "Payment Type",
|
"paymenttype": "Payment Type",
|
||||||
"refundamount": "Refund Amount",
|
"refundamount": "Refund Amount",
|
||||||
"transactionid": "Transaction ID"
|
"transactionid": "Transaction ID"
|
||||||
@@ -2207,7 +2208,8 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"exporting": "Error exporting payment(s). {{error}}",
|
"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": {
|
"fields": {
|
||||||
"amount": "Amount",
|
"amount": "Amount",
|
||||||
|
|||||||
@@ -1211,6 +1211,7 @@
|
|||||||
"payer": "",
|
"payer": "",
|
||||||
"payername": "",
|
"payername": "",
|
||||||
"paymentid": "",
|
"paymentid": "",
|
||||||
|
"paymentnum": "",
|
||||||
"paymenttype": "",
|
"paymenttype": "",
|
||||||
"refundamount": "",
|
"refundamount": "",
|
||||||
"transactionid": ""
|
"transactionid": ""
|
||||||
@@ -2207,7 +2208,8 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"exporting": "",
|
"exporting": "",
|
||||||
"exporting-partner": ""
|
"exporting-partner": "",
|
||||||
|
"inserting": ""
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"amount": "",
|
"amount": "",
|
||||||
|
|||||||
@@ -1211,6 +1211,7 @@
|
|||||||
"payer": "",
|
"payer": "",
|
||||||
"payername": "",
|
"payername": "",
|
||||||
"paymentid": "",
|
"paymentid": "",
|
||||||
|
"paymentnum": "",
|
||||||
"paymenttype": "",
|
"paymenttype": "",
|
||||||
"refundamount": "",
|
"refundamount": "",
|
||||||
"transactionid": ""
|
"transactionid": ""
|
||||||
@@ -2207,7 +2208,8 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"exporting": "",
|
"exporting": "",
|
||||||
"exporting-partner": ""
|
"exporting-partner": "",
|
||||||
|
"inserting": ""
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"amount": "",
|
"amount": "",
|
||||||
|
|||||||
@@ -3274,6 +3274,7 @@
|
|||||||
- cat_no
|
- cat_no
|
||||||
- category
|
- category
|
||||||
- cieca_pfl
|
- cieca_pfl
|
||||||
|
- cieca_pft
|
||||||
- cieca_stl
|
- cieca_stl
|
||||||
- cieca_ttl
|
- cieca_ttl
|
||||||
- ciecaid
|
- ciecaid
|
||||||
@@ -3541,6 +3542,7 @@
|
|||||||
- cat_no
|
- cat_no
|
||||||
- category
|
- category
|
||||||
- cieca_pfl
|
- cieca_pfl
|
||||||
|
- cieca_pft
|
||||||
- cieca_stl
|
- cieca_stl
|
||||||
- cieca_ttl
|
- cieca_ttl
|
||||||
- ciecaid
|
- ciecaid
|
||||||
@@ -3819,6 +3821,7 @@
|
|||||||
- cat_no
|
- cat_no
|
||||||
- category
|
- category
|
||||||
- cieca_pfl
|
- cieca_pfl
|
||||||
|
- cieca_pft
|
||||||
- cieca_stl
|
- cieca_stl
|
||||||
- cieca_ttl
|
- cieca_ttl
|
||||||
- ciecaid
|
- ciecaid
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."jobs" add column "cieca_pft" jsonb
|
||||||
|
-- null default jsonb_build_object();
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."jobs" add column "cieca_pft" jsonb
|
||||||
|
null default jsonb_build_object();
|
||||||
Reference in New Issue
Block a user