@kenyaemr/esm-billing-app 5.4.1-pre.1995 → 5.4.1-pre.2000
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +71 -71
- package/dist/290.js +1 -1
- package/dist/{668.js → 970.js} +1 -1
- package/dist/970.js.map +1 -0
- package/dist/kenyaemr-esm-billing-app.js +1 -1
- package/dist/kenyaemr-esm-billing-app.js.buildmanifest.json +29 -29
- package/dist/main.js +3 -3
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/config-schema.ts +6 -0
- package/src/invoice/invoice.component.tsx +1 -0
- package/src/invoice/payments/initiate-payment/initiate-payment.component.tsx +59 -27
- package/src/invoice/payments/initiate-payment/initiate-payment.scss +18 -8
- package/src/invoice/payments/payment-status-ckecker.modal.tsx +136 -0
- package/src/invoice/payments/payments.resource.ts +32 -1
- package/src/invoice/payments/payments.scss +21 -0
- package/dist/668.js.map +0 -1
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"billableServicesHome","route":"billable-services"},{"component":"requirePaymentModal","routeRegex":"^patient/.+/chart","online":true,"offline":false}],"extensions":[{"component":"billingDashboardLink","name":"billing-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"billing","title":"billing","slot":"billing-dashboard-slot"}},{"component":"benefitsPackageDashboardLink","name":"benefits-package-dashboard-link","slot":"patient-chart-dashboard-slot","meta":{"name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot","path":"insurance-benefits","columns":1,"columnSpan":1},"featureFlag":"healthInformationExchange"},{"component":"benefitsPackage","name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot"},{"component":"root","name":"billing-dashboard-root","slot":"billing-dashboard-slot"},{"component":"benefitsEligibilyRequestForm","name":"benefits-eligibility-request-form"},{"component":"benefitsPreAuthForm","name":"benefits-pre-auth-form"},{"name":"billing-patient-summary","component":"billingPatientSummary","slot":"patient-chart-billing-dashboard-slot","order":10,"meta":{"columnSpan":4}},{"name":"billing-summary-dashboard-link","component":"billingSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":11,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-billing-dashboard-slot","path":"Billing","layoutMode":"anchored"}},{"name":"billing-check-in-form","slot":"extra-visit-attribute-slot","component":"billingCheckInForm"},{"name":"require-billing-modal","component":"requirePaymentModal"},{"name":"patient-banner-billing-tags","component":"visitAttributeTags","slot":"patient-banner-tags-slot","order":2},{"name":"initiate-payment-modal","component":"initiatePaymentDialog"},{"name":"delete-billableservice-modal","component":"deleteBillableServiceModal"},{"name":"refund-bill-modal","component":"refundBillModal"},{"name":"delete-bill-modal","component":"deleteBillModal"},{"name":"lab-order-billable-item","component":"labOrder","slot":"top-of-lab-order-form-slot"},{"name":"procedure-order-billable-item","component":"procedureOrder","slot":"top-of-procedure-order-form-slot"},{"name":"imaging-order-billable-item","component":"imagingOrder","slot":"top-of-imaging-order-form-slot"},{"name":"price-info-order","component":"priceInfoOrder"},{"name":"drug-order-billable-item","component":"drugOrder","slot":"medication-info-slot"},{"name":"order-action-button","component":"orderActionButton","slots":["prescription-action-button-slot","imaging-orders-action","procedure-orders-action","tests-ordered-actions-slot"],"order":0},{"component":"billingOverviewLink","name":"billing-overview-link","order":0,"slot":"billing-dashboard-link-slot"},{"component":"paymentHistoryLink","name":"payment-history-link","slot":"billing-dashboard-link-slot"},{"component":"paymentPointsLink","name":"payment-points-link","slot":"billing-dashboard-link-slot"},{"component":"paymentModesLink","name":"payment-modes-link","slot":"billing-dashboard-link-slot"},{"component":"billManagerLink","name":"bill-manager-link","slot":"billing-dashboard-link-slot"},{"component":"chargeableItemsLink","name":"chargeable-items-link","slot":"billing-dashboard-link-slot"},{"component":"billableExemptionsLink","name":"billable-exemptions-link","slot":"billing-dashboard-link-slot"},{"component":"claimsManagementSideNavGroup","name":"claims-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"claims-management","title":"Claims management Overview","slot":"case-management-slot"},"featureFlag":"healthInformationExchange"},{"component":"claimsManagementOverviewDashboardLink","name":"claims-management-overview-link","order":0,"slot":"claims-management-dashboard-link-slot"},{"component":"preAuthRequestsDashboardLink","name":"preauthrequest-overview-link","slot":"claims-management-dashboard-link-slot"},{"component":"claimsOverview","name":"claims-overview-dashboard-link","slot":"claims-management-overview-slot"},{"component":"waiveBillActionButton","name":"waive-bill-action-button","slot":"bill-actions-slot"},{"component":"deleteBillActionButton","name":"delete-bill-action-button","slot":"bill-actions-slot"},{"component":"refundLineItem","name":"refund-line-item","slot":"bill-actions-overflow-menu-slot"},{"name":"edit-line-item","component":"editLineItem","slot":"bill-actions-overflow-menu-slot"},{"name":"cancel-line-item","component":"cancelLineItem","slot":"bill-actions-overflow-menu-slot"}],"workspaces":[{"name":"create-bill-workspace","component":"createBillWorkspace","title":"Create Bill Workspace","type":"other-form"},{"name":"waive-bill-form","component":"waiveBillForm","title":"Waive Bill Form","type":"other-form"},{"name":"edit-bill-form","component":"editBillForm","title":"Edit Bill Form","type":"other-form"},{"name":"billable-service-form","component":"addServiceForm","title":"Create Charge Item Form","type":"other-form"},{"name":"commodity-form","component":"addCommodityForm","title":"Create Charge Item Form","type":"other-form"},{"name":"billing-form","component":"billingForm","title":"Billing Form","type":"other-form","width":"extra-wide"},{"name":"payment-mode-workspace","component":"paymentModeWorkspace","title":"Payment Mode Workspace","type":"other-form"},{"name":"cancel-bill-workspace","component":"cancelBillWorkspace","title":"Cancel Bill Workspace","type":"other-form"},{"name":"bill-deposit-workspace","component":"billDepositWorkspace","title":"Bill Deposit Workspace","type":"other-form"}],"modals":[{"name":"create-payment-point","component":"createPaymentPoint"},{"name":"clock-out-modal","component":"clockOut"},{"name":"bulk-import-billable-services-modal","component":"bulkImportBillableServicesModal"},{"name":"delete-payment-mode-modal","component":"deletePaymentModeModal"},{"name":"retry-claim-request-modal","component":"retryClaimRequestModal"},{"name":"paid-bill-receipt-print-preview-modal","component":"paidBillReceiptPrintPreviewModal"},{"name":"clock-in-modal","component":"clockIn"},{"name":"create-bill-item-modal","component":"createBillItemModal"}],"version":"5.4.1-pre.
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"billableServicesHome","route":"billable-services"},{"component":"requirePaymentModal","routeRegex":"^patient/.+/chart","online":true,"offline":false}],"extensions":[{"component":"billingDashboardLink","name":"billing-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"billing","title":"billing","slot":"billing-dashboard-slot"}},{"component":"benefitsPackageDashboardLink","name":"benefits-package-dashboard-link","slot":"patient-chart-dashboard-slot","meta":{"name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot","path":"insurance-benefits","columns":1,"columnSpan":1},"featureFlag":"healthInformationExchange"},{"component":"benefitsPackage","name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot"},{"component":"root","name":"billing-dashboard-root","slot":"billing-dashboard-slot"},{"component":"benefitsEligibilyRequestForm","name":"benefits-eligibility-request-form"},{"component":"benefitsPreAuthForm","name":"benefits-pre-auth-form"},{"name":"billing-patient-summary","component":"billingPatientSummary","slot":"patient-chart-billing-dashboard-slot","order":10,"meta":{"columnSpan":4}},{"name":"billing-summary-dashboard-link","component":"billingSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":11,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-billing-dashboard-slot","path":"Billing","layoutMode":"anchored"}},{"name":"billing-check-in-form","slot":"extra-visit-attribute-slot","component":"billingCheckInForm"},{"name":"require-billing-modal","component":"requirePaymentModal"},{"name":"patient-banner-billing-tags","component":"visitAttributeTags","slot":"patient-banner-tags-slot","order":2},{"name":"initiate-payment-modal","component":"initiatePaymentDialog"},{"name":"delete-billableservice-modal","component":"deleteBillableServiceModal"},{"name":"refund-bill-modal","component":"refundBillModal"},{"name":"delete-bill-modal","component":"deleteBillModal"},{"name":"lab-order-billable-item","component":"labOrder","slot":"top-of-lab-order-form-slot"},{"name":"procedure-order-billable-item","component":"procedureOrder","slot":"top-of-procedure-order-form-slot"},{"name":"imaging-order-billable-item","component":"imagingOrder","slot":"top-of-imaging-order-form-slot"},{"name":"price-info-order","component":"priceInfoOrder"},{"name":"drug-order-billable-item","component":"drugOrder","slot":"medication-info-slot"},{"name":"order-action-button","component":"orderActionButton","slots":["prescription-action-button-slot","imaging-orders-action","procedure-orders-action","tests-ordered-actions-slot"],"order":0},{"component":"billingOverviewLink","name":"billing-overview-link","order":0,"slot":"billing-dashboard-link-slot"},{"component":"paymentHistoryLink","name":"payment-history-link","slot":"billing-dashboard-link-slot"},{"component":"paymentPointsLink","name":"payment-points-link","slot":"billing-dashboard-link-slot"},{"component":"paymentModesLink","name":"payment-modes-link","slot":"billing-dashboard-link-slot"},{"component":"billManagerLink","name":"bill-manager-link","slot":"billing-dashboard-link-slot"},{"component":"chargeableItemsLink","name":"chargeable-items-link","slot":"billing-dashboard-link-slot"},{"component":"billableExemptionsLink","name":"billable-exemptions-link","slot":"billing-dashboard-link-slot"},{"component":"claimsManagementSideNavGroup","name":"claims-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"claims-management","title":"Claims management Overview","slot":"case-management-slot"},"featureFlag":"healthInformationExchange"},{"component":"claimsManagementOverviewDashboardLink","name":"claims-management-overview-link","order":0,"slot":"claims-management-dashboard-link-slot"},{"component":"preAuthRequestsDashboardLink","name":"preauthrequest-overview-link","slot":"claims-management-dashboard-link-slot"},{"component":"claimsOverview","name":"claims-overview-dashboard-link","slot":"claims-management-overview-slot"},{"component":"waiveBillActionButton","name":"waive-bill-action-button","slot":"bill-actions-slot"},{"component":"deleteBillActionButton","name":"delete-bill-action-button","slot":"bill-actions-slot"},{"component":"refundLineItem","name":"refund-line-item","slot":"bill-actions-overflow-menu-slot"},{"name":"edit-line-item","component":"editLineItem","slot":"bill-actions-overflow-menu-slot"},{"name":"cancel-line-item","component":"cancelLineItem","slot":"bill-actions-overflow-menu-slot"}],"workspaces":[{"name":"create-bill-workspace","component":"createBillWorkspace","title":"Create Bill Workspace","type":"other-form"},{"name":"waive-bill-form","component":"waiveBillForm","title":"Waive Bill Form","type":"other-form"},{"name":"edit-bill-form","component":"editBillForm","title":"Edit Bill Form","type":"other-form"},{"name":"billable-service-form","component":"addServiceForm","title":"Create Charge Item Form","type":"other-form"},{"name":"commodity-form","component":"addCommodityForm","title":"Create Charge Item Form","type":"other-form"},{"name":"billing-form","component":"billingForm","title":"Billing Form","type":"other-form","width":"extra-wide"},{"name":"payment-mode-workspace","component":"paymentModeWorkspace","title":"Payment Mode Workspace","type":"other-form"},{"name":"cancel-bill-workspace","component":"cancelBillWorkspace","title":"Cancel Bill Workspace","type":"other-form"},{"name":"bill-deposit-workspace","component":"billDepositWorkspace","title":"Bill Deposit Workspace","type":"other-form"}],"modals":[{"name":"create-payment-point","component":"createPaymentPoint"},{"name":"clock-out-modal","component":"clockOut"},{"name":"bulk-import-billable-services-modal","component":"bulkImportBillableServicesModal"},{"name":"delete-payment-mode-modal","component":"deletePaymentModeModal"},{"name":"retry-claim-request-modal","component":"retryClaimRequestModal"},{"name":"paid-bill-receipt-print-preview-modal","component":"paidBillReceiptPrintPreviewModal"},{"name":"clock-in-modal","component":"clockIn"},{"name":"create-bill-item-modal","component":"createBillItemModal"}],"version":"5.4.1-pre.2000"}
|
package/package.json
CHANGED
package/src/config-schema.ts
CHANGED
|
@@ -25,6 +25,7 @@ export interface BillingConfig {
|
|
|
25
25
|
patientBillsUrl: string;
|
|
26
26
|
nationalIdUUID: string;
|
|
27
27
|
isPDSLFacility: boolean;
|
|
28
|
+
mobileMoneyPaymentModeUUID: string;
|
|
28
29
|
concepts: {
|
|
29
30
|
emergencyPriorityConceptUuid: string;
|
|
30
31
|
};
|
|
@@ -41,6 +42,11 @@ export const configSchema: ConfigSchema = {
|
|
|
41
42
|
_description: 'A flag for PDSL facilities',
|
|
42
43
|
_default: false,
|
|
43
44
|
},
|
|
45
|
+
mobileMoneyPaymentModeUUID: {
|
|
46
|
+
_type: Type.UUID,
|
|
47
|
+
_description: 'Mobile money payment method uuid',
|
|
48
|
+
_default: '28989582-e8c3-46b0-96d0-c249cb06d5c6',
|
|
49
|
+
},
|
|
44
50
|
shaIdentificationNumberUUID: {
|
|
45
51
|
_type: Type.String,
|
|
46
52
|
_description: 'Social Health Authority Identification Number',
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Button,
|
|
3
|
+
ButtonSet,
|
|
4
|
+
ContentSwitcher,
|
|
3
5
|
Form,
|
|
4
6
|
InlineNotification,
|
|
5
7
|
Layer,
|
|
6
8
|
Loading,
|
|
7
9
|
ModalBody,
|
|
10
|
+
ModalFooter,
|
|
8
11
|
ModalHeader,
|
|
9
12
|
NumberInputSkeleton,
|
|
13
|
+
Switch,
|
|
10
14
|
TextInput,
|
|
11
15
|
} from '@carbon/react';
|
|
12
16
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
@@ -20,7 +24,8 @@ import { useSystemSetting } from '../../../hooks/getMflCode';
|
|
|
20
24
|
import { usePatientAttributes } from '../../../hooks/usePatientAttributes';
|
|
21
25
|
import { useRequestStatus } from '../../../hooks/useRequestStatus';
|
|
22
26
|
import { initiateStkPush } from '../../../m-pesa/mpesa-resource';
|
|
23
|
-
import { MappedBill } from '../../../types';
|
|
27
|
+
import { LineItem, MappedBill } from '../../../types';
|
|
28
|
+
import PaymentStatusCheckerModal from '../payment-status-ckecker.modal';
|
|
24
29
|
import { formatKenyanPhoneNumber } from '../utils';
|
|
25
30
|
import styles from './initiate-payment.scss';
|
|
26
31
|
|
|
@@ -37,15 +42,17 @@ type FormData = z.infer<typeof initiatePaymentSchema>;
|
|
|
37
42
|
export interface InitiatePaymentDialogProps {
|
|
38
43
|
closeModal: () => void;
|
|
39
44
|
bill: MappedBill;
|
|
45
|
+
selectedLineItems: Array<LineItem>;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
const InitiatePaymentDialog: React.FC<InitiatePaymentDialogProps> = ({ closeModal, bill }) => {
|
|
48
|
+
const InitiatePaymentDialog: React.FC<InitiatePaymentDialogProps> = ({ closeModal, bill, selectedLineItems }) => {
|
|
43
49
|
const { t } = useTranslation();
|
|
44
50
|
const { phoneNumber, isLoading: isLoadingPhoneNumber } = usePatientAttributes(bill.patientUuid);
|
|
45
51
|
const { mpesaAPIBaseUrl, isPDSLFacility } = useConfig<BillingConfig>();
|
|
46
52
|
const { mflCodeValue } = useSystemSetting('facility.mflcode');
|
|
47
53
|
const [notification, setNotification] = useState<{ type: 'error' | 'success'; message: string } | null>(null);
|
|
48
54
|
const [isLoading, setIsLoading] = useState(false);
|
|
55
|
+
const [hasMadePayment, setHasMadepayment] = useState(false);
|
|
49
56
|
const [{ requestStatus }, pollingTrigger] = useRequestStatus(setNotification, closeModal, bill);
|
|
50
57
|
|
|
51
58
|
const pendingAmount = bill.totalAmount - bill.tenderedAmount;
|
|
@@ -91,12 +98,35 @@ const InitiatePaymentDialog: React.FC<InitiatePaymentDialogProps> = ({ closeModa
|
|
|
91
98
|
setIsLoading(false);
|
|
92
99
|
};
|
|
93
100
|
|
|
101
|
+
if (isPDSLFacility && hasMadePayment) {
|
|
102
|
+
return (
|
|
103
|
+
<PaymentStatusCheckerModal
|
|
104
|
+
onClose={closeModal}
|
|
105
|
+
paymentMade={hasMadePayment}
|
|
106
|
+
onPaymentMadestatusChange={setHasMadepayment}
|
|
107
|
+
bill={bill}
|
|
108
|
+
selectedLineItems={selectedLineItems}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
94
113
|
return (
|
|
95
|
-
<
|
|
96
|
-
<ModalHeader closeModal={closeModal}
|
|
114
|
+
<Form>
|
|
115
|
+
<ModalHeader className={styles.heading} closeModal={closeModal}>
|
|
116
|
+
{t('paymentPayment', 'Bill Payment')}
|
|
117
|
+
</ModalHeader>
|
|
97
118
|
<ModalBody>
|
|
98
|
-
|
|
99
|
-
<
|
|
119
|
+
{isPDSLFacility && (
|
|
120
|
+
<ContentSwitcher
|
|
121
|
+
selectedIndex={hasMadePayment ? 1 : 0}
|
|
122
|
+
onChange={({ name }) => {
|
|
123
|
+
setHasMadepayment(name === 'paymentMade');
|
|
124
|
+
}}>
|
|
125
|
+
<Switch name="paymentNotMade" text={t('paymentNotMade', 'Payment not made')} />
|
|
126
|
+
<Switch name="paymentMade" text={t('paymentMade', 'Payments already made')} />
|
|
127
|
+
</ContentSwitcher>
|
|
128
|
+
)}
|
|
129
|
+
<div className={styles.form}>
|
|
100
130
|
{notification && (
|
|
101
131
|
<InlineNotification
|
|
102
132
|
kind={notification.type}
|
|
@@ -144,28 +174,30 @@ const InitiatePaymentDialog: React.FC<InitiatePaymentDialogProps> = ({ closeModa
|
|
|
144
174
|
)}
|
|
145
175
|
/>
|
|
146
176
|
</section>
|
|
147
|
-
|
|
148
|
-
<Button kind="secondary" className={styles.buttonLayout} onClick={closeModal}>
|
|
149
|
-
{t('cancel', 'Cancel')}
|
|
150
|
-
</Button>
|
|
151
|
-
<Button
|
|
152
|
-
type="submit"
|
|
153
|
-
className={styles.button}
|
|
154
|
-
onClick={handleSubmit(onSubmit)}
|
|
155
|
-
disabled={!isValid || isLoading || requestStatus === 'INITIATED'}>
|
|
156
|
-
{isLoading ? (
|
|
157
|
-
<>
|
|
158
|
-
<Loading className={styles.button_spinner} withOverlay={false} small />{' '}
|
|
159
|
-
{t('processingPayment', 'Processing Payment')}
|
|
160
|
-
</>
|
|
161
|
-
) : (
|
|
162
|
-
t('initiatePay', 'Initiate Payment')
|
|
163
|
-
)}
|
|
164
|
-
</Button>
|
|
165
|
-
</section>
|
|
166
|
-
</Form>
|
|
177
|
+
</div>
|
|
167
178
|
</ModalBody>
|
|
168
|
-
|
|
179
|
+
<ModalFooter>
|
|
180
|
+
<ButtonSet className={styles.buttonSet}>
|
|
181
|
+
<Button kind="secondary" onClick={closeModal} className={styles.button}>
|
|
182
|
+
{t('cancel', 'Cancel')}
|
|
183
|
+
</Button>
|
|
184
|
+
<Button
|
|
185
|
+
type="submit"
|
|
186
|
+
className={styles.button}
|
|
187
|
+
onClick={handleSubmit(onSubmit)}
|
|
188
|
+
disabled={!isValid || isLoading || requestStatus === 'INITIATED'}>
|
|
189
|
+
{isLoading ? (
|
|
190
|
+
<>
|
|
191
|
+
<Loading className={styles.button_spinner} withOverlay={false} small />{' '}
|
|
192
|
+
{t('processingPayment', 'Processing Payment')}
|
|
193
|
+
</>
|
|
194
|
+
) : (
|
|
195
|
+
t('initiatePayment', 'Initiate Payment')
|
|
196
|
+
)}
|
|
197
|
+
</Button>
|
|
198
|
+
</ButtonSet>
|
|
199
|
+
</ModalFooter>
|
|
200
|
+
</Form>
|
|
169
201
|
);
|
|
170
202
|
};
|
|
171
203
|
|
|
@@ -21,18 +21,28 @@
|
|
|
21
21
|
margin-bottom: spacing.$spacing-04;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
margin-
|
|
24
|
+
.button_spinner {
|
|
25
|
+
padding: 0;
|
|
26
|
+
margin-right: layout.$spacing-04;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.button {
|
|
30
|
-
|
|
30
|
+
height: layout.$spacing-10;
|
|
31
|
+
display: flex;
|
|
32
|
+
align-content: flex-start;
|
|
33
|
+
align-items: baseline;
|
|
34
|
+
min-width: 20%;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.buttonSet {
|
|
38
|
+
padding: 0rem;
|
|
31
39
|
margin-top: layout.$spacing-05;
|
|
32
|
-
|
|
40
|
+
display: flex;
|
|
41
|
+
justify-content: space-between;
|
|
42
|
+
width: 100%;
|
|
43
|
+
margin-bottom: layout.$spacing-05;
|
|
33
44
|
}
|
|
34
45
|
|
|
35
|
-
.
|
|
36
|
-
|
|
37
|
-
margin-right: 12px;
|
|
46
|
+
.heading {
|
|
47
|
+
@include type.type-style('heading-02');
|
|
38
48
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
ButtonSet,
|
|
4
|
+
ContentSwitcher,
|
|
5
|
+
InlineLoading,
|
|
6
|
+
ModalBody,
|
|
7
|
+
ModalFooter,
|
|
8
|
+
ModalHeader,
|
|
9
|
+
Switch,
|
|
10
|
+
TextInput,
|
|
11
|
+
} from '@carbon/react';
|
|
12
|
+
import { showSnackbar, useConfig } from '@openmrs/esm-framework';
|
|
13
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
14
|
+
import { useTranslation } from 'react-i18next';
|
|
15
|
+
import { mutate } from 'swr';
|
|
16
|
+
import { processBillPayment, usePaymentModes } from '../../billing.resource';
|
|
17
|
+
import { BillingConfig } from '../../config-schema';
|
|
18
|
+
import { useClockInStatus } from '../../payment-points/use-clock-in-status';
|
|
19
|
+
import { LineItem, MappedBill } from '../../types';
|
|
20
|
+
import { checkPaymentStatus } from './payments.resource';
|
|
21
|
+
import styles from './payments.scss';
|
|
22
|
+
import { createPaymentPayload } from './utils';
|
|
23
|
+
type PaymentStatusCheckerModalProps = {
|
|
24
|
+
onClose: () => void;
|
|
25
|
+
paymentMade?: boolean;
|
|
26
|
+
onPaymentMadestatusChange?: (paid: boolean) => void;
|
|
27
|
+
bill: MappedBill;
|
|
28
|
+
selectedLineItems: Array<LineItem>;
|
|
29
|
+
};
|
|
30
|
+
const PaymentStatusCheckerModal: React.FC<PaymentStatusCheckerModalProps> = ({
|
|
31
|
+
onClose,
|
|
32
|
+
onPaymentMadestatusChange,
|
|
33
|
+
paymentMade,
|
|
34
|
+
bill,
|
|
35
|
+
selectedLineItems,
|
|
36
|
+
}) => {
|
|
37
|
+
const { t } = useTranslation();
|
|
38
|
+
const [transactionid, setTransactionid] = useState<string>();
|
|
39
|
+
const { globalActiveSheet } = useClockInStatus();
|
|
40
|
+
const { mobileMoneyPaymentModeUUID } = useConfig<BillingConfig>();
|
|
41
|
+
const { paymentModes, isLoading } = usePaymentModes();
|
|
42
|
+
const [checking, setChecking] = useState(false);
|
|
43
|
+
const mobilemoneypaymentMethod = useMemo(
|
|
44
|
+
() => paymentModes.find((mode) => mode.uuid === mobileMoneyPaymentModeUUID),
|
|
45
|
+
[paymentModes, mobileMoneyPaymentModeUUID],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const handleCheckPaymentStatus = useCallback(async () => {
|
|
49
|
+
try {
|
|
50
|
+
setChecking(true);
|
|
51
|
+
const res = await checkPaymentStatus(transactionid);
|
|
52
|
+
if (res?.data?.success) {
|
|
53
|
+
const totalAmountTendered = Number(res.data.data.TransAmount) || 0;
|
|
54
|
+
const amountDue = Number(bill.totalAmount) - (Number(bill.tenderedAmount) + Number(totalAmountTendered));
|
|
55
|
+
const paymentPayload = createPaymentPayload(
|
|
56
|
+
bill,
|
|
57
|
+
bill.patientUuid,
|
|
58
|
+
[{ referenceCode: transactionid, amount: totalAmountTendered, method: mobilemoneypaymentMethod }],
|
|
59
|
+
amountDue,
|
|
60
|
+
selectedLineItems,
|
|
61
|
+
globalActiveSheet,
|
|
62
|
+
);
|
|
63
|
+
await processBillPayment(paymentPayload, bill.uuid);
|
|
64
|
+
showSnackbar({
|
|
65
|
+
title: t('success', 'Success'),
|
|
66
|
+
kind: 'success',
|
|
67
|
+
subtitle: t('paymentReceived', 'Payment received'),
|
|
68
|
+
});
|
|
69
|
+
const url = `/ws/rest/v1/cashier/bill/${bill.uuid}`;
|
|
70
|
+
mutate((key) => typeof key === 'string' && key.startsWith(url), undefined, { revalidate: true });
|
|
71
|
+
onClose?.();
|
|
72
|
+
} else {
|
|
73
|
+
showSnackbar({
|
|
74
|
+
title: t('paymentFailure', 'Payment Failure'),
|
|
75
|
+
kind: 'error',
|
|
76
|
+
subtitle: res?.data?.message || t('paymentNotSettled', 'Payment not settled'),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
} catch (error: any) {
|
|
80
|
+
showSnackbar({ title: t('error', 'Error'), kind: 'error', subtitle: error?.message });
|
|
81
|
+
} finally {
|
|
82
|
+
setChecking(false);
|
|
83
|
+
}
|
|
84
|
+
}, [transactionid, t]);
|
|
85
|
+
return (
|
|
86
|
+
<React.Fragment>
|
|
87
|
+
<ModalHeader className={styles.heading} closeModal={onClose}>
|
|
88
|
+
{t('checkpaymentStatus', 'Check payment status')}
|
|
89
|
+
</ModalHeader>
|
|
90
|
+
<ModalBody>
|
|
91
|
+
<ContentSwitcher
|
|
92
|
+
selectedIndex={paymentMade ? 1 : 0}
|
|
93
|
+
onChange={({ name }) => {
|
|
94
|
+
onPaymentMadestatusChange?.(name === 'paymentMade');
|
|
95
|
+
}}>
|
|
96
|
+
<Switch name="paymentNotMade" text={t('paymentNotMade', 'Payment not made')} />
|
|
97
|
+
<Switch name="paymentMade" text={t('paymentMade', 'Payments already made')} />
|
|
98
|
+
</ContentSwitcher>
|
|
99
|
+
<TextInput
|
|
100
|
+
value={transactionid}
|
|
101
|
+
defaultWidth={300}
|
|
102
|
+
id="text-input-1"
|
|
103
|
+
labelText={t('transactionId', 'Transaction Id')}
|
|
104
|
+
placeholder={t('exampletransactionId', 'e.g TRMEWECEDD')}
|
|
105
|
+
size="md"
|
|
106
|
+
type="text"
|
|
107
|
+
helperText={t('mpesaTransactionId', 'Mpesa transaction Id')}
|
|
108
|
+
onChange={({ target: { value } }) => setTransactionid(value)}
|
|
109
|
+
/>
|
|
110
|
+
</ModalBody>
|
|
111
|
+
<ModalFooter>
|
|
112
|
+
<ButtonSet className={styles.buttonSet}>
|
|
113
|
+
<Button kind="secondary" onClick={onClose} className={styles.button}>
|
|
114
|
+
{t('cancel', 'Cancel')}
|
|
115
|
+
</Button>
|
|
116
|
+
<Button
|
|
117
|
+
kind="primary"
|
|
118
|
+
disabled={!transactionid?.length || isLoading || checking}
|
|
119
|
+
onClick={handleCheckPaymentStatus}
|
|
120
|
+
className={styles.button}>
|
|
121
|
+
{isLoading || checking ? (
|
|
122
|
+
<InlineLoading
|
|
123
|
+
description={t('checkingPaymentStatus', 'Check payment status') + '...'}
|
|
124
|
+
iconDescription={t('loading', 'Loading')}
|
|
125
|
+
/>
|
|
126
|
+
) : (
|
|
127
|
+
t('check', 'Check')
|
|
128
|
+
)}
|
|
129
|
+
</Button>
|
|
130
|
+
</ButtonSet>
|
|
131
|
+
</ModalFooter>
|
|
132
|
+
</React.Fragment>
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export default PaymentStatusCheckerModal;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import useSWR from 'swr';
|
|
2
|
-
import { openmrsFetch, useConfig } from '@openmrs/esm-framework';
|
|
2
|
+
import { openmrsFetch, restBaseUrl, useConfig } from '@openmrs/esm-framework';
|
|
3
3
|
import { BillingConfig } from '../../config-schema';
|
|
4
4
|
|
|
5
5
|
type PaymentMethod = {
|
|
@@ -13,6 +13,32 @@ const swrOption = {
|
|
|
13
13
|
errorRetryCount: 2,
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
export interface PaymentStatusResponse {
|
|
17
|
+
success: boolean;
|
|
18
|
+
message: string;
|
|
19
|
+
data?: Data;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface Data {
|
|
23
|
+
id: number;
|
|
24
|
+
TransactionType: string;
|
|
25
|
+
TransID: string;
|
|
26
|
+
TransTime: string;
|
|
27
|
+
TransAmount: string;
|
|
28
|
+
BusinessShortCode: string;
|
|
29
|
+
BillRefNumber: string;
|
|
30
|
+
InvoiceNumber?: string;
|
|
31
|
+
OrgAccountBalance: string;
|
|
32
|
+
ThirdPartyTransID?: string;
|
|
33
|
+
MSISDN: string;
|
|
34
|
+
FirstName: string;
|
|
35
|
+
MiddleName?: string;
|
|
36
|
+
LastName?: string;
|
|
37
|
+
status: string;
|
|
38
|
+
created_at: string;
|
|
39
|
+
updated_at: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
16
42
|
export const usePaymentModes = () => {
|
|
17
43
|
const { excludedPaymentMode } = useConfig<BillingConfig>();
|
|
18
44
|
const url = `/ws/rest/v1/cashier/paymentMode`;
|
|
@@ -32,3 +58,8 @@ export const usePaymentModes = () => {
|
|
|
32
58
|
error,
|
|
33
59
|
};
|
|
34
60
|
};
|
|
61
|
+
|
|
62
|
+
export const checkPaymentStatus = (transactionId: string) => {
|
|
63
|
+
const url = `${restBaseUrl}/rmsdataexchange/api/rmsmpesachecker?transactionId=${transactionId}`;
|
|
64
|
+
return openmrsFetch<PaymentStatusResponse>(url);
|
|
65
|
+
};
|
|
@@ -48,3 +48,24 @@
|
|
|
48
48
|
.paymentError {
|
|
49
49
|
margin: layout.$spacing-05 0;
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
.heading {
|
|
53
|
+
@include type.type-style('heading-02');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.button {
|
|
57
|
+
height: layout.$spacing-10;
|
|
58
|
+
display: flex;
|
|
59
|
+
align-content: flex-start;
|
|
60
|
+
align-items: baseline;
|
|
61
|
+
min-width: 20%;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.buttonSet {
|
|
65
|
+
padding: 0rem;
|
|
66
|
+
margin-top: layout.$spacing-05;
|
|
67
|
+
display: flex;
|
|
68
|
+
justify-content: space-between;
|
|
69
|
+
width: 100%;
|
|
70
|
+
margin-bottom: layout.$spacing-05;
|
|
71
|
+
}
|