@kenyaemr/esm-billing-app 5.4.1-pre.1998 → 5.4.1-pre.2008
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 +74 -74
- package/dist/290.js +1 -1
- package/dist/300.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 +32 -32
- 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/billable-services/billable-service.resource.tsx +6 -2
- package/src/billable-services/billiable-item/order-actions/hooks/useLabOrderAction.ts +18 -3
- 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/src/prompt-payment/prompt-payment.resource.tsx +0 -1
- package/translations/en.json +6 -1
- 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.2008"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { OpenmrsResource, openmrsFetch } from '@openmrs/esm-framework';
|
|
1
|
+
import { Concept, OpenmrsResource, openmrsFetch } from '@openmrs/esm-framework';
|
|
2
2
|
import useSWR from 'swr';
|
|
3
3
|
import { ServiceConcept, ServiceTypesResponse } from '../types';
|
|
4
4
|
|
|
5
|
+
type ExtendedResponseObject = OpenmrsResource & {
|
|
6
|
+
concept: Concept;
|
|
7
|
+
};
|
|
8
|
+
|
|
5
9
|
type ResponseObject = {
|
|
6
|
-
results: Array<
|
|
10
|
+
results: Array<ExtendedResponseObject>;
|
|
7
11
|
};
|
|
8
12
|
|
|
9
13
|
export const useBillableServices = () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useTranslation } from 'react-i18next';
|
|
2
2
|
import { Order } from '@openmrs/esm-patient-common-lib';
|
|
3
3
|
import { useBillStatus } from './useBillStatus';
|
|
4
|
+
import { useBillableServices } from '../../../billable-service.resource';
|
|
4
5
|
|
|
5
6
|
export enum FulfillerStatus {
|
|
6
7
|
IN_PROGRESS = 'IN_PROGRESS',
|
|
@@ -11,11 +12,25 @@ export function useLabOrderAction(order?: Order) {
|
|
|
11
12
|
const orderUuid = order?.uuid;
|
|
12
13
|
const patientUuid = order?.patient?.uuid;
|
|
13
14
|
const conceptClass = order?.concept?.conceptClass?.['display'];
|
|
15
|
+
const { isLoading: isLoadingBillableServices, billableServices } = useBillableServices();
|
|
16
|
+
|
|
17
|
+
const serviceBillingStatus =
|
|
18
|
+
billableServices?.find((service) => service.concept.uuid === order.concept.uuid)?.serviceStatus === 'ENABLED';
|
|
14
19
|
|
|
15
20
|
const { isLoading, hasPendingPayment, itemHasBill } = useBillStatus(orderUuid, patientUuid);
|
|
16
|
-
const shouldShowBillModal = itemHasBill.length < 1;
|
|
21
|
+
const shouldShowBillModal = itemHasBill.length < 1 && serviceBillingStatus;
|
|
17
22
|
const isInProgress = order?.fulfillerStatus === FulfillerStatus.IN_PROGRESS;
|
|
18
23
|
|
|
24
|
+
const getOrderType = () => {
|
|
25
|
+
if (!conceptClass) {
|
|
26
|
+
return 'Lab Request';
|
|
27
|
+
}
|
|
28
|
+
if (conceptClass.includes('/')) {
|
|
29
|
+
return conceptClass.split('/')[1].trim();
|
|
30
|
+
}
|
|
31
|
+
return conceptClass;
|
|
32
|
+
};
|
|
33
|
+
|
|
19
34
|
const getButtonText = () => {
|
|
20
35
|
if (hasPendingPayment) {
|
|
21
36
|
return t('unsettledBill', 'Unsettled bill');
|
|
@@ -25,11 +40,11 @@ export function useLabOrderAction(order?: Order) {
|
|
|
25
40
|
return t('bill', 'Bill');
|
|
26
41
|
}
|
|
27
42
|
|
|
28
|
-
return t('pickLabRequest', 'Pick {{orderType}}
|
|
43
|
+
return t('pickLabRequest', 'Pick {{orderType}}', { orderType: getOrderType() ?? 'Lab Request' });
|
|
29
44
|
};
|
|
30
45
|
|
|
31
46
|
return {
|
|
32
|
-
isLoading,
|
|
47
|
+
isLoading: isLoading && isLoadingBillableServices,
|
|
33
48
|
isDisabled: hasPendingPayment,
|
|
34
49
|
buttonText: getButtonText(),
|
|
35
50
|
isInProgress,
|
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
|
+
}
|
|
@@ -173,7 +173,6 @@ export const usePatientBills = (patientUuid: string) => {
|
|
|
173
173
|
const patientBills = useMemo(() => {
|
|
174
174
|
return data?.data?.results?.map(mapBillProperties) ?? [];
|
|
175
175
|
}, [data?.data?.results]);
|
|
176
|
-
|
|
177
176
|
return {
|
|
178
177
|
patientBills: patientBills ?? [],
|
|
179
178
|
isLoading,
|
package/translations/en.json
CHANGED
|
@@ -96,6 +96,8 @@
|
|
|
96
96
|
"eligibleBenefits": "Eligible benefits",
|
|
97
97
|
"emptyClaimsHeader": "No Claims",
|
|
98
98
|
"emptyClaimsState": "There are no claims to display",
|
|
99
|
+
"emptyPreauthHeader": "No Preauths",
|
|
100
|
+
"emptyPreauthState": "There are no preauth to display",
|
|
99
101
|
"endDate": "End date",
|
|
100
102
|
"endVisitAndClaim": "End visit and Process claims",
|
|
101
103
|
"enterAmount": "Enter amount",
|
|
@@ -135,7 +137,7 @@
|
|
|
135
137
|
"inactive": "Inactive",
|
|
136
138
|
"incompletePayment": "Incomplete payment",
|
|
137
139
|
"incompletePaymentSubtitle": "Please ensure all selected line items are fully paid, Total amount expected is {{selectedLineItemsAmountDue}}",
|
|
138
|
-
"
|
|
140
|
+
"initiatePayment": "Initiate Payment",
|
|
139
141
|
"inputSampleSchema": "Input sample schema",
|
|
140
142
|
"insuranceScheme": "Insurance scheme",
|
|
141
143
|
"insurer": "Insurer",
|
|
@@ -196,18 +198,21 @@
|
|
|
196
198
|
"patientMissingSHANumber": "Patient is missing SHA number, SHA validation cannot be done, Advise patient to visit registration desk",
|
|
197
199
|
"patientName": "Patient Name",
|
|
198
200
|
"paymentHistory": "Payment History",
|
|
201
|
+
"paymentMade": "Payments already made",
|
|
199
202
|
"paymentMethod": "Payment method",
|
|
200
203
|
"paymentMethodDescription": "Payment method {{methodName}}",
|
|
201
204
|
"paymentMethodsTitle": "Payment method",
|
|
202
205
|
"paymentMode": "Payment Mode",
|
|
203
206
|
"paymentModes": "Payment Modes",
|
|
204
207
|
"paymentModeSummary": "Payment Mode Summary",
|
|
208
|
+
"paymentNotMade": "Payment not made",
|
|
205
209
|
"paymentPayment": "Bill Payment",
|
|
206
210
|
"paymentPoints": "Payment Points",
|
|
207
211
|
"payments": "Payments",
|
|
208
212
|
"paymentType": "Payment Type",
|
|
209
213
|
"Phone Number": "Phone Number",
|
|
210
214
|
"policyNumber": "Policy number",
|
|
215
|
+
"preathsRequests": "Preauth Requests",
|
|
211
216
|
"preauthRequest": "Preauth requests",
|
|
212
217
|
"preAuthRequests": "Pre-auth requests",
|
|
213
218
|
"preAuthRequets": "Pre-Auth Requests",
|