@kenyaemr/esm-billing-app 5.4.1-pre.2075 → 5.4.1-pre.2077
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 +80 -87
- package/dist/421.js +1 -0
- package/dist/421.js.map +1 -0
- package/dist/746.js +2 -2
- package/dist/kenyaemr-esm-billing-app.js +1 -1
- package/dist/kenyaemr-esm-billing-app.js.buildmanifest.json +32 -32
- package/dist/kenyaemr-esm-billing-app.js.map +1 -1
- 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/bill-manager/workspaces/create-bill/create-bill.workspace.test.tsx +271 -0
- package/src/billable-services/bill-manager/workspaces/create-bill/create-bill.workspace.tsx +174 -40
- package/src/billable-services/billables/charge-summary.resource.tsx +2 -2
- package/src/billable-services/billiable-item/order-actions/components/medication-order-button.component.tsx +6 -11
- package/src/billable-services/billiable-item/order-actions/components/order-action-button.component.tsx +3 -12
- package/src/billable-services/billiable-item/order-actions/hooks/useMedicationOrderAction.ts +5 -2
- package/src/index.ts +77 -53
- package/dist/22.js +0 -1
- package/dist/22.js.map +0 -1
- package/src/billable-services/bill-manager/modals/create-bill-item-modal.component.tsx +0 -208
- package/src/billable-services/bill-manager/modals/create-bill-item-modal.scss +0 -26
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import {
|
|
4
|
-
Button,
|
|
5
|
-
ModalBody,
|
|
6
|
-
ModalFooter,
|
|
7
|
-
ModalHeader,
|
|
8
|
-
Column,
|
|
9
|
-
Dropdown,
|
|
10
|
-
Stack,
|
|
11
|
-
Table,
|
|
12
|
-
TableBody,
|
|
13
|
-
TableCell,
|
|
14
|
-
TableHead,
|
|
15
|
-
TableHeader,
|
|
16
|
-
TableRow,
|
|
17
|
-
} from '@carbon/react';
|
|
18
|
-
import { z } from 'zod';
|
|
19
|
-
import { Controller, useForm } from 'react-hook-form';
|
|
20
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
21
|
-
import { useBillableServices } from '../../billable-service.resource';
|
|
22
|
-
import { showSnackbar, useConfig } from '@openmrs/esm-framework';
|
|
23
|
-
import { BillingConfig } from '../../../config-schema';
|
|
24
|
-
import { billingFormSchema, processBillItems } from '../../../billing.resource';
|
|
25
|
-
import styles from './create-bill-item-modal.scss';
|
|
26
|
-
import { useStockItemQuantity } from '../../billiable-item/useBillableItem';
|
|
27
|
-
|
|
28
|
-
interface CreateBillItemModalProps {
|
|
29
|
-
closeModal: () => void;
|
|
30
|
-
medicationRequestBundle: {
|
|
31
|
-
request: fhir.MedicationRequest;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
type FormType = z.infer<typeof billingFormSchema>;
|
|
36
|
-
|
|
37
|
-
const CreateBillItemModal: React.FC<CreateBillItemModalProps> = ({ closeModal, medicationRequestBundle }) => {
|
|
38
|
-
const { t } = useTranslation();
|
|
39
|
-
const { billableServices, error, isLoading } = useBillableServices();
|
|
40
|
-
const { cashPointUuid, cashierUuid } = useConfig<BillingConfig>();
|
|
41
|
-
|
|
42
|
-
const patientUuid = medicationRequestBundle?.request?.subject?.reference?.split('/')[1];
|
|
43
|
-
const orderUuid = medicationRequestBundle?.request?.id;
|
|
44
|
-
const quantityToDispense = medicationRequestBundle?.request?.dispenseRequest?.quantity?.value;
|
|
45
|
-
const drugUuid = medicationRequestBundle?.request?.medicationReference?.reference?.split('/')[1];
|
|
46
|
-
const { stockItemUuid } = useStockItemQuantity(drugUuid);
|
|
47
|
-
|
|
48
|
-
const billableItem =
|
|
49
|
-
billableServices?.filter((service) => {
|
|
50
|
-
const stockItem = service?.stockItem.split(':')[0];
|
|
51
|
-
return stockItem === stockItemUuid;
|
|
52
|
-
}) || [];
|
|
53
|
-
const defaultPaymentStatus = 'PENDING';
|
|
54
|
-
|
|
55
|
-
const form = useForm<FormType>({
|
|
56
|
-
mode: 'onChange',
|
|
57
|
-
resolver: zodResolver(billingFormSchema),
|
|
58
|
-
defaultValues: {
|
|
59
|
-
cashPoint: cashPointUuid,
|
|
60
|
-
cashier: cashierUuid,
|
|
61
|
-
patient: patientUuid,
|
|
62
|
-
status: 'PENDING',
|
|
63
|
-
lineItems: billableItem.map((service) => ({
|
|
64
|
-
billableService: service.uuid,
|
|
65
|
-
lineItemOrder: 0,
|
|
66
|
-
quantity: quantityToDispense || 1,
|
|
67
|
-
price: 0,
|
|
68
|
-
paymentStatus: defaultPaymentStatus,
|
|
69
|
-
priceUuid: '',
|
|
70
|
-
priceName: '',
|
|
71
|
-
order: orderUuid,
|
|
72
|
-
})),
|
|
73
|
-
payments: [],
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const handleSubmit = async (data: FormType) => {
|
|
78
|
-
const validatedLineItems = data.lineItems.map((item, index) => ({
|
|
79
|
-
...item,
|
|
80
|
-
billableService: billableItem[index]?.uuid,
|
|
81
|
-
order: orderUuid,
|
|
82
|
-
paymentStatus: defaultPaymentStatus,
|
|
83
|
-
}));
|
|
84
|
-
|
|
85
|
-
const validatedData = {
|
|
86
|
-
...data,
|
|
87
|
-
lineItems: validatedLineItems,
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
await processBillItems(validatedData);
|
|
92
|
-
showSnackbar({
|
|
93
|
-
title: t('billItems', 'Save Bill'),
|
|
94
|
-
subtitle: 'Bill processing has been successful',
|
|
95
|
-
kind: 'success',
|
|
96
|
-
timeoutInMs: 3000,
|
|
97
|
-
});
|
|
98
|
-
// TODO: mutate the bill
|
|
99
|
-
closeModal();
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.error('Bill processing error:', error);
|
|
102
|
-
showSnackbar({
|
|
103
|
-
title: 'Bill processing error',
|
|
104
|
-
kind: 'error',
|
|
105
|
-
subtitle: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const calculateTotal = (index: number) => {
|
|
111
|
-
const price = form.watch(`lineItems.${index}.price`) || 0;
|
|
112
|
-
const quantity = form.watch(`lineItems.${index}.quantity`) || 1;
|
|
113
|
-
return price * quantity;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
return (
|
|
117
|
-
<div>
|
|
118
|
-
<form onSubmit={form.handleSubmit(handleSubmit)}>
|
|
119
|
-
<ModalHeader closeModal={closeModal} title={t('billing', 'Billing')} />
|
|
120
|
-
<ModalBody>
|
|
121
|
-
<Stack gap={4} className={styles.grid}>
|
|
122
|
-
<Column className={styles.billingItem}>
|
|
123
|
-
<Table aria-label="billing items table">
|
|
124
|
-
<TableHead>
|
|
125
|
-
<TableRow>
|
|
126
|
-
<TableHeader>Item</TableHeader>
|
|
127
|
-
<TableHeader>Quantity</TableHeader>
|
|
128
|
-
<TableHeader>PaymentMethod</TableHeader>
|
|
129
|
-
<TableHeader>Price</TableHeader>
|
|
130
|
-
<TableHeader>Total</TableHeader>
|
|
131
|
-
</TableRow>
|
|
132
|
-
</TableHead>
|
|
133
|
-
<TableBody>
|
|
134
|
-
{billableItem.map((service, index) => (
|
|
135
|
-
<TableRow key={service.uuid}>
|
|
136
|
-
<TableCell>{service?.name || 'Service Not Found'}</TableCell>
|
|
137
|
-
<TableCell>
|
|
138
|
-
<Controller
|
|
139
|
-
control={form.control}
|
|
140
|
-
name={`lineItems.${index}.quantity`}
|
|
141
|
-
defaultValue={quantityToDispense}
|
|
142
|
-
render={({ field }) => (
|
|
143
|
-
<input
|
|
144
|
-
{...field}
|
|
145
|
-
type="number"
|
|
146
|
-
className="form-control"
|
|
147
|
-
min={1}
|
|
148
|
-
max={quantityToDispense}
|
|
149
|
-
onChange={(e) => {
|
|
150
|
-
const value = parseInt(e.target.value, 10);
|
|
151
|
-
field.onChange(value);
|
|
152
|
-
}}
|
|
153
|
-
/>
|
|
154
|
-
)}
|
|
155
|
-
/>
|
|
156
|
-
</TableCell>
|
|
157
|
-
<TableCell>
|
|
158
|
-
<Controller
|
|
159
|
-
control={form.control}
|
|
160
|
-
name={`lineItems.${index}.priceUuid`}
|
|
161
|
-
render={({ field }) => (
|
|
162
|
-
<Dropdown
|
|
163
|
-
id={`priceUuid-${index}`}
|
|
164
|
-
invalid={!!form.formState.errors.lineItems?.[index]?.priceUuid}
|
|
165
|
-
invalidText={form.formState.errors.lineItems?.[index]?.priceUuid?.message}
|
|
166
|
-
onChange={(e) => {
|
|
167
|
-
const selectedPrice = service?.servicePrices.find((p) => p.uuid === e.selectedItem);
|
|
168
|
-
if (selectedPrice) {
|
|
169
|
-
field.onChange(e.selectedItem);
|
|
170
|
-
form.setValue(`lineItems.${index}.price`, selectedPrice.price);
|
|
171
|
-
form.setValue(`lineItems.${index}.priceName`, selectedPrice.name);
|
|
172
|
-
form.setValue(`lineItems.${index}.billableService`, service.uuid);
|
|
173
|
-
form.setValue(`lineItems.${index}.order`, orderUuid);
|
|
174
|
-
form.setValue(`lineItems.${index}.paymentStatus`, defaultPaymentStatus);
|
|
175
|
-
}
|
|
176
|
-
}}
|
|
177
|
-
selectedItem={field.value}
|
|
178
|
-
label="Choose method"
|
|
179
|
-
items={service?.servicePrices.map((r) => r.uuid) ?? []}
|
|
180
|
-
itemToString={(item) => service?.servicePrices.find((r) => r.uuid === item)?.name ?? ''}
|
|
181
|
-
direction="top"
|
|
182
|
-
/>
|
|
183
|
-
)}
|
|
184
|
-
/>
|
|
185
|
-
</TableCell>
|
|
186
|
-
<TableCell>{form.watch(`lineItems.${index}.price`) ?? ' '}</TableCell>
|
|
187
|
-
<TableCell>{calculateTotal(index)}</TableCell>
|
|
188
|
-
</TableRow>
|
|
189
|
-
))}
|
|
190
|
-
</TableBody>
|
|
191
|
-
</Table>
|
|
192
|
-
</Column>
|
|
193
|
-
</Stack>
|
|
194
|
-
</ModalBody>
|
|
195
|
-
<ModalFooter>
|
|
196
|
-
<Button className={styles.button} kind="secondary" onClick={closeModal}>
|
|
197
|
-
{t('discard', 'Discard')}
|
|
198
|
-
</Button>
|
|
199
|
-
<Button className={styles.button} kind="primary" type="submit" disabled={form.formState.isSubmitting}>
|
|
200
|
-
{t('saveAndClose', 'Save & Close')}
|
|
201
|
-
</Button>
|
|
202
|
-
</ModalFooter>
|
|
203
|
-
</form>
|
|
204
|
-
</div>
|
|
205
|
-
);
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
export default CreateBillItemModal;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
@use '@carbon/type';
|
|
2
|
-
@use '@carbon/layout';
|
|
3
|
-
@use '@carbon/colors';
|
|
4
|
-
|
|
5
|
-
.heading {
|
|
6
|
-
@include type.type-style('heading-compact-01');
|
|
7
|
-
margin: layout.$spacing-05 0 layout.$spacing-05;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.grid {
|
|
11
|
-
margin: layout.$spacing-05 layout.$spacing-05;
|
|
12
|
-
padding-top: layout.$spacing-05;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.billingItem {
|
|
16
|
-
margin-top: layout.$spacing-10;
|
|
17
|
-
overflow-x: auto;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.button {
|
|
21
|
-
height: layout.$spacing-10;
|
|
22
|
-
display: flex;
|
|
23
|
-
align-content: flex-start;
|
|
24
|
-
align-items: baseline;
|
|
25
|
-
min-width: 50%;
|
|
26
|
-
}
|