diff --git a/src/components/Dashboard/Finance/Payments/AuthorisePayment.jsx b/src/components/Dashboard/Finance/Payments/AuthorisePayment.jsx
new file mode 100644
index 0000000..c7822d0
--- /dev/null
+++ b/src/components/Dashboard/Finance/Payments/AuthorisePayment.jsx
@@ -0,0 +1,46 @@
+import { useState, useContext } from 'react'
+import PropTypes from 'prop-types'
+import { ApiServerContext } from '../../context/ApiServerContext'
+import { message } from 'antd'
+import MessageDialogView from '../../common/MessageDialogView.jsx'
+
+const AuthorisePayment = ({ onOk, objectData }) => {
+ const [authoriseLoading, setAuthoriseLoading] = useState(false)
+ const { sendObjectFunction } = useContext(ApiServerContext)
+
+ const handleAuthorise = async () => {
+ setAuthoriseLoading(true)
+ try {
+ const result = await sendObjectFunction(
+ objectData._id,
+ 'Payment',
+ 'authorise'
+ )
+ if (result) {
+ message.success('Payment authorised successfully')
+ onOk(result)
+ }
+ } catch (error) {
+ console.error('Error authorising payment:', error)
+ } finally {
+ setAuthoriseLoading(false)
+ }
+ }
+
+ return (
+
+ )
+}
+
+AuthorisePayment.propTypes = {
+ onOk: PropTypes.func.isRequired,
+ objectData: PropTypes.object
+}
+
+export default AuthorisePayment
diff --git a/src/components/Dashboard/Finance/Payments/CancelPayment.jsx b/src/components/Dashboard/Finance/Payments/CancelPayment.jsx
new file mode 100644
index 0000000..b98083a
--- /dev/null
+++ b/src/components/Dashboard/Finance/Payments/CancelPayment.jsx
@@ -0,0 +1,46 @@
+import { useState, useContext } from 'react'
+import PropTypes from 'prop-types'
+import { ApiServerContext } from '../../context/ApiServerContext'
+import { message } from 'antd'
+import MessageDialogView from '../../common/MessageDialogView.jsx'
+
+const CancelPayment = ({ onOk, objectData }) => {
+ const [cancelLoading, setCancelLoading] = useState(false)
+ const { sendObjectFunction } = useContext(ApiServerContext)
+
+ const handleCancel = async () => {
+ setCancelLoading(true)
+ try {
+ const result = await sendObjectFunction(
+ objectData._id,
+ 'Payment',
+ 'cancel'
+ )
+ if (result) {
+ message.success('Payment cancelled successfully')
+ onOk(result)
+ }
+ } catch (error) {
+ console.error('Error cancelling payment:', error)
+ } finally {
+ setCancelLoading(false)
+ }
+ }
+
+ return (
+
+ )
+}
+
+CancelPayment.propTypes = {
+ onOk: PropTypes.func.isRequired,
+ objectData: PropTypes.object
+}
+
+export default CancelPayment
diff --git a/src/components/Dashboard/Finance/Payments/DeclinePayment.jsx b/src/components/Dashboard/Finance/Payments/DeclinePayment.jsx
new file mode 100644
index 0000000..ca5014e
--- /dev/null
+++ b/src/components/Dashboard/Finance/Payments/DeclinePayment.jsx
@@ -0,0 +1,46 @@
+import { useState, useContext } from 'react'
+import PropTypes from 'prop-types'
+import { ApiServerContext } from '../../context/ApiServerContext'
+import { message } from 'antd'
+import MessageDialogView from '../../common/MessageDialogView.jsx'
+
+const DeclinePayment = ({ onOk, objectData }) => {
+ const [declineLoading, setDeclineLoading] = useState(false)
+ const { sendObjectFunction } = useContext(ApiServerContext)
+
+ const handleDecline = async () => {
+ setDeclineLoading(true)
+ try {
+ const result = await sendObjectFunction(
+ objectData._id,
+ 'Payment',
+ 'decline'
+ )
+ if (result) {
+ message.success('Payment declined successfully')
+ onOk(result)
+ }
+ } catch (error) {
+ console.error('Error declining payment:', error)
+ } finally {
+ setDeclineLoading(false)
+ }
+ }
+
+ return (
+
+ )
+}
+
+DeclinePayment.propTypes = {
+ onOk: PropTypes.func.isRequired,
+ objectData: PropTypes.object
+}
+
+export default DeclinePayment
diff --git a/src/components/Dashboard/Finance/Payments/NewPayment.jsx b/src/components/Dashboard/Finance/Payments/NewPayment.jsx
index 71c5663..840e638 100644
--- a/src/components/Dashboard/Finance/Payments/NewPayment.jsx
+++ b/src/components/Dashboard/Finance/Payments/NewPayment.jsx
@@ -53,6 +53,8 @@ const NewPayment = ({ onOk, reset, defaultValues }) => {
updatedAt: false,
_reference: false,
postedAt: false,
+ authorisedAt: false,
+ declinedAt: false,
cancelledAt: false
}}
isEditing={false}
diff --git a/src/components/Dashboard/Finance/Payments/PaymentInfo.jsx b/src/components/Dashboard/Finance/Payments/PaymentInfo.jsx
index b574b36..8bb6430 100644
--- a/src/components/Dashboard/Finance/Payments/PaymentInfo.jsx
+++ b/src/components/Dashboard/Finance/Payments/PaymentInfo.jsx
@@ -24,6 +24,9 @@ import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
import ScrollBox from '../../common/ScrollBox.jsx'
import { getModelByName } from '../../../../database/ObjectModels.js'
import PostPayment from './PostPayment.jsx'
+import AuthorisePayment from './AuthorisePayment.jsx'
+import DeclinePayment from './DeclinePayment.jsx'
+import CancelPayment from './CancelPayment.jsx'
const log = loglevel.getLogger('PaymentInfo')
log.setLevel(config.logLevel)
@@ -48,6 +51,9 @@ const PaymentInfo = () => {
objectData: {}
})
const [postPaymentOpen, setPostPaymentOpen] = useState(false)
+ const [authorisePaymentOpen, setAuthorisePaymentOpen] = useState(false)
+ const [declinePaymentOpen, setDeclinePaymentOpen] = useState(false)
+ const [cancelPaymentOpen, setCancelPaymentOpen] = useState(false)
const actions = {
edit: () => {
@@ -69,6 +75,18 @@ const PaymentInfo = () => {
post: () => {
setPostPaymentOpen(true)
return true
+ },
+ authorise: () => {
+ setAuthorisePaymentOpen(true)
+ return true
+ },
+ decline: () => {
+ setDeclinePaymentOpen(true)
+ return true
+ },
+ cancel: () => {
+ setCancelPaymentOpen(true)
+ return true
}
}
@@ -234,6 +252,60 @@ const PaymentInfo = () => {
objectData={objectFormState.objectData}
/>
+ {
+ setAuthorisePaymentOpen(false)
+ }}
+ width={515}
+ footer={null}
+ destroyOnHidden={true}
+ centered={true}
+ >
+ {
+ setAuthorisePaymentOpen(false)
+ objectFormRef?.current.handleFetchObject()
+ }}
+ objectData={objectFormState.objectData}
+ />
+
+ {
+ setDeclinePaymentOpen(false)
+ }}
+ width={515}
+ footer={null}
+ destroyOnHidden={true}
+ centered={true}
+ >
+ {
+ setDeclinePaymentOpen(false)
+ objectFormRef?.current.handleFetchObject()
+ }}
+ objectData={objectFormState.objectData}
+ />
+
+ {
+ setCancelPaymentOpen(false)
+ }}
+ width={515}
+ footer={null}
+ destroyOnHidden={true}
+ centered={true}
+ >
+ {
+ setCancelPaymentOpen(false)
+ objectFormRef?.current.handleFetchObject()
+ }}
+ objectData={objectFormState.objectData}
+ />
+
>
)
}
diff --git a/src/components/Dashboard/common/StateTag.jsx b/src/components/Dashboard/common/StateTag.jsx
index 89220a7..7c9c1b9 100644
--- a/src/components/Dashboard/common/StateTag.jsx
+++ b/src/components/Dashboard/common/StateTag.jsx
@@ -140,6 +140,14 @@ const StateTag = ({ state, showBadge = true, style = {} }) => {
status = 'magenta'
text = 'Posted'
break
+ case 'authorised':
+ status = 'success'
+ text = 'Authorised'
+ break
+ case 'declined':
+ status = 'error'
+ text = 'Declined'
+ break
case 'received':
status = 'success'
text = 'Received'
diff --git a/src/database/models/Payment.js b/src/database/models/Payment.js
index ce74451..0de2816 100644
--- a/src/database/models/Payment.js
+++ b/src/database/models/Payment.js
@@ -82,6 +82,35 @@ export const Payment = {
return objectData?.state?.type == 'draft'
}
},
+ {
+ name: 'authorise',
+ label: 'Authorise',
+ type: 'button',
+ icon: CheckIcon,
+ url: (_id) =>
+ `/dashboard/finance/payments/info?paymentId=${_id}&action=authorise`,
+ disabled: (objectData) => {
+ return objectData?.state?.type != 'posted'
+ },
+ visible: (objectData) => {
+ return objectData?.state?.type == 'posted'
+ }
+ },
+ {
+ name: 'decline',
+ label: 'Decline',
+ type: 'button',
+ icon: XMarkIcon,
+ danger: true,
+ url: (_id) =>
+ `/dashboard/finance/payments/info?paymentId=${_id}&action=decline`,
+ disabled: (objectData) => {
+ return objectData?.state?.type != 'posted'
+ },
+ visible: (objectData) => {
+ return objectData?.state?.type == 'posted'
+ }
+ },
{
name: 'cancel',
label: 'Cancel',
@@ -91,13 +120,10 @@ export const Payment = {
url: (_id) =>
`/dashboard/finance/payments/info?paymentId=${_id}&action=cancel`,
disabled: (objectData) => {
- return objectData?.state?.type == 'cancelled'
+ return objectData?.state?.type != 'posted'
},
visible: (objectData) => {
- return (
- objectData?.state?.type == 'draft' ||
- objectData?.state?.type == 'posted'
- )
+ return objectData?.state?.type == 'posted'
}
}
],
@@ -197,6 +223,20 @@ export const Payment = {
readOnly: true,
columnWidth: 175
},
+ {
+ name: 'authorisedAt',
+ label: 'Authorised At',
+ type: 'dateTime',
+ readOnly: true,
+ columnWidth: 175
+ },
+ {
+ name: 'declinedAt',
+ label: 'Declined At',
+ type: 'dateTime',
+ readOnly: true,
+ columnWidth: 175
+ },
{
name: 'cancelledAt',
label: 'Cancelled At',
@@ -256,6 +296,34 @@ export const Payment = {
prefix: '£',
roundNumber: 2,
color: 'cyan'
+ },
+ {
+ name: 'authorised.authorisedCount.count',
+ label: 'Authorised',
+ type: 'number',
+ color: 'green'
+ },
+ {
+ name: 'authorised.authorisedAmount.sum',
+ label: 'Authorised Amount',
+ type: 'number',
+ prefix: '£',
+ roundNumber: 2,
+ color: 'green'
+ },
+ {
+ name: 'declined.declinedCount.count',
+ label: 'Declined',
+ type: 'number',
+ color: 'red'
+ },
+ {
+ name: 'declined.declinedAmount.sum',
+ label: 'Declined Amount',
+ type: 'number',
+ prefix: '£',
+ roundNumber: 2,
+ color: 'red'
}
]
}