Merged in release/2023-09-15 (pull request #980)

Release/2023 09 15
This commit is contained in:
Patrick Fic
2023-09-15 17:40:34 +00:00
20 changed files with 315 additions and 173 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 />

View File

@@ -254,7 +254,7 @@ function Header({
onClick={() => { onClick={() => {
setCardPaymentContext({ setCardPaymentContext({
actions: {}, actions: {},
context: null, context: {},
}); });
}} }}
icon={<Icon component={FaCreditCard} />} icon={<Icon component={FaCreditCard} />}

View File

@@ -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,

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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>

View File

@@ -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",

View File

@@ -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",

View File

@@ -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

View File

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

View File

@@ -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",

View File

@@ -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": "",

View File

@@ -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": "",

View File

@@ -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

View File

@@ -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();

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "cieca_pft" jsonb
null default jsonb_build_object();