@kenyaemr/esm-billing-app 5.4.2-pre.2135 → 5.4.2-pre.2138
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 +113 -85
- package/dist/574.js +1 -1
- package/dist/919.js +1 -0
- package/dist/919.js.map +1 -0
- package/dist/{746.js → 933.js} +3 -3
- package/dist/{746.js.map → 933.js.map} +1 -1
- package/dist/kenyaemr-esm-billing-app.js +1 -1
- package/dist/kenyaemr-esm-billing-app.js.buildmanifest.json +86 -86
- 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/bill-deposit/components/dashboard/bill-deposit-dashboard.component.tsx +35 -0
- package/src/bill-deposit/components/forms/add-deposit.workspace.scss +26 -0
- package/src/bill-deposit/components/forms/add-deposit.workspace.tsx +212 -0
- package/src/{billing-form/bill-deposit/bill-deposit.scss → bill-deposit/components/forms/deposit-transactions/deposit-transaction.workspace.scss} +10 -17
- package/src/bill-deposit/components/forms/deposit-transactions/deposit-transaction.workspace.tsx +254 -0
- package/src/bill-deposit/components/modal/delete-deposit.modal.tsx +58 -0
- package/src/bill-deposit/components/modal/reverse-transaction.modal.tsx +59 -0
- package/src/bill-deposit/components/search/bill-deposit-search.component.tsx +106 -0
- package/src/bill-deposit/components/search/bill-deposit-search.scss +107 -0
- package/src/bill-deposit/components/search/components/deposit-table.tsx +150 -0
- package/src/bill-deposit/components/search/components/patient-info.tsx +38 -0
- package/src/bill-deposit/components/search/components/patient-search.tsx +24 -0
- package/src/bill-deposit/components/search/components/transaction-list/transaction-list.component.tsx +65 -0
- package/src/bill-deposit/components/search/components/transaction-list/transaction-list.scss +5 -0
- package/src/bill-deposit/constants/bill-deposit.constants.ts +25 -0
- package/src/bill-deposit/hooks/useBillDeposit.ts +43 -0
- package/src/bill-deposit/styles/bill-deposit-dashboard.scss +11 -0
- package/src/bill-deposit/types/bill-deposit.types.ts +61 -0
- package/src/bill-deposit/utils/bill-deposit.utils.ts +94 -0
- package/src/index.ts +23 -2
- package/src/past-patient-bills/patient-bills-dashboard/empty-patient-bill.component.tsx +29 -12
- package/src/past-patient-bills/patient-bills-dashboard/patient-bills-dashboard.scss +1 -0
- package/src/root.component.tsx +2 -0
- package/src/routes.json +22 -3
- package/src/types/index.ts +1 -0
- package/translations/en.json +3 -0
- package/dist/912.js +0 -1
- package/dist/912.js.map +0 -1
- package/src/billing-form/bill-deposit/bill-deposit.workspace.tsx +0 -236
- /package/dist/{746.js.LICENSE.txt → 933.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type Patient } from '@openmrs/esm-framework';
|
|
2
|
+
|
|
3
|
+
export interface BillDeposit {
|
|
4
|
+
uuid: string;
|
|
5
|
+
display: string;
|
|
6
|
+
patient: Patient;
|
|
7
|
+
amount: number;
|
|
8
|
+
depositType: string;
|
|
9
|
+
status: string;
|
|
10
|
+
referenceNumber: string;
|
|
11
|
+
description: string;
|
|
12
|
+
transactions: Array<BillDepositTransaction>;
|
|
13
|
+
dateCreated: string;
|
|
14
|
+
voided: boolean;
|
|
15
|
+
availableBalance: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface BillDepositTransaction {
|
|
19
|
+
uuid: string;
|
|
20
|
+
display: string;
|
|
21
|
+
amount: number;
|
|
22
|
+
transactionType: string;
|
|
23
|
+
dateCreated: string;
|
|
24
|
+
reason?: string;
|
|
25
|
+
voided: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface DepositFormData {
|
|
29
|
+
amount: number;
|
|
30
|
+
depositType: string;
|
|
31
|
+
referenceNumber: string;
|
|
32
|
+
description: string;
|
|
33
|
+
status: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface BillDepositWorkspaceProps {
|
|
37
|
+
patientUuid: string;
|
|
38
|
+
patient: Patient;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CreateDepositPayload {
|
|
42
|
+
patient: string;
|
|
43
|
+
amount: number;
|
|
44
|
+
depositType: string;
|
|
45
|
+
referenceNumber: string;
|
|
46
|
+
description: string;
|
|
47
|
+
status: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type FormattedDeposit = {
|
|
51
|
+
id: string;
|
|
52
|
+
depositType: string;
|
|
53
|
+
amount: number;
|
|
54
|
+
status: string;
|
|
55
|
+
dateCreated: string;
|
|
56
|
+
referenceNumber: string;
|
|
57
|
+
availableBalance: number;
|
|
58
|
+
patient: Patient;
|
|
59
|
+
description: string;
|
|
60
|
+
transactions: Array<BillDepositTransaction>;
|
|
61
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { type BillDeposit, type CreateDepositPayload } from '../types/bill-deposit.types';
|
|
3
|
+
import { MAX_REFERENCE_NUMBER_COUNTER } from '../constants/bill-deposit.constants';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a unique reference number for bill deposits
|
|
7
|
+
* Format: [Location Initials][YYMMDD][HHMMSS][Counter]
|
|
8
|
+
* Example: RDK240315143022001 for "Railways Dispensary (Kisumu)"
|
|
9
|
+
*/
|
|
10
|
+
let counter = 0;
|
|
11
|
+
|
|
12
|
+
export const generateReferenceNumber = (locationDisplay: string): string => {
|
|
13
|
+
// Extract location initials including parenthetical part
|
|
14
|
+
// e.g., "Railways Dispensary (Kisumu)" -> "RDK"
|
|
15
|
+
const locationInitials = locationDisplay
|
|
16
|
+
.replace(/[()]/g, '')
|
|
17
|
+
.split(' ')
|
|
18
|
+
.map((word) => word[0])
|
|
19
|
+
.join('')
|
|
20
|
+
.toUpperCase();
|
|
21
|
+
|
|
22
|
+
// Get current date and time in format YYMMDDHHMMSS
|
|
23
|
+
const now = new Date();
|
|
24
|
+
const dateTime = now.toISOString().slice(2, 19).replace(/[-:]/g, '');
|
|
25
|
+
|
|
26
|
+
// Generate unique code using counter
|
|
27
|
+
counter = (counter + 1) % MAX_REFERENCE_NUMBER_COUNTER;
|
|
28
|
+
const uniqueCode = counter.toString().padStart(3, '0');
|
|
29
|
+
|
|
30
|
+
return `${locationInitials}${dateTime}${uniqueCode}`;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Saves a new bill deposit
|
|
35
|
+
*/
|
|
36
|
+
export const saveDeposit = async (deposit: CreateDepositPayload | Partial<BillDeposit>, uuid?: string) => {
|
|
37
|
+
const url = `${restBaseUrl}/cashier/deposit` + (uuid ? `/${uuid}` : '');
|
|
38
|
+
return await openmrsFetch(url, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
body: deposit,
|
|
41
|
+
headers: {
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Deletes a bill deposit
|
|
49
|
+
*/
|
|
50
|
+
export const deleteDeposit = async (uuid: string) => {
|
|
51
|
+
const url = `${restBaseUrl}/cashier/deposit/${uuid}`;
|
|
52
|
+
return await openmrsFetch(url, {
|
|
53
|
+
method: 'DELETE',
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Formats a deposit amount with currency symbol
|
|
59
|
+
*/
|
|
60
|
+
export const formatDepositAmount = (amount: number): string => {
|
|
61
|
+
return new Intl.NumberFormat('en-US', {
|
|
62
|
+
style: 'currency',
|
|
63
|
+
currency: 'KES',
|
|
64
|
+
}).format(amount);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Validates a deposit amount
|
|
69
|
+
*/
|
|
70
|
+
export const validateDepositAmount = (amount: number): boolean => {
|
|
71
|
+
return amount > 0 && amount <= 100000000; // Assuming max deposit is 100M
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Add a bill deposit transaction
|
|
76
|
+
*/
|
|
77
|
+
export const addDepositTransaction = async (depositUuid: string, transaction: Record<string, string | number>) => {
|
|
78
|
+
const url = `${restBaseUrl}/cashier/deposit/${depositUuid}/transaction`;
|
|
79
|
+
return await openmrsFetch(url, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
body: JSON.stringify(transaction),
|
|
82
|
+
headers: {
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Reverses a bill deposit transaction
|
|
90
|
+
*/
|
|
91
|
+
export const reverseTransaction = async (depositUuid: string, transactionUuid: string) => {
|
|
92
|
+
const url = `${restBaseUrl}/cashier/deposit/${depositUuid}/transaction/${transactionUuid}`;
|
|
93
|
+
return await openmrsFetch(url, { method: 'DELETE' });
|
|
94
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -17,7 +17,8 @@ import rootComponent from './root.component';
|
|
|
17
17
|
import BillingForm from './billing-form/billing-form.component';
|
|
18
18
|
import BillingCheckInForm from './billing-form/billing-checkin-form.component';
|
|
19
19
|
import BillHistory from './bill-history/bill-history.component';
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
// Bill Deposit Components
|
|
21
22
|
|
|
22
23
|
// Benefits Package Components
|
|
23
24
|
import BenefitsPackage from './benefits-package/benefits-package.component';
|
|
@@ -66,6 +67,13 @@ import { CreatePaymentPoint } from './payment-points/create-payment-point.compon
|
|
|
66
67
|
import { ClockIn } from './payment-points/payment-point/clock-in.modal';
|
|
67
68
|
import { ClockOut } from './payment-points/payment-point/clock-out.modal';
|
|
68
69
|
|
|
70
|
+
// Bill Deposit Components
|
|
71
|
+
import BillDepositSearch from './bill-deposit/components/search/bill-deposit-search.component';
|
|
72
|
+
import AddDepositWorkspace from './bill-deposit/components/forms/add-deposit.workspace';
|
|
73
|
+
import DeleteDepositModal from './bill-deposit/components/modal/delete-deposit.modal';
|
|
74
|
+
import ReverseTransactionModal from './bill-deposit/components/modal/reverse-transaction.modal';
|
|
75
|
+
import DepositTransactionWorkspace from './bill-deposit/components/forms/deposit-transactions/deposit-transaction.workspace';
|
|
76
|
+
|
|
69
77
|
// Translation
|
|
70
78
|
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
71
79
|
|
|
@@ -167,6 +175,14 @@ export const preAuthRequestsDashboardLink = getSyncLifecycle(
|
|
|
167
175
|
options,
|
|
168
176
|
);
|
|
169
177
|
|
|
178
|
+
// Bill Deposit Links
|
|
179
|
+
export const billDepositDashboardLink = getSyncLifecycle(
|
|
180
|
+
createLeftPanelLink({
|
|
181
|
+
name: 'bill-deposit',
|
|
182
|
+
title: 'Bill Deposit',
|
|
183
|
+
}),
|
|
184
|
+
options,
|
|
185
|
+
);
|
|
170
186
|
export const benefitsPackageDashboardLink = getSyncLifecycle(
|
|
171
187
|
createDashboardLink({
|
|
172
188
|
...benefitsPackageDashboardMeta,
|
|
@@ -181,7 +197,6 @@ export const root = getSyncLifecycle(rootComponent, options);
|
|
|
181
197
|
export const billingPatientSummary = getSyncLifecycle(BillHistory, options);
|
|
182
198
|
export const billingCheckInForm = getSyncLifecycle(BillingCheckInForm, options);
|
|
183
199
|
export const billingForm = getSyncLifecycle(BillingForm, options);
|
|
184
|
-
export const billDepositWorkspace = getSyncLifecycle(BillDepositWorkspace, options);
|
|
185
200
|
|
|
186
201
|
// Bill Manager Components
|
|
187
202
|
export const deleteBillableServiceModal = getSyncLifecycle(DeleteBillableServiceModal, options);
|
|
@@ -232,6 +247,12 @@ export const bulkImportBillableServicesModal = getSyncLifecycle(BulkImportBillab
|
|
|
232
247
|
export const claimsOverview = getSyncLifecycle(ClaimsManagementOverview, options);
|
|
233
248
|
export const manageClaimRequestModal = getSyncLifecycle(ManageClaimRequest, options);
|
|
234
249
|
|
|
250
|
+
// Bill Deposit Components
|
|
251
|
+
export const billDepositSearch = getSyncLifecycle(BillDepositSearch, options);
|
|
252
|
+
export const addDepositWorkspace = getSyncLifecycle(AddDepositWorkspace, options);
|
|
253
|
+
export const deleteDepositModal = getSyncLifecycle(DeleteDepositModal, options);
|
|
254
|
+
export const depositTransactionWorkspace = getSyncLifecycle(DepositTransactionWorkspace, options);
|
|
255
|
+
export const reverseTransactionModal = getSyncLifecycle(ReverseTransactionModal, options);
|
|
235
256
|
// App Startup
|
|
236
257
|
export function startupApp() {
|
|
237
258
|
defineConfigSchema(moduleName, configSchema);
|
|
@@ -2,23 +2,40 @@ import React from 'react';
|
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import styles from './patient-bills-dashboard.scss';
|
|
4
4
|
import { EmptySvg } from './empty-svg.component';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { Button } from '@carbon/react';
|
|
6
|
+
import { Add } from '@carbon/react/icons';
|
|
7
|
+
type BaseEmptyPatientBillProps = {
|
|
7
8
|
title?: string;
|
|
8
9
|
subTitle?: string;
|
|
9
10
|
};
|
|
10
|
-
|
|
11
|
+
|
|
12
|
+
type WithLaunchForm = BaseEmptyPatientBillProps & {
|
|
13
|
+
launchForm: () => void;
|
|
14
|
+
buttonText: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type WithoutLaunchForm = BaseEmptyPatientBillProps & {
|
|
18
|
+
launchForm?: never;
|
|
19
|
+
buttonText?: never;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type EmptyPatientBillProps = WithLaunchForm | WithoutLaunchForm;
|
|
23
|
+
|
|
24
|
+
const EmptyPatientBill: React.FC<EmptyPatientBillProps> = ({ title, subTitle, launchForm, buttonText }) => {
|
|
11
25
|
const { t } = useTranslation();
|
|
12
26
|
return (
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
<div className={styles.emptyStateContainer}>
|
|
28
|
+
<EmptySvg />
|
|
29
|
+
<p className={styles.title}>{title ?? t('searchForAPatient', 'Search for a patient')}</p>
|
|
30
|
+
<p className={styles.subTitle}>
|
|
31
|
+
{subTitle ?? t('enterAnIdNumberOrPatientName', 'Enter an ID number or patient name')}
|
|
32
|
+
</p>
|
|
33
|
+
{launchForm && buttonText && (
|
|
34
|
+
<Button onClick={launchForm} kind="ghost" renderIcon={Add}>
|
|
35
|
+
{buttonText}
|
|
36
|
+
</Button>
|
|
37
|
+
)}
|
|
38
|
+
</div>
|
|
22
39
|
);
|
|
23
40
|
};
|
|
24
41
|
|
package/src/root.component.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import PaymentModeHome from './payment-modes/payment-mode-home.component';
|
|
|
13
13
|
import { ClockInBoundary } from './payment-points/clock-in-boundary.component';
|
|
14
14
|
import { PaymentPoint } from './payment-points/payment-point/payment-point.component';
|
|
15
15
|
import { PaymentPoints } from './payment-points/payment-points.component';
|
|
16
|
+
import BillDepositDashboard from './bill-deposit/components/dashboard/bill-deposit-dashboard.component';
|
|
16
17
|
|
|
17
18
|
const RootComponent: React.FC = () => {
|
|
18
19
|
const baseName = window.getOpenmrsSpaBase() + 'home/billing';
|
|
@@ -46,6 +47,7 @@ const RootComponent: React.FC = () => {
|
|
|
46
47
|
<Route path="/charge-items" element={<ChargeItemsDashboard />} />
|
|
47
48
|
<Route path="/payment-modes" element={<PaymentModeHome />} />
|
|
48
49
|
<Route path="/billable-exemptions" element={<BillableExemptions />} />
|
|
50
|
+
<Route path="/bill-deposit" element={<BillDepositDashboard />} />
|
|
49
51
|
</Routes>
|
|
50
52
|
</BrowserRouter>
|
|
51
53
|
);
|
package/src/routes.json
CHANGED
|
@@ -150,6 +150,11 @@
|
|
|
150
150
|
"order": 0,
|
|
151
151
|
"slot": "billing-dashboard-link-slot"
|
|
152
152
|
},
|
|
153
|
+
{
|
|
154
|
+
"component": "billDepositDashboardLink",
|
|
155
|
+
"name": "bill-deposit-dashboard-link",
|
|
156
|
+
"slots": ["billing-dashboard-link-slot","billing-dashboard-group-nav-slot"]
|
|
157
|
+
},
|
|
153
158
|
{
|
|
154
159
|
"component": "paymentHistoryLink",
|
|
155
160
|
"name": "payment-history-link",
|
|
@@ -284,9 +289,15 @@
|
|
|
284
289
|
"type": "other-form"
|
|
285
290
|
},
|
|
286
291
|
{
|
|
287
|
-
"name": "
|
|
288
|
-
"component": "
|
|
289
|
-
"title": "
|
|
292
|
+
"name": "add-deposit-workspace",
|
|
293
|
+
"component": "addDepositWorkspace",
|
|
294
|
+
"title": "Add Deposit",
|
|
295
|
+
"type": "other-form"
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"name":"deposit-transaction-workspace",
|
|
299
|
+
"component": "depositTransactionWorkspace",
|
|
300
|
+
"title": "Deposit Transaction",
|
|
290
301
|
"type": "other-form"
|
|
291
302
|
}
|
|
292
303
|
],
|
|
@@ -322,6 +333,14 @@
|
|
|
322
333
|
{
|
|
323
334
|
"name": "create-bill-item-modal",
|
|
324
335
|
"component": "createBillItemModal"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"name": "delete-deposit-modal",
|
|
339
|
+
"component": "deleteDepositModal"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"name": "reverse-transaction-modal",
|
|
343
|
+
"component": "reverseTransactionModal"
|
|
325
344
|
}
|
|
326
345
|
]
|
|
327
346
|
}
|
package/src/types/index.ts
CHANGED
package/translations/en.json
CHANGED
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"create": "Create",
|
|
78
78
|
"createClaimError": "Create Claim error",
|
|
79
79
|
"created": "Created",
|
|
80
|
+
"createNewDeposit": "Create a new deposit for this patient",
|
|
80
81
|
"creating": "Creating",
|
|
81
82
|
"date": "Date of Claim",
|
|
82
83
|
"dateCreated": "Date Created",
|
|
@@ -163,6 +164,7 @@
|
|
|
163
164
|
"mpesaPayment": "MPESA Payment",
|
|
164
165
|
"name": "Name",
|
|
165
166
|
"navigateBack": "Navigate back",
|
|
167
|
+
"newDeposit": "New Deposit",
|
|
166
168
|
"nextPage": "Next page",
|
|
167
169
|
"no": "No",
|
|
168
170
|
"noBenefitFound": "No benefit found",
|
|
@@ -171,6 +173,7 @@
|
|
|
171
173
|
"noBillsFoundDescription": "No bills found for this patient",
|
|
172
174
|
"noCashPoints": "No Cash Points",
|
|
173
175
|
"noCashPointsConfigured": "There are no cash points configured for this location",
|
|
176
|
+
"noDepositsFound": "No deposits found",
|
|
174
177
|
"noItemsSelected": "No items selected",
|
|
175
178
|
"noMatchingBillsToDisplay": "No matching bills to display",
|
|
176
179
|
"noMatchingItemsToDisplay": "No matching items to display",
|