@kenyaemr/esm-billing-app 5.4.1-pre.1936 → 5.4.1-pre.1945
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 +65 -65
- package/dist/300.js +1 -1
- package/dist/423.js +1 -0
- package/dist/423.js.map +1 -0
- package/dist/{308.js → 610.js} +1 -1
- package/dist/610.js.map +1 -0
- package/dist/917.js +2 -0
- package/dist/917.js.map +1 -0
- package/dist/kenyaemr-esm-billing-app.js +1 -1
- package/dist/kenyaemr-esm-billing-app.js.buildmanifest.json +71 -71
- package/dist/kenyaemr-esm-billing-app.js.map +1 -1
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/benefits-package/forms/packages-and-interventions-form.component.tsx +15 -2
- package/src/billable-services/billiable-item/order-actions/components/base-order-button.component.tsx +42 -0
- package/src/billable-services/billiable-item/order-actions/components/lab-order-button.component.tsx +51 -0
- package/src/billable-services/billiable-item/order-actions/components/medication-order-button.component.tsx +84 -0
- package/src/billable-services/billiable-item/order-actions/components/order-action-button.component.tsx +29 -0
- package/src/billable-services/billiable-item/order-actions/hooks/useBillStatus.ts +12 -0
- package/src/billable-services/billiable-item/order-actions/hooks/useLabOrderAction.ts +27 -0
- package/src/billable-services/billiable-item/order-actions/hooks/useMedicationOrderAction.ts +106 -0
- package/src/billable-services/billiable-item/order-actions/hooks/useModalHandler.ts +66 -0
- package/src/billable-services/billiable-item/order-actions/styles/order-action.scss +0 -0
- package/src/claims/dashboard/form/claims-explanation-and-justification-form-input.component.tsx +120 -0
- package/src/claims/dashboard/form/claims-form.component.tsx +3 -40
- package/src/index.ts +2 -2
- package/src/routes.json +3 -3
- package/translations/en.json +2 -5
- package/dist/138.js +0 -2
- package/dist/138.js.map +0 -1
- package/dist/308.js.map +0 -1
- package/dist/614.js +0 -1
- package/dist/614.js.map +0 -1
- package/src/billable-services/billiable-item/test-order/test-order-action.component.tsx +0 -134
- package/src/billable-services/billiable-item/test-order/test-order-action.test.tsx +0 -178
- /package/dist/{138.js.LICENSE.txt → 917.js.LICENSE.txt} +0 -0
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":"
|
|
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","slot":"prescription-action-button-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":"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"}],"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.1945"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Column, InlineLoading, InlineNotification, MultiSelect } from '@carbon/react';
|
|
2
|
-
import React
|
|
2
|
+
import React from 'react';
|
|
3
3
|
import { Controller, useFormContext } from 'react-hook-form';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import PackageInterventions from './interventions-form.component';
|
|
6
5
|
import usePackages from '../../hooks/usePackages';
|
|
6
|
+
import PackageInterventions from './interventions-form.component';
|
|
7
7
|
|
|
8
8
|
type Props = {
|
|
9
9
|
patientUuid: string;
|
|
@@ -21,6 +21,19 @@ const SHABenefitPackangesAndInterventions: React.FC<Props> = ({ patientUuid }) =
|
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
if (packageError) {
|
|
25
|
+
return (
|
|
26
|
+
<InlineNotification
|
|
27
|
+
aria-label="closes notification"
|
|
28
|
+
kind="error"
|
|
29
|
+
lowContrast={true}
|
|
30
|
+
statusIconDescription="notification"
|
|
31
|
+
title={t('errorLoadingpackages', 'Error loading packages')}
|
|
32
|
+
subtitle={packageError?.message}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
return (
|
|
25
38
|
<>
|
|
26
39
|
<Column>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { InlineLoading, Button } from '@carbon/react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
export type BaseOrderButtonProps = {
|
|
5
|
+
isDisabled: boolean;
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
buttonText: string;
|
|
8
|
+
onClick: () => void;
|
|
9
|
+
kind?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'tertiary';
|
|
10
|
+
size?: 'sm' | 'md' | 'lg';
|
|
11
|
+
className?: string;
|
|
12
|
+
Icon?;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const BaseOrderButton: React.FC<BaseOrderButtonProps> = ({
|
|
16
|
+
isDisabled,
|
|
17
|
+
isLoading,
|
|
18
|
+
buttonText,
|
|
19
|
+
onClick,
|
|
20
|
+
kind = 'primary',
|
|
21
|
+
size = 'md',
|
|
22
|
+
className = '',
|
|
23
|
+
Icon,
|
|
24
|
+
}) => {
|
|
25
|
+
const { t } = useTranslation();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Button
|
|
29
|
+
kind={isLoading ? 'ghost' : kind}
|
|
30
|
+
renderIcon={!isLoading ? Icon : undefined}
|
|
31
|
+
className={className}
|
|
32
|
+
size={size}
|
|
33
|
+
disabled={isLoading || isDisabled}
|
|
34
|
+
onClick={onClick}>
|
|
35
|
+
{isLoading ? (
|
|
36
|
+
<InlineLoading description={t('verifyingBillStatus', 'Verifying bill status...')} status="active" />
|
|
37
|
+
) : (
|
|
38
|
+
buttonText
|
|
39
|
+
)}
|
|
40
|
+
</Button>
|
|
41
|
+
);
|
|
42
|
+
};
|
package/src/billable-services/billiable-item/order-actions/components/lab-order-button.component.tsx
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { showModal } from '@openmrs/esm-framework';
|
|
3
|
+
import { Order } from '@openmrs/esm-patient-common-lib';
|
|
4
|
+
import { BaseOrderButton } from './base-order-button.component';
|
|
5
|
+
import { useLabOrderAction } from '../hooks/useLabOrderAction';
|
|
6
|
+
import { useModalHandler } from '../hooks/useModalHandler';
|
|
7
|
+
import styles from '../styles/order-action.scss';
|
|
8
|
+
|
|
9
|
+
export interface LabOrderButtonProps {
|
|
10
|
+
order?: Order;
|
|
11
|
+
modalName?: string;
|
|
12
|
+
additionalProps?: Record<string, unknown>;
|
|
13
|
+
actionText?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const LabOrderButton: React.FC<LabOrderButtonProps> = ({
|
|
17
|
+
order,
|
|
18
|
+
modalName = 'pickup-lab-request-modal',
|
|
19
|
+
additionalProps,
|
|
20
|
+
actionText,
|
|
21
|
+
}) => {
|
|
22
|
+
const { isLoading, isDisabled, buttonText: defaultButtonText, isInProgress } = useLabOrderAction(order);
|
|
23
|
+
|
|
24
|
+
const { handleModalClose } = useModalHandler(additionalProps?.mutateUrl as string);
|
|
25
|
+
const buttonText = actionText ?? defaultButtonText;
|
|
26
|
+
|
|
27
|
+
const launchModal = useCallback(() => {
|
|
28
|
+
const dispose = showModal(modalName, {
|
|
29
|
+
closeModal: () => {
|
|
30
|
+
handleModalClose();
|
|
31
|
+
dispose();
|
|
32
|
+
},
|
|
33
|
+
order,
|
|
34
|
+
...(additionalProps && { additionalProps }),
|
|
35
|
+
});
|
|
36
|
+
}, [modalName, order, additionalProps, handleModalClose]);
|
|
37
|
+
|
|
38
|
+
if (isInProgress) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<BaseOrderButton
|
|
44
|
+
isLoading={isLoading}
|
|
45
|
+
isDisabled={isDisabled}
|
|
46
|
+
buttonText={buttonText}
|
|
47
|
+
onClick={launchModal}
|
|
48
|
+
className={styles.actionButton}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { Edit } from '@carbon/react/icons';
|
|
3
|
+
import { showModal, launchWorkspace } from '@openmrs/esm-framework';
|
|
4
|
+
import { BaseOrderButton } from './base-order-button.component';
|
|
5
|
+
import { useMedicationOrderAction, useOrderByUuid } from '../hooks/useMedicationOrderAction';
|
|
6
|
+
import { launchPrescriptionEditWorkspace, useModalHandler } from '../hooks/useModalHandler';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
export interface MedicationOrderButtonProps {
|
|
9
|
+
medicationRequestBundle?: {
|
|
10
|
+
request: fhir.MedicationRequest;
|
|
11
|
+
};
|
|
12
|
+
modalName?: string;
|
|
13
|
+
additionalProps?: Record<string, unknown>;
|
|
14
|
+
actionText?: string;
|
|
15
|
+
closeable?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const MedicationOrderButton: React.FC<MedicationOrderButtonProps> = ({
|
|
19
|
+
medicationRequestBundle,
|
|
20
|
+
modalName,
|
|
21
|
+
additionalProps,
|
|
22
|
+
actionText,
|
|
23
|
+
closeable = true,
|
|
24
|
+
}) => {
|
|
25
|
+
const { t } = useTranslation();
|
|
26
|
+
const {
|
|
27
|
+
isLoading: isMedicationOrderLoading,
|
|
28
|
+
isDisabled,
|
|
29
|
+
buttonText: defaultButtonText,
|
|
30
|
+
shouldShowBillModal,
|
|
31
|
+
dispenseFormProps,
|
|
32
|
+
patientUuid,
|
|
33
|
+
shouldAllowModify,
|
|
34
|
+
} = useMedicationOrderAction(medicationRequestBundle);
|
|
35
|
+
const { data: order, isLoading: isOrderLoading } = useOrderByUuid(medicationRequestBundle?.request?.id);
|
|
36
|
+
const isLoading = isMedicationOrderLoading && isOrderLoading;
|
|
37
|
+
|
|
38
|
+
const { handleModalClose } = useModalHandler(additionalProps?.mutateUrl as string);
|
|
39
|
+
const buttonText = actionText ?? defaultButtonText;
|
|
40
|
+
|
|
41
|
+
const launchModal = useCallback(() => {
|
|
42
|
+
if (shouldShowBillModal) {
|
|
43
|
+
const disposeBill = showModal(modalName ?? 'create-bill-item-modal', {
|
|
44
|
+
closeModal: () => {
|
|
45
|
+
handleModalClose();
|
|
46
|
+
disposeBill();
|
|
47
|
+
},
|
|
48
|
+
medicationRequestBundle,
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (dispenseFormProps) {
|
|
54
|
+
launchWorkspace('dispense-workspace', dispenseFormProps);
|
|
55
|
+
}
|
|
56
|
+
}, [modalName, shouldShowBillModal, handleModalClose, medicationRequestBundle, dispenseFormProps]);
|
|
57
|
+
|
|
58
|
+
if (!closeable) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div>
|
|
64
|
+
{shouldAllowModify && (
|
|
65
|
+
<BaseOrderButton
|
|
66
|
+
size="lg"
|
|
67
|
+
kind="tertiary"
|
|
68
|
+
Icon={Edit}
|
|
69
|
+
isLoading={isLoading}
|
|
70
|
+
isDisabled={false}
|
|
71
|
+
buttonText={t('modify', 'Modify')}
|
|
72
|
+
onClick={() => launchPrescriptionEditWorkspace(order, patientUuid)}
|
|
73
|
+
/>
|
|
74
|
+
)}
|
|
75
|
+
<BaseOrderButton
|
|
76
|
+
size="lg"
|
|
77
|
+
isLoading={isLoading}
|
|
78
|
+
isDisabled={isDisabled}
|
|
79
|
+
buttonText={buttonText}
|
|
80
|
+
onClick={launchModal}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LabOrderButton } from './lab-order-button.component';
|
|
3
|
+
import { MedicationOrderButton } from './medication-order-button.component';
|
|
4
|
+
|
|
5
|
+
const OrderActionButton: React.FC<Record<string, any>> = (props) => {
|
|
6
|
+
if (Object.hasOwn(props, 'medicationRequestBundle')) {
|
|
7
|
+
const { medicationRequestBundle, modalName, additionalProps, actionText, closeable } = props;
|
|
8
|
+
return (
|
|
9
|
+
<MedicationOrderButton
|
|
10
|
+
medicationRequestBundle={medicationRequestBundle}
|
|
11
|
+
modalName={modalName}
|
|
12
|
+
additionalProps={additionalProps}
|
|
13
|
+
actionText={actionText}
|
|
14
|
+
closeable={closeable}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (props.orderType === 'lab') {
|
|
20
|
+
const { order, modalName, additionalProps, actionText } = props;
|
|
21
|
+
return (
|
|
22
|
+
<LabOrderButton order={order} modalName={modalName} additionalProps={additionalProps} actionText={actionText} />
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default OrderActionButton;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useOrderBill, useTestOrderBillStatus } from '../../test-order/test-order-action.resource';
|
|
2
|
+
|
|
3
|
+
export function useBillStatus(orderUuid?: string, patientUuid?: string) {
|
|
4
|
+
const { isLoading, hasPendingPayment } = useTestOrderBillStatus(orderUuid, patientUuid);
|
|
5
|
+
const { itemHasBill } = useOrderBill(patientUuid, orderUuid);
|
|
6
|
+
|
|
7
|
+
return {
|
|
8
|
+
isLoading,
|
|
9
|
+
hasPendingPayment,
|
|
10
|
+
itemHasBill,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useTranslation } from 'react-i18next';
|
|
2
|
+
import { Order } from '@openmrs/esm-patient-common-lib';
|
|
3
|
+
import { useBillStatus } from './useBillStatus';
|
|
4
|
+
|
|
5
|
+
export enum FulfillerStatus {
|
|
6
|
+
IN_PROGRESS = 'IN_PROGRESS',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useLabOrderAction(order?: Order) {
|
|
10
|
+
const { t } = useTranslation();
|
|
11
|
+
const orderUuid = order?.uuid;
|
|
12
|
+
const patientUuid = order?.patient?.uuid;
|
|
13
|
+
|
|
14
|
+
const { isLoading, hasPendingPayment } = useBillStatus(orderUuid, patientUuid);
|
|
15
|
+
|
|
16
|
+
const isInProgress = order?.fulfillerStatus === FulfillerStatus.IN_PROGRESS;
|
|
17
|
+
const buttonText = hasPendingPayment ? t('unsettledBill', 'Unsettled bill') : t('pickLabRequest', 'Pick Lab Request');
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
isLoading,
|
|
21
|
+
isDisabled: hasPendingPayment,
|
|
22
|
+
buttonText,
|
|
23
|
+
isInProgress,
|
|
24
|
+
orderUuid,
|
|
25
|
+
patientUuid,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useTranslation } from 'react-i18next';
|
|
2
|
+
import { useStockItemQuantity } from '../../useBillableItem';
|
|
3
|
+
import { useBillableServices } from '../../../billable-service.resource';
|
|
4
|
+
|
|
5
|
+
import { useBillStatus } from './useBillStatus';
|
|
6
|
+
import { createMedicationDispenseProps } from '../../test-order/dispense.resource';
|
|
7
|
+
|
|
8
|
+
interface MedicationRequest {
|
|
9
|
+
request: fhir.MedicationRequest;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useMedicationOrderAction(medicationRequestBundle?: MedicationRequest) {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const request = medicationRequestBundle?.request;
|
|
15
|
+
const orderUuid = request?.id;
|
|
16
|
+
const patientUuid = request?.subject?.reference?.split('/')[1];
|
|
17
|
+
const drugUuid = request?.medicationReference?.reference?.split('/')[1];
|
|
18
|
+
|
|
19
|
+
const { isLoading, hasPendingPayment, itemHasBill } = useBillStatus(orderUuid, patientUuid);
|
|
20
|
+
const { stockItemQuantity, stockItemUuid } = useStockItemQuantity(drugUuid);
|
|
21
|
+
const { billableServices } = useBillableServices();
|
|
22
|
+
|
|
23
|
+
const billableItem =
|
|
24
|
+
billableServices?.filter((service) => {
|
|
25
|
+
const stockItem = service?.stockItem.split(':')[0];
|
|
26
|
+
return stockItem === stockItemUuid;
|
|
27
|
+
}) || [];
|
|
28
|
+
|
|
29
|
+
const dispenseFormProps = medicationRequestBundle ? createMedicationDispenseProps({ medicationRequestBundle }) : null;
|
|
30
|
+
|
|
31
|
+
const shouldShowBillModal = stockItemQuantity > 0 && itemHasBill.length < 1 && billableItem.length > 0;
|
|
32
|
+
const isDisabled = hasPendingPayment || (stockItemQuantity < 1 && !!drugUuid);
|
|
33
|
+
|
|
34
|
+
// Modification is allowed only when:
|
|
35
|
+
// 1. There are no pending payments
|
|
36
|
+
// 2. Stock item is available (quantity > 0)
|
|
37
|
+
// 3. Item hasn't been billed yet (no existing bills)
|
|
38
|
+
// 4. Item exists in billable items list
|
|
39
|
+
const shouldAllowModify =
|
|
40
|
+
!hasPendingPayment && stockItemQuantity > 0 && itemHasBill.length < 1 && billableItem.length > 0;
|
|
41
|
+
|
|
42
|
+
const getButtonText = () => {
|
|
43
|
+
if (hasPendingPayment) {
|
|
44
|
+
return t('unsettledBill', 'Unsettled bill');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (stockItemQuantity < 1 && drugUuid) {
|
|
48
|
+
return t('outOfStock', 'Out of Stock');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (shouldShowBillModal) {
|
|
52
|
+
return t('bill', 'Bill');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return t('dispense', 'Dispense');
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
isLoading,
|
|
60
|
+
isDisabled,
|
|
61
|
+
buttonText: getButtonText(),
|
|
62
|
+
shouldShowBillModal,
|
|
63
|
+
dispenseFormProps,
|
|
64
|
+
orderUuid,
|
|
65
|
+
patientUuid,
|
|
66
|
+
billableItem,
|
|
67
|
+
itemHasBill,
|
|
68
|
+
medicationRequestBundle,
|
|
69
|
+
hasPendingPayment,
|
|
70
|
+
shouldAllowModify,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
import { useMemo } from 'react';
|
|
75
|
+
import { FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
76
|
+
import { Order } from '@openmrs/esm-patient-common-lib';
|
|
77
|
+
import useSWR from 'swr';
|
|
78
|
+
|
|
79
|
+
const customRepresentation =
|
|
80
|
+
'custom:(uuid,dosingType,orderNumber,accessionNumber,' +
|
|
81
|
+
'patient:ref,action,careSetting:ref,previousOrder:ref,dateActivated,scheduledDate,dateStopped,autoExpireDate,' +
|
|
82
|
+
'orderType:ref,encounter:ref,orderer:(uuid,display,person:(display)),orderReason,orderReasonNonCoded,orderType,urgency,instructions,' +
|
|
83
|
+
'commentToFulfiller,drug:(uuid,display,strength,dosageForm:(display,uuid),concept),dose,doseUnits:ref,' +
|
|
84
|
+
'frequency:ref,asNeeded,asNeededCondition,quantity,quantityUnits:ref,numRefills,dosingInstructions,' +
|
|
85
|
+
'duration,durationUnits:ref,route:ref,brandName,dispenseAsWritten)';
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Hook to get a single order by UUID.
|
|
89
|
+
*
|
|
90
|
+
* @param orderUuid The UUID of the order to fetch.
|
|
91
|
+
*/
|
|
92
|
+
export function useOrderByUuid(orderUuid: string) {
|
|
93
|
+
const ordersUrl = useMemo(
|
|
94
|
+
() => (orderUuid ? `${restBaseUrl}/order/${orderUuid}?v=${customRepresentation}` : null),
|
|
95
|
+
[orderUuid],
|
|
96
|
+
);
|
|
97
|
+
const { data, error, isLoading, isValidating, mutate } = useSWR<FetchResponse<Order>, Error>(ordersUrl, openmrsFetch);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
data: data?.data,
|
|
101
|
+
error,
|
|
102
|
+
isLoading,
|
|
103
|
+
isValidating,
|
|
104
|
+
mutate,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { launchWorkspace } from '@openmrs/esm-framework';
|
|
2
|
+
import { Order } from '@openmrs/esm-patient-common-lib';
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { mutate } from 'swr';
|
|
5
|
+
|
|
6
|
+
export function useModalHandler(mutateUrl?: string) {
|
|
7
|
+
const handleModalClose = useCallback(() => {
|
|
8
|
+
if (!mutateUrl) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
mutate((key) => typeof key === 'string' && key.startsWith(mutateUrl), undefined, {
|
|
13
|
+
revalidate: true,
|
|
14
|
+
});
|
|
15
|
+
}, [mutateUrl]);
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
handleModalClose,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const launchPrescriptionEditWorkspace = (order: Order, patientUuid: string) => {
|
|
23
|
+
const newItem = {
|
|
24
|
+
uuid: order.uuid,
|
|
25
|
+
display: order.drug?.display,
|
|
26
|
+
previousOrder: order.uuid,
|
|
27
|
+
startDate: new Date(),
|
|
28
|
+
action: 'REVISE',
|
|
29
|
+
drug: order.drug,
|
|
30
|
+
dosage: order.dose,
|
|
31
|
+
unit: {
|
|
32
|
+
value: order.doseUnits?.display,
|
|
33
|
+
valueCoded: order.doseUnits?.uuid,
|
|
34
|
+
},
|
|
35
|
+
frequency: {
|
|
36
|
+
valueCoded: order.frequency?.uuid,
|
|
37
|
+
value: order.frequency?.display,
|
|
38
|
+
},
|
|
39
|
+
route: {
|
|
40
|
+
valueCoded: order.route?.uuid,
|
|
41
|
+
value: order.route?.display,
|
|
42
|
+
},
|
|
43
|
+
commonMedicationName: order.drug?.display,
|
|
44
|
+
isFreeTextDosage: order.dosingType === 'org.openmrs.FreeTextDosingInstructions',
|
|
45
|
+
freeTextDosage: order.dosingType === 'org.openmrs.FreeTextDosingInstructions' ? order.dosingInstructions : '',
|
|
46
|
+
patientInstructions: order.dosingType !== 'org.openmrs.FreeTextDosingInstructions' ? order.dosingInstructions : '',
|
|
47
|
+
asNeeded: order.asNeeded,
|
|
48
|
+
asNeededCondition: order.asNeededCondition,
|
|
49
|
+
duration: order.duration,
|
|
50
|
+
durationUnit: {
|
|
51
|
+
valueCoded: order.durationUnits?.uuid,
|
|
52
|
+
value: order.durationUnits?.display,
|
|
53
|
+
},
|
|
54
|
+
pillsDispensed: order.quantity,
|
|
55
|
+
numRefills: order.numRefills,
|
|
56
|
+
indication: order.orderReasonNonCoded,
|
|
57
|
+
orderer: order.orderer?.uuid,
|
|
58
|
+
careSetting: order.careSetting?.uuid,
|
|
59
|
+
quantityUnits: {
|
|
60
|
+
value: order.quantityUnits?.display,
|
|
61
|
+
valueCoded: order.quantityUnits?.uuid,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
launchWorkspace('add-drug-order', { patientUuid, order: newItem });
|
|
66
|
+
};
|
|
File without changes
|
package/src/claims/dashboard/form/claims-explanation-and-justification-form-input.component.tsx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Column, InlineLoading, InlineNotification, Layer, TextArea } from '@carbon/react';
|
|
2
|
+
import { usePatient } from '@openmrs/esm-framework';
|
|
3
|
+
import React, { useEffect, useMemo } from 'react';
|
|
4
|
+
import { Controller, useFormContext } from 'react-hook-form';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { InterventionsFilter, useInterventions } from '../../../hooks/useInterventions';
|
|
7
|
+
import usePackages from '../../../hooks/usePackages';
|
|
8
|
+
import styles from './claims-form.scss';
|
|
9
|
+
|
|
10
|
+
type ClaimExplanationAndJusificationInputProps = {
|
|
11
|
+
patientUuid: string;
|
|
12
|
+
};
|
|
13
|
+
const ClaimExplanationAndJusificationInput: React.FC<ClaimExplanationAndJusificationInputProps> = ({ patientUuid }) => {
|
|
14
|
+
const { error: patientError, isLoading: isPatientLoading, patient } = usePatient(patientUuid);
|
|
15
|
+
|
|
16
|
+
const form = useFormContext<{
|
|
17
|
+
claimExplanation: string;
|
|
18
|
+
claimJustification: string;
|
|
19
|
+
packages: Array<string>;
|
|
20
|
+
interventions: Array<string>;
|
|
21
|
+
}>();
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const { isLoading: packagesLoading, error: packageError, packages: shaPackages } = usePackages();
|
|
24
|
+
const { setValue } = form;
|
|
25
|
+
const packagesObservable = form.watch('packages');
|
|
26
|
+
const interventionsObservable = form.watch('interventions');
|
|
27
|
+
const filters = useMemo<InterventionsFilter>(
|
|
28
|
+
() => ({
|
|
29
|
+
package_code: packagesObservable.join(','),
|
|
30
|
+
applicable_gender: patient?.gender === 'male' ? 'MALE' : 'FEMALE',
|
|
31
|
+
}),
|
|
32
|
+
[packagesObservable, patient],
|
|
33
|
+
);
|
|
34
|
+
const { error: interventionsError, isLoading: isLoadingInterventions, allInterventions } = useInterventions(filters);
|
|
35
|
+
const packagesSelected = useMemo(
|
|
36
|
+
() =>
|
|
37
|
+
packagesObservable
|
|
38
|
+
.map((packageCode) => shaPackages.find((pkg) => pkg.uuid === packageCode))
|
|
39
|
+
?.map((p) => p?.packageName ?? '')
|
|
40
|
+
.filter(Boolean) ?? [],
|
|
41
|
+
[packagesObservable, shaPackages],
|
|
42
|
+
);
|
|
43
|
+
const interventionSelected = useMemo(
|
|
44
|
+
() =>
|
|
45
|
+
interventionsObservable.map(
|
|
46
|
+
(interventionCode) =>
|
|
47
|
+
allInterventions.find((intervention) => intervention.interventionCode === interventionCode)?.interventionName,
|
|
48
|
+
) ?? [],
|
|
49
|
+
[interventionsObservable, allInterventions],
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
setValue('claimExplanation', packagesSelected.join(', '));
|
|
54
|
+
setValue('claimJustification', interventionSelected.join(', '));
|
|
55
|
+
}, [packagesSelected, setValue, interventionSelected]);
|
|
56
|
+
|
|
57
|
+
if (packagesLoading || isPatientLoading || isLoadingInterventions) {
|
|
58
|
+
return (
|
|
59
|
+
<InlineLoading description={t('loading', 'Loading')} iconDescription={t('loading', 'Loading data') + '...'} />
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (packageError || patientError || interventionsError) {
|
|
64
|
+
return (
|
|
65
|
+
<InlineNotification
|
|
66
|
+
aria-label="closes notification"
|
|
67
|
+
kind="error"
|
|
68
|
+
lowContrast={true}
|
|
69
|
+
statusIconDescription="notification"
|
|
70
|
+
title={t('errorLoadingpackages', 'Error loading packages')}
|
|
71
|
+
subtitle={packageError?.message ?? packageError?.message ?? interventionsError?.message}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<>
|
|
78
|
+
<Column>
|
|
79
|
+
<Layer className={styles.input}>
|
|
80
|
+
<Controller
|
|
81
|
+
control={form.control}
|
|
82
|
+
name="claimExplanation"
|
|
83
|
+
render={({ field, fieldState: { error } }) => (
|
|
84
|
+
<TextArea
|
|
85
|
+
{...field}
|
|
86
|
+
labelText={t('claimExplanation', 'Claim Explanation')}
|
|
87
|
+
rows={3}
|
|
88
|
+
placeholder="Claim Explanation"
|
|
89
|
+
id="claimExplanation"
|
|
90
|
+
invalid={!!error?.message}
|
|
91
|
+
invalidText={error?.message}
|
|
92
|
+
/>
|
|
93
|
+
)}
|
|
94
|
+
/>
|
|
95
|
+
</Layer>
|
|
96
|
+
</Column>
|
|
97
|
+
<Column>
|
|
98
|
+
<Layer className={styles.input}>
|
|
99
|
+
<Controller
|
|
100
|
+
control={form.control}
|
|
101
|
+
name="claimJustification"
|
|
102
|
+
render={({ field, fieldState: { error } }) => (
|
|
103
|
+
<TextArea
|
|
104
|
+
{...field}
|
|
105
|
+
labelText={t('claimJustification', 'Claim Justification')}
|
|
106
|
+
rows={3}
|
|
107
|
+
placeholder="Claim Justification"
|
|
108
|
+
id="claimJustification"
|
|
109
|
+
invalid={!!error?.message}
|
|
110
|
+
invalidText={error?.message}
|
|
111
|
+
/>
|
|
112
|
+
)}
|
|
113
|
+
/>
|
|
114
|
+
</Layer>
|
|
115
|
+
</Column>
|
|
116
|
+
</>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export default ClaimExplanationAndJusificationInput;
|