@ampath/esm-dispensing-app 1.10.0-next.2 → 1.10.0-next.21
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/dist/3568.js +1 -1
- package/dist/3568.js.map +1 -1
- package/dist/3693.js +1 -0
- package/dist/3693.js.map +1 -0
- package/dist/{7252.js → 4099.js} +1 -1
- package/dist/{7252.js.map → 4099.js.map} +1 -1
- package/dist/4300.js +1 -1
- package/dist/6841.js +1 -1
- package/dist/6841.js.map +1 -1
- package/dist/963.js +1 -1
- package/dist/963.js.map +1 -1
- package/dist/9764.js +1 -0
- package/dist/9764.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-dispensing-app.js +1 -1
- package/dist/openmrs-esm-dispensing-app.js.buildmanifest.json +87 -87
- package/dist/routes.json +1 -1
- package/package.json +2 -1
- package/src/bill/bill.resource.ts +89 -0
- package/src/components/action-buttons.component.tsx +97 -5
- package/src/components/action-buttons.test.tsx +22 -2
- package/src/components/prescription-actions/close-action-button.component.tsx +3 -0
- package/src/components/prescription-actions/dispense-action-button.component.tsx +17 -4
- package/src/components/prescription-actions/generate-bill-action-button.component.tsx +53 -0
- package/src/components/prescription-actions/pause-action-button.component.tsx +3 -0
- package/src/config-schema.ts +36 -0
- package/src/forms/close-dispense-form.workspace.tsx +13 -1
- package/src/forms/pause-dispense-form.workspace.tsx +13 -1
- package/src/index.ts +3 -1
- package/src/location/location.resource.test.tsx +46 -8
- package/src/location/location.resource.tsx +7 -4
- package/src/medication-request/medication-request.resource.test.tsx +2 -6
- package/src/medication-request/medication-request.resource.tsx +97 -11
- package/src/prescriptions/prescription-details.component.tsx +59 -18
- package/src/prescriptions/prescription-details.test.tsx +70 -1
- package/src/prescriptions/prescription-tab-panel.component.tsx +23 -2
- package/src/prescriptions/prescriptions-table.component.tsx +53 -23
- package/src/prescriptions/priority-tag.component.tsx +44 -0
- package/src/prescriptions/priority-tag.scss +12 -0
- package/src/print-prescription/prescription-printout.component.tsx +10 -3
- package/src/routes.json +5 -0
- package/src/types.ts +53 -1
- package/src/utils.test.ts +9 -9
- package/src/utils.ts +36 -2
- package/src/visit/visit.resource.ts +1 -1
- package/translations/en.json +5 -0
- package/dist/609.js +0 -1
- package/dist/609.js.map +0 -1
- package/dist/8885.js +0 -1
- package/dist/8885.js.map +0 -1
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
|
-
import { useConfig, ExtensionSlot } from '@openmrs/esm-framework';
|
|
3
|
+
import { useConfig, ExtensionSlot, type Order } from '@openmrs/esm-framework';
|
|
4
4
|
import { computeMedicationRequestStatus, getMostRecentMedicationDispenseStatus } from '../utils';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type BillInvoice,
|
|
7
|
+
type BillStatus,
|
|
8
|
+
MedicationDispenseStatus,
|
|
9
|
+
type MedicationRequest,
|
|
10
|
+
MedicationRequestStatus,
|
|
11
|
+
} from '../types';
|
|
6
12
|
import ActionButtons from './action-buttons.component';
|
|
7
13
|
import CloseActionButton from './prescription-actions/close-action-button.component';
|
|
8
14
|
import DispenseActionButton from './prescription-actions/dispense-action-button.component';
|
|
@@ -111,6 +117,10 @@ const medicationRequest: MedicationRequest = {
|
|
|
111
117
|
const medicationRequestStatus = computeMedicationRequestStatus(medicationRequest, 90);
|
|
112
118
|
const mostRecentMedicationDispenseStatus: MedicationDispenseStatus = getMostRecentMedicationDispenseStatus([]);
|
|
113
119
|
|
|
120
|
+
const orders = [] as Order[];
|
|
121
|
+
const bills = [] as BillInvoice[];
|
|
122
|
+
const mutated = () => {};
|
|
123
|
+
|
|
114
124
|
const prescriptionActionsState = {
|
|
115
125
|
dispensable:
|
|
116
126
|
medicationRequestStatus === MedicationRequestStatus.active &&
|
|
@@ -125,6 +135,8 @@ const prescriptionActionsState = {
|
|
|
125
135
|
session: undefined,
|
|
126
136
|
providers: [],
|
|
127
137
|
disabled: false,
|
|
138
|
+
billStatus: 'PAID' as BillStatus,
|
|
139
|
+
hasActiveRequests: true,
|
|
128
140
|
};
|
|
129
141
|
|
|
130
142
|
describe('Action Buttons Component tests', () => {
|
|
@@ -162,6 +174,10 @@ describe('Action Buttons Component tests', () => {
|
|
|
162
174
|
encounterUuid={mockEncounterUuid}
|
|
163
175
|
medicationRequestBundle={{ request: medicationRequest, dispenses: [] }}
|
|
164
176
|
disabled={false}
|
|
177
|
+
orders={orders}
|
|
178
|
+
bills={bills}
|
|
179
|
+
mutated={mutated}
|
|
180
|
+
isLoading={false}
|
|
165
181
|
/>,
|
|
166
182
|
);
|
|
167
183
|
expect(getByText('Dispense')).toBeInTheDocument();
|
|
@@ -209,6 +225,10 @@ describe('Action Buttons Component tests', () => {
|
|
|
209
225
|
encounterUuid={mockEncounterUuid}
|
|
210
226
|
medicationRequestBundle={{ request: expiredMedicationRequest, dispenses: [] }}
|
|
211
227
|
disabled={false}
|
|
228
|
+
orders={orders}
|
|
229
|
+
bills={bills}
|
|
230
|
+
mutated={mutated}
|
|
231
|
+
isLoading={false}
|
|
212
232
|
/>,
|
|
213
233
|
);
|
|
214
234
|
|
|
@@ -13,6 +13,7 @@ type CloseActionButtonProps = {
|
|
|
13
13
|
providers: Array<Provider>;
|
|
14
14
|
closeable: boolean;
|
|
15
15
|
disabled: boolean;
|
|
16
|
+
hasActiveRequests: boolean;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const CloseActionButton: React.FC<CloseActionButtonProps> = ({
|
|
@@ -23,6 +24,7 @@ const CloseActionButton: React.FC<CloseActionButtonProps> = ({
|
|
|
23
24
|
providers,
|
|
24
25
|
closeable,
|
|
25
26
|
disabled,
|
|
27
|
+
hasActiveRequests,
|
|
26
28
|
}) => {
|
|
27
29
|
const { t } = useTranslation();
|
|
28
30
|
|
|
@@ -31,6 +33,7 @@ const CloseActionButton: React.FC<CloseActionButtonProps> = ({
|
|
|
31
33
|
encounterUuid,
|
|
32
34
|
medicationDispense: initiateMedicationDispenseBody(medicationRequestBundle.request, session, providers, false),
|
|
33
35
|
mode: 'enter',
|
|
36
|
+
hasActiveRequests,
|
|
34
37
|
};
|
|
35
38
|
|
|
36
39
|
const handleLaunchWorkspace = () => {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Button } from '@carbon/react';
|
|
2
|
+
import { Button, Tag } from '@carbon/react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { launchWorkspace2, type Session } from '@openmrs/esm-framework';
|
|
5
5
|
import { initiateMedicationDispenseBody } from '../../medication-dispense/medication-dispense.resource';
|
|
6
|
-
import { type Provider, type MedicationRequestBundle } from '../../types';
|
|
6
|
+
import { type Provider, type MedicationRequestBundle, type BillStatus } from '../../types';
|
|
7
|
+
import { usePatientBills } from '../../bill/bill.resource';
|
|
7
8
|
|
|
8
9
|
type DispenseActionButtonProps = {
|
|
9
10
|
patientUuid: string;
|
|
@@ -15,6 +16,7 @@ type DispenseActionButtonProps = {
|
|
|
15
16
|
quantityRemaining: number;
|
|
16
17
|
quantityDispensed: number;
|
|
17
18
|
disabled: boolean;
|
|
19
|
+
billStatus: BillStatus;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
const DispenseActionButton: React.FC<DispenseActionButtonProps> = ({
|
|
@@ -27,6 +29,7 @@ const DispenseActionButton: React.FC<DispenseActionButtonProps> = ({
|
|
|
27
29
|
quantityRemaining,
|
|
28
30
|
quantityDispensed,
|
|
29
31
|
disabled,
|
|
32
|
+
billStatus = 'PAID',
|
|
30
33
|
}) => {
|
|
31
34
|
const { t } = useTranslation();
|
|
32
35
|
const dispenseWorkspaceProps = {
|
|
@@ -39,6 +42,8 @@ const DispenseActionButton: React.FC<DispenseActionButtonProps> = ({
|
|
|
39
42
|
mode: 'enter',
|
|
40
43
|
};
|
|
41
44
|
|
|
45
|
+
const { currentDayBills } = usePatientBills(patientUuid);
|
|
46
|
+
|
|
42
47
|
const handleLaunchWorkspace = () => {
|
|
43
48
|
launchWorkspace2('dispense-workspace', dispenseWorkspaceProps);
|
|
44
49
|
};
|
|
@@ -47,11 +52,19 @@ const DispenseActionButton: React.FC<DispenseActionButtonProps> = ({
|
|
|
47
52
|
return null;
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
|
|
55
|
+
if (currentDayBills && currentDayBills.length && (billStatus === 'PAID' || billStatus === 'POSTED')) {
|
|
56
|
+
return (
|
|
57
|
+
<Tag type="red" size="lg">
|
|
58
|
+
{t('clearPendingBills', 'Clear pending bills to dispense')}
|
|
59
|
+
</Tag>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return billStatus === 'PAID' || billStatus === 'POSTED' ? (
|
|
51
64
|
<Button kind="primary" onClick={handleLaunchWorkspace} disabled={disabled}>
|
|
52
65
|
{t('dispense', 'Dispense')}
|
|
53
66
|
</Button>
|
|
54
|
-
);
|
|
67
|
+
) : null;
|
|
55
68
|
};
|
|
56
69
|
|
|
57
70
|
export default DispenseActionButton;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, InlineLoading } from '@carbon/react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { launchWorkspace, type Order, useConfig } from '@openmrs/esm-framework';
|
|
5
|
+
import { type MedicationRequestBundle, type BillStatus } from '../../types';
|
|
6
|
+
import { type PharmacyConfig } from '../../config-schema';
|
|
7
|
+
|
|
8
|
+
type GenerateBillActionButtonProps = {
|
|
9
|
+
medicationRequestBundle: MedicationRequestBundle;
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
billStatus: BillStatus;
|
|
12
|
+
order: Order;
|
|
13
|
+
dispensable: boolean;
|
|
14
|
+
mutated: () => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const GenerateBillActionButton: React.FC<GenerateBillActionButtonProps> = ({
|
|
18
|
+
medicationRequestBundle,
|
|
19
|
+
isLoading,
|
|
20
|
+
billStatus,
|
|
21
|
+
order,
|
|
22
|
+
dispensable,
|
|
23
|
+
mutated,
|
|
24
|
+
}) => {
|
|
25
|
+
const { t } = useTranslation();
|
|
26
|
+
const { pharmacyServiceTypedUuid } = useConfig<PharmacyConfig>();
|
|
27
|
+
|
|
28
|
+
const launchBillWorkspace = () => {
|
|
29
|
+
launchWorkspace('create-order-bill-form-workspace', {
|
|
30
|
+
workspaceTitle: t('createOrderBill', 'Create order bill form'),
|
|
31
|
+
order: order,
|
|
32
|
+
quantity: medicationRequestBundle.request.dispenseRequest.quantity.value,
|
|
33
|
+
serviceTypeUuid: pharmacyServiceTypedUuid,
|
|
34
|
+
mutated,
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
if (!dispensable) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return isLoading ? (
|
|
43
|
+
<InlineLoading description="Checking bills" />
|
|
44
|
+
) : billStatus === 'PENDING' ? (
|
|
45
|
+
<Button kind="secondary">{t('pendingPayment', 'Pending payment')}</Button>
|
|
46
|
+
) : billStatus === 'BLANK' ? (
|
|
47
|
+
<Button kind="primary" onClick={launchBillWorkspace}>
|
|
48
|
+
{t('generateBill', 'Generate bill')}
|
|
49
|
+
</Button>
|
|
50
|
+
) : null;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default GenerateBillActionButton;
|
|
@@ -13,6 +13,7 @@ type PauseActionButtonProps = {
|
|
|
13
13
|
providers: Array<Provider>;
|
|
14
14
|
pauseable: boolean;
|
|
15
15
|
disabled: boolean;
|
|
16
|
+
hasActiveRequests: boolean;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const PauseActionButton: React.FC<PauseActionButtonProps> = ({
|
|
@@ -23,6 +24,7 @@ const PauseActionButton: React.FC<PauseActionButtonProps> = ({
|
|
|
23
24
|
providers,
|
|
24
25
|
pauseable,
|
|
25
26
|
disabled,
|
|
27
|
+
hasActiveRequests,
|
|
26
28
|
}) => {
|
|
27
29
|
const { t } = useTranslation();
|
|
28
30
|
const pauseWorkspaceProps = {
|
|
@@ -30,6 +32,7 @@ const PauseActionButton: React.FC<PauseActionButtonProps> = ({
|
|
|
30
32
|
encounterUuid,
|
|
31
33
|
medicationDispense: initiateMedicationDispenseBody(medicationRequestBundle.request, session, providers, false),
|
|
32
34
|
mode: 'enter',
|
|
35
|
+
hasActiveRequests,
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
const handleLaunchWorkspace = () => {
|
package/src/config-schema.ts
CHANGED
|
@@ -77,6 +77,16 @@ export const configSchema = {
|
|
|
77
77
|
_description: 'Name of the attribute used to associate locations with a pharmacy location',
|
|
78
78
|
_default: 'Associated Pharmacy Location',
|
|
79
79
|
},
|
|
80
|
+
useAssociatedPharmacyLocations: {
|
|
81
|
+
_type: Type.Boolean,
|
|
82
|
+
_description: 'Show medication requests from all associated pharmacy locations of the current location',
|
|
83
|
+
_default: false,
|
|
84
|
+
},
|
|
85
|
+
useCurrentLocation: {
|
|
86
|
+
_type: Type.Boolean,
|
|
87
|
+
_description: 'Show medication requests from current location',
|
|
88
|
+
_default: false,
|
|
89
|
+
},
|
|
80
90
|
},
|
|
81
91
|
},
|
|
82
92
|
refreshInterval: {
|
|
@@ -146,6 +156,26 @@ export const configSchema = {
|
|
|
146
156
|
_description: 'Custom tabs to be added to the prescription panel. See README for more details.',
|
|
147
157
|
_default: [],
|
|
148
158
|
},
|
|
159
|
+
pharmacyServiceTypedUuid: {
|
|
160
|
+
_type: Type.UUID,
|
|
161
|
+
_default: '3adgb9de-5545-2572-add4-a661005f727r',
|
|
162
|
+
_description: 'Pharmacy billable service type',
|
|
163
|
+
},
|
|
164
|
+
enableOdooBilling: {
|
|
165
|
+
_type: Type.Boolean,
|
|
166
|
+
_default: false,
|
|
167
|
+
_description: 'Enable Odoo billing',
|
|
168
|
+
},
|
|
169
|
+
blockedPaymentModes: {
|
|
170
|
+
_type: Type.Array,
|
|
171
|
+
_default: ['MPESA', 'CASH'],
|
|
172
|
+
_description: 'Payment modes that require bill generation before picking an order',
|
|
173
|
+
},
|
|
174
|
+
serviceUuid: {
|
|
175
|
+
_type: Type.UUID,
|
|
176
|
+
_default: '2d4472e2-d7ab-4430-8e0e-a9ffcd809bf4',
|
|
177
|
+
_description: 'Service Uuid for filtering queues',
|
|
178
|
+
},
|
|
149
179
|
};
|
|
150
180
|
|
|
151
181
|
export interface PharmacyConfig {
|
|
@@ -174,6 +204,8 @@ export interface PharmacyConfig {
|
|
|
174
204
|
enabled: boolean;
|
|
175
205
|
tag: string;
|
|
176
206
|
associatedPharmacyLocationAttribute: string;
|
|
207
|
+
useAssociatedPharmacyLocations: boolean;
|
|
208
|
+
useCurrentLocation: boolean;
|
|
177
209
|
};
|
|
178
210
|
};
|
|
179
211
|
valueSets: {
|
|
@@ -195,4 +227,8 @@ export interface PharmacyConfig {
|
|
|
195
227
|
validateBatch: boolean;
|
|
196
228
|
leftNavMode: 'normal' | 'collapsed' | 'hidden';
|
|
197
229
|
customTabs: Array<CustomTab>;
|
|
230
|
+
pharmacyServiceTypedUuid: string;
|
|
231
|
+
enableOdooBilling: boolean;
|
|
232
|
+
blockedPaymentModes: Array<string>;
|
|
233
|
+
serviceUuid: string;
|
|
198
234
|
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
showSnackbar,
|
|
9
9
|
useConfig,
|
|
10
10
|
usePatient,
|
|
11
|
+
useVisit,
|
|
11
12
|
Workspace2,
|
|
12
13
|
type Workspace2DefinitionProps,
|
|
13
14
|
} from '@openmrs/esm-framework';
|
|
@@ -17,6 +18,7 @@ import { type MedicationDispense, MedicationDispenseStatus, MedicationRequestFul
|
|
|
17
18
|
import { type PharmacyConfig } from '../config-schema';
|
|
18
19
|
import { getUuidFromReference, markEncounterAsStale, revalidate } from '../utils';
|
|
19
20
|
import styles from './forms.scss';
|
|
21
|
+
import { endVisit } from '../visit/visit.resource';
|
|
20
22
|
|
|
21
23
|
type CloseDispenseFormProps = {
|
|
22
24
|
medicationDispense: MedicationDispense;
|
|
@@ -24,15 +26,17 @@ type CloseDispenseFormProps = {
|
|
|
24
26
|
patientUuid?: string;
|
|
25
27
|
encounterUuid: string;
|
|
26
28
|
customWorkspaceTitle?: string;
|
|
29
|
+
hasActiveRequests: boolean;
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
const CloseDispenseForm: React.FC<Workspace2DefinitionProps<CloseDispenseFormProps, {}, {}>> = ({
|
|
30
|
-
workspaceProps: { medicationDispense, mode, patientUuid, encounterUuid, customWorkspaceTitle },
|
|
33
|
+
workspaceProps: { medicationDispense, mode, patientUuid, encounterUuid, customWorkspaceTitle, hasActiveRequests },
|
|
31
34
|
closeWorkspace,
|
|
32
35
|
}) => {
|
|
33
36
|
const { t } = useTranslation();
|
|
34
37
|
const config = useConfig<PharmacyConfig>();
|
|
35
38
|
const { patient, isLoading } = usePatient(patientUuid);
|
|
39
|
+
const { activeVisit } = useVisit(patientUuid);
|
|
36
40
|
|
|
37
41
|
// Keep track of medication dispense payload
|
|
38
42
|
const [medicationDispensePayload, setMedicationDispensePayload] = useState<MedicationDispense>();
|
|
@@ -92,6 +96,14 @@ const CloseDispenseForm: React.FC<Workspace2DefinitionProps<CloseDispenseFormPro
|
|
|
92
96
|
mode === 'enter' ? 'Medication dispense closed.' : 'Dispense record successfully updated.',
|
|
93
97
|
),
|
|
94
98
|
});
|
|
99
|
+
if (!hasActiveRequests) {
|
|
100
|
+
if (config.dispenseBehavior.endActiveVisitOnCompletingOrder) {
|
|
101
|
+
if (activeVisit) {
|
|
102
|
+
const visitUuid = activeVisit?.uuid;
|
|
103
|
+
endVisit(visitUuid).then(() => {});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
95
107
|
closeWorkspace({ discardUnsavedChanges: true });
|
|
96
108
|
}
|
|
97
109
|
})
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
showSnackbar,
|
|
9
9
|
useConfig,
|
|
10
10
|
usePatient,
|
|
11
|
+
useVisit,
|
|
11
12
|
Workspace2,
|
|
12
13
|
type Workspace2DefinitionProps,
|
|
13
14
|
} from '@openmrs/esm-framework';
|
|
@@ -17,6 +18,7 @@ import { getUuidFromReference, markEncounterAsStale, revalidate } from '../utils
|
|
|
17
18
|
import { type MedicationDispense, MedicationDispenseStatus, MedicationRequestFulfillerStatus } from '../types';
|
|
18
19
|
import { type PharmacyConfig } from '../config-schema';
|
|
19
20
|
import styles from './forms.scss';
|
|
21
|
+
import { endVisit } from '../visit/visit.resource';
|
|
20
22
|
|
|
21
23
|
type PauseDispenseFormProps = {
|
|
22
24
|
medicationDispense: MedicationDispense;
|
|
@@ -24,15 +26,17 @@ type PauseDispenseFormProps = {
|
|
|
24
26
|
patientUuid?: string;
|
|
25
27
|
encounterUuid: string;
|
|
26
28
|
customWorkspaceTitle?: string;
|
|
29
|
+
hasActiveRequests: boolean;
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
const PauseDispenseForm: React.FC<Workspace2DefinitionProps<PauseDispenseFormProps, {}, {}>> = ({
|
|
30
|
-
workspaceProps: { medicationDispense, mode, patientUuid, encounterUuid, customWorkspaceTitle },
|
|
33
|
+
workspaceProps: { medicationDispense, mode, patientUuid, encounterUuid, customWorkspaceTitle, hasActiveRequests },
|
|
31
34
|
closeWorkspace,
|
|
32
35
|
}) => {
|
|
33
36
|
const { t } = useTranslation();
|
|
34
37
|
const config = useConfig<PharmacyConfig>();
|
|
35
38
|
const { patient, isLoading } = usePatient(patientUuid);
|
|
39
|
+
const { activeVisit } = useVisit(patientUuid);
|
|
36
40
|
|
|
37
41
|
// Keep track of medication dispense payload
|
|
38
42
|
const [medicationDispensePayload, setMedicationDispensePayload] = useState<MedicationDispense>();
|
|
@@ -92,6 +96,14 @@ const PauseDispenseForm: React.FC<Workspace2DefinitionProps<PauseDispenseFormPro
|
|
|
92
96
|
mode === 'enter' ? 'Medication dispense paused.' : 'Dispense record successfully updated.',
|
|
93
97
|
),
|
|
94
98
|
});
|
|
99
|
+
if (!hasActiveRequests) {
|
|
100
|
+
if (config.dispenseBehavior.endActiveVisitOnCompletingOrder) {
|
|
101
|
+
if (activeVisit) {
|
|
102
|
+
const visitUuid = activeVisit?.uuid;
|
|
103
|
+
endVisit(visitUuid).then(() => {});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
95
107
|
closeWorkspace({ discardUnsavedChanges: true });
|
|
96
108
|
}
|
|
97
109
|
})
|
package/src/index.ts
CHANGED
|
@@ -7,10 +7,11 @@ import DispensingDashboardComponent from './dashboard/dispensing-dashboard.compo
|
|
|
7
7
|
import DispensingLinkComponent from './dispensing-link.component';
|
|
8
8
|
import DispensingLinkHomepageComponent from './dashboard/dispensing-dashboard-link.component';
|
|
9
9
|
import PauseActionButton from './components/prescription-actions/pause-action-button.component';
|
|
10
|
+
import GenerateBillActionButton from './components/prescription-actions/generate-bill-action-button.component';
|
|
10
11
|
|
|
11
12
|
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
12
13
|
|
|
13
|
-
const moduleName = '@
|
|
14
|
+
const moduleName = '@ampath/esm-dispensing-app';
|
|
14
15
|
|
|
15
16
|
const options = {
|
|
16
17
|
featureName: 'dispensing',
|
|
@@ -33,6 +34,7 @@ export const dispensingDashboardLink = getSyncLifecycle(DispensingLinkHomepageCo
|
|
|
33
34
|
export const closeActionButton = getSyncLifecycle(CloseActionButton, options);
|
|
34
35
|
export const dispenseActionButton = getSyncLifecycle(DispenseActionButton, options);
|
|
35
36
|
export const pauseActionButton = getSyncLifecycle(PauseActionButton, options);
|
|
37
|
+
export const generateBillActionButton = getSyncLifecycle(GenerateBillActionButton, options);
|
|
36
38
|
|
|
37
39
|
// Dispensing workspace
|
|
38
40
|
// t('closePrescription', 'Close prescription')
|
|
@@ -29,6 +29,8 @@ const pharmacyConfig: PharmacyConfig = {
|
|
|
29
29
|
enabled: false,
|
|
30
30
|
tag: 'Login Location',
|
|
31
31
|
associatedPharmacyLocationAttribute: 'Associated Pharmacy Location',
|
|
32
|
+
useAssociatedPharmacyLocations: true,
|
|
33
|
+
useCurrentLocation: true,
|
|
32
34
|
},
|
|
33
35
|
},
|
|
34
36
|
refreshInterval: 10000,
|
|
@@ -44,6 +46,10 @@ const pharmacyConfig: PharmacyConfig = {
|
|
|
44
46
|
validateBatch: false,
|
|
45
47
|
leftNavMode: 'collapsed',
|
|
46
48
|
customTabs: [],
|
|
49
|
+
pharmacyServiceTypedUuid: '',
|
|
50
|
+
enableOdooBilling: false,
|
|
51
|
+
serviceUuid: '',
|
|
52
|
+
blockedPaymentModes: [],
|
|
47
53
|
};
|
|
48
54
|
|
|
49
55
|
describe('Location Resource tests', () => {
|
|
@@ -80,6 +86,22 @@ describe('Location Resource tests', () => {
|
|
|
80
86
|
uuid: '84b9b680-786c-4388-9e7c-805614c13b5a',
|
|
81
87
|
},
|
|
82
88
|
},
|
|
89
|
+
{
|
|
90
|
+
attributeType: {
|
|
91
|
+
name: 'Associated Pharmacy Location',
|
|
92
|
+
},
|
|
93
|
+
value: {
|
|
94
|
+
uuid: '318bb1dc-77e3-4ac4-b524-cef0e8a456bd',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
attributeType: {
|
|
99
|
+
name: 'Associated Pharmacy Location',
|
|
100
|
+
},
|
|
101
|
+
value: {
|
|
102
|
+
uuid: '879bf321-e857-43a5-8f6b-e28e345a34c1',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
83
105
|
],
|
|
84
106
|
},
|
|
85
107
|
{
|
|
@@ -87,6 +109,16 @@ describe('Location Resource tests', () => {
|
|
|
87
109
|
name: 'KGH NCD',
|
|
88
110
|
attributes: [],
|
|
89
111
|
},
|
|
112
|
+
{
|
|
113
|
+
uuid: '318bb1dc-77e3-4ac4-b524-cef0e8a456bd',
|
|
114
|
+
name: 'KGH MCH Main Pharmacy',
|
|
115
|
+
attributes: [],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
uuid: '879bf321-e857-43a5-8f6b-e28e345a34c1',
|
|
119
|
+
name: 'KGH MCH Revolving Fund Pharmacy',
|
|
120
|
+
attributes: [],
|
|
121
|
+
},
|
|
90
122
|
],
|
|
91
123
|
};
|
|
92
124
|
|
|
@@ -94,16 +126,22 @@ describe('Location Resource tests', () => {
|
|
|
94
126
|
useSWR.mockImplementation(() => ({ data: { data: queryResultsBundle } }));
|
|
95
127
|
const { result } = renderHook(() => useLocations(pharmacyConfig));
|
|
96
128
|
const { locations } = result.current;
|
|
97
|
-
expect(locations.length).toBe(
|
|
129
|
+
expect(locations.length).toBe(5);
|
|
98
130
|
// should be sorted by name alphabetically
|
|
99
131
|
expect(locations[0].id).toBe('5981f962-6eec-453d-89ce-2f9ac48d096f');
|
|
100
132
|
expect(locations[0].name).toBe('KGH MCH');
|
|
101
|
-
expect(locations[0].
|
|
102
|
-
expect(locations[1].id).toBe('
|
|
103
|
-
expect(locations[1].name).toBe('KGH
|
|
104
|
-
expect(locations[1].
|
|
105
|
-
expect(locations[2].id).toBe('
|
|
106
|
-
expect(locations[2].name).toBe('KGH
|
|
107
|
-
expect(locations[2].
|
|
133
|
+
expect(locations[0].associatedPharmacyLocations).toContain('84b9b680-786c-4388-9e7c-805614c13b5a');
|
|
134
|
+
expect(locations[1].id).toBe('318bb1dc-77e3-4ac4-b524-cef0e8a456bd');
|
|
135
|
+
expect(locations[1].name).toBe('KGH MCH Main Pharmacy');
|
|
136
|
+
expect(locations[1].associatedPharmacyLocations).toEqual([]);
|
|
137
|
+
expect(locations[2].id).toBe('879bf321-e857-43a5-8f6b-e28e345a34c1');
|
|
138
|
+
expect(locations[2].name).toBe('KGH MCH Revolving Fund Pharmacy');
|
|
139
|
+
expect(locations[2].associatedPharmacyLocations).toEqual([]);
|
|
140
|
+
expect(locations[3].id).toBe('7b959d2f-11f3-4611-b2e4-700200625d61');
|
|
141
|
+
expect(locations[3].name).toBe('KGH NCD');
|
|
142
|
+
expect(locations[3].associatedPharmacyLocations).toEqual([]);
|
|
143
|
+
expect(locations[4].id).toBe('2bcb9215-8cd6-11eb-b7be-0242ac110002');
|
|
144
|
+
expect(locations[4].name).toBe('KGH Triage');
|
|
145
|
+
expect(locations[4].associatedPharmacyLocations).toEqual([]);
|
|
108
146
|
});
|
|
109
147
|
});
|
|
@@ -16,10 +16,13 @@ export function useLocations(config: PharmacyConfig) {
|
|
|
16
16
|
?.map((e) => ({
|
|
17
17
|
id: e.uuid,
|
|
18
18
|
name: e.name,
|
|
19
|
-
|
|
20
|
-
e.attributes
|
|
21
|
-
(
|
|
22
|
-
|
|
19
|
+
associatedPharmacyLocations:
|
|
20
|
+
e.attributes
|
|
21
|
+
?.filter(
|
|
22
|
+
(a) =>
|
|
23
|
+
a.attributeType.name === config.locationBehavior.locationFilter.associatedPharmacyLocationAttribute,
|
|
24
|
+
)
|
|
25
|
+
?.map((a) => a.value.uuid) ?? [],
|
|
23
26
|
}))
|
|
24
27
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
25
28
|
}, [data?.data?.results, config]);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import dayjs from 'dayjs';
|
|
2
1
|
import useSWR from 'swr';
|
|
3
2
|
import {
|
|
4
3
|
updateMedicationRequestFulfillerStatus,
|
|
@@ -19,15 +18,12 @@ jest.mock('react', () => ({
|
|
|
19
18
|
}));
|
|
20
19
|
|
|
21
20
|
describe('Medication Request Resource Test', () => {
|
|
22
|
-
test('usePrescriptionsTable should call active endpoint
|
|
21
|
+
test('usePrescriptionsTable should call active endpoint with a large fetch count and no page offset when status parameter is active', () => {
|
|
23
22
|
// @ts-ignore
|
|
24
23
|
useSWR.mockImplementation(() => ({ data: { data: 'mockedReturnData' } }));
|
|
25
24
|
usePrescriptionsTable(true, '', 'ACTIVE', 5, 5, 'bob', null, 10, 10000);
|
|
26
25
|
expect(useSWR).toHaveBeenCalledWith(
|
|
27
|
-
`/ws/fhir2/R4/Encounter?_query=encountersWithMedicationRequests&_getpagesoffset=
|
|
28
|
-
.startOf('day')
|
|
29
|
-
.subtract(10, 'day')
|
|
30
|
-
.toISOString()}&status=ACTIVE&patientSearchTerm=bob`,
|
|
26
|
+
`/ws/fhir2/R4/Encounter?_query=encountersWithMedicationRequests&_getpagesoffset=0&_count=200&status=ACTIVE&patientSearchTerm=bob`,
|
|
31
27
|
openmrsFetch,
|
|
32
28
|
{ refreshInterval: 10000 },
|
|
33
29
|
);
|