diff --git a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx
index 301fec91f..eef6dfaf5 100644
--- a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx
+++ b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx
@@ -7,6 +7,7 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
+import JobTotalsCashDiscount from "./jobs-totals.cash-discount-display.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -169,13 +170,7 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
},
{
key: t("jobs.labels.total_cust_payable"),
- total: Dinero(job.job_totals.totals.custPayable.total)
- .add(
- Dinero(job.job_totals.totals.custPayable.total).percentage(
- bodyshop.intellipay_config?.cash_discount_percentage || 0
- )
- )
- .toJSON(),
+ render: ,
bold: true
}
]
@@ -211,7 +206,7 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
dataIndex: "total",
key: "total",
align: "right",
- render: (text, record) => Dinero(record.total).toFormat(),
+ render: (text, record) => (record.render ? record.render : Dinero(record.total).toFormat()),
width: "20%",
onCell: (record, rowIndex) => {
return { style: { fontWeight: record.bold && "bold" } };
diff --git a/client/src/components/job-totals-table/jobs-totals.cash-discount-display.component.jsx b/client/src/components/job-totals-table/jobs-totals.cash-discount-display.component.jsx
new file mode 100644
index 000000000..9a529866f
--- /dev/null
+++ b/client/src/components/job-totals-table/jobs-totals.cash-discount-display.component.jsx
@@ -0,0 +1,57 @@
+import { notification, Spin } from "antd";
+import axios from "axios";
+import Dinero from "dinero.js";
+import React, { useCallback, useEffect, useState } from "react";
+
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop } from "../../redux/user/user.selectors";
+const mapStateToProps = createStructuredSelector({
+ bodyshop: selectBodyshop
+});
+const mapDispatchToProps = (dispatch) => ({
+});
+export default connect(mapStateToProps, mapDispatchToProps)(JobTotalsCashDiscount);
+
+export function JobTotalsCashDiscount({ bodyshop, amountDinero }) {
+ const [loading, setLoading] = useState(true);
+ const [fee, setFee] = useState(0);
+
+ const fetchData = useCallback(async () => {
+ if (amountDinero && bodyshop) {
+ setLoading(true);
+ let response;
+ try {
+ response = await axios.post("/intellipay/checkfee", {
+ bodyshop: { id: bodyshop.id, imexshopid: bodyshop.imexshopid },
+ amount: Dinero(amountDinero).toFormat("0.00")
+ });
+
+ if (response?.data?.error) {
+ notification.open({
+ type: "error",
+ message: response.data?.error || "Error encountered contacting IntelliPay service."
+ });
+ } else {
+ setFee(response.data?.fee || 0);
+ }
+ } catch (error) {
+ notification.open({
+ type: "error",
+ message: error.response?.data?.error || "Error encountered contacting IntelliPay service."
+ });
+ } finally {
+ setLoading(false);
+ }
+ }
+ }, [amountDinero, bodyshop]);
+
+ useEffect(() => {
+ fetchData();
+ }, [fetchData, bodyshop, amountDinero]);
+
+ if (loading) return ;
+ return Dinero(amountDinero)
+ .add(Dinero({ amount: Math.round(fee * 100) }))
+ .toFormat();
+}
diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js
index 080deec90..43758f97e 100644
--- a/server/intellipay/intellipay.js
+++ b/server/intellipay/intellipay.js
@@ -149,6 +149,52 @@ exports.generate_payment_url = async (req, res) => {
}
};
+//Reference: https://intellipay.com/dist/webapi26.html#operation/fee
+exports.checkfee = async (req, res) => {
+ logger.log("intellipay-fee-check", "DEBUG", req.user?.email, null, null);
+
+ //If there's no amount, there can't be a fee. Skip the call.
+ if (!req.body.amount || req.body.amount <= 0) {
+ res.json({ fee: 0 });
+ return;
+ }
+
+ const shopCredentials = await getShopCredentials(req.body.bodyshop);
+
+ try {
+ const options = {
+ method: "POST",
+ headers: { "content-type": "application/x-www-form-urlencoded" },
+ //TODO: Move these to environment variables/database.
+ data: qs.stringify(
+ {
+ method: "fee",
+ ...shopCredentials,
+ amount: req.body.amount,
+ paymenttype: `"CC"`
+ },
+ { sort: false } //ColdFusion Query Strings depend on order. This preserves it.
+ ),
+ url: `https://${domain}.cpteller.com/api/26/webapi.cfc`
+ };
+
+ const response = await axios(options);
+ if (response.data?.error) {
+ res.status(400).json({ error: response.data.error });
+ } else if (response.data < 0) {
+ res.json({ error: "Fee amount negative. Check API credentials & account configuration." });
+ } else {
+ res.json({ fee: response.data });
+ }
+ } catch (error) {
+ //console.log(error);
+ logger.log("intellipay-fee-check-error", "ERROR", req.user?.email, null, {
+ error: error.message
+ });
+ res.status(400).json({ error });
+ }
+};
+
exports.postback = async (req, res) => {
try {
logger.log("intellipay-postback", "DEBUG", req.user?.email, null, req.body);
diff --git a/server/routes/intellipayRoutes.js b/server/routes/intellipayRoutes.js
index 47f09ffb0..ad0b87323 100644
--- a/server/routes/intellipayRoutes.js
+++ b/server/routes/intellipayRoutes.js
@@ -1,11 +1,12 @@
const express = require("express");
const router = express.Router();
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
-const { lightbox_credentials, payment_refund, generate_payment_url, postback } = require("../intellipay/intellipay");
+const { lightbox_credentials, payment_refund, generate_payment_url, postback, checkfee } = require("../intellipay/intellipay");
router.post("/lightbox_credentials", validateFirebaseIdTokenMiddleware, lightbox_credentials);
router.post("/payment_refund", validateFirebaseIdTokenMiddleware, payment_refund);
router.post("/generate_payment_url", validateFirebaseIdTokenMiddleware, generate_payment_url);
+router.post("/checkfee", validateFirebaseIdTokenMiddleware, checkfee);
router.post("/postback", postback);
module.exports = router;