@kenyaemr/esm-billing-app 5.3.8-pre.1599 → 5.3.9-pre.1620
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 +57 -57
- package/dist/571.js +1 -1
- package/dist/571.js.map +1 -1
- package/dist/kenyaemr-esm-billing-app.js.buildmanifest.json +6 -6
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/billable-services/payment-history/payment-history-table.component.tsx +10 -9
- package/src/config-schema.ts +13 -0
- package/src/helpers/functions.ts +7 -12
- package/src/invoice/invoice-table.component.tsx +7 -3
- package/src/invoice/payments/payments.test.tsx +54 -11
- package/src/invoice/payments/utils.ts +36 -8
- package/src/prompt-payment/prompt-payment-modal.component.tsx +1 -1
- package/src/prompt-payment/prompt-payment.modal.test.tsx +200 -0
- package/src/prompt-payment/prompt-payment.resource.tsx +79 -4
- package/src/types/index.ts +1 -0
|
@@ -4,6 +4,7 @@ import useSWR from 'swr';
|
|
|
4
4
|
import { mapBillProperties } from '../billing.resource';
|
|
5
5
|
import { BillingConfig } from '../config-schema';
|
|
6
6
|
import { BillingPromptType, MappedBill, PatientInvoice } from '../types';
|
|
7
|
+
import dayjs from 'dayjs';
|
|
7
8
|
|
|
8
9
|
interface BillingPromptResult {
|
|
9
10
|
shouldShowBillingPrompt: boolean;
|
|
@@ -11,6 +12,12 @@ interface BillingPromptResult {
|
|
|
11
12
|
error: Error | null;
|
|
12
13
|
currentVisit: Visit | null;
|
|
13
14
|
bills: Array<MappedBill>;
|
|
15
|
+
billingDuration?: {
|
|
16
|
+
isWithinPromptDuration: boolean;
|
|
17
|
+
hoursSinceLastBill: number;
|
|
18
|
+
lastDateBilled: Date;
|
|
19
|
+
mostRecentBill: MappedBill;
|
|
20
|
+
};
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
// Constants
|
|
@@ -80,7 +87,7 @@ const hasOnlyOrderBills = (bills: Array<MappedBill>): boolean => {
|
|
|
80
87
|
* 1. The current visit is not an inpatient visit
|
|
81
88
|
* 2. The patient has a positive bill balance
|
|
82
89
|
* 3. The payment method is not in the excluded payment methods list
|
|
83
|
-
* 4. For patient-chart, prompt is not shown if the line items in the bill are only orders
|
|
90
|
+
* 4. For patient-chart, prompt is not shown if the line items in the bill are only orders and the billing duration is within the prompt duration
|
|
84
91
|
*
|
|
85
92
|
* @param patientUuid - The UUID of the patient to check billing status for
|
|
86
93
|
* @returns {BillingPromptResult} An object containing:
|
|
@@ -89,6 +96,7 @@ const hasOnlyOrderBills = (bills: Array<MappedBill>): boolean => {
|
|
|
89
96
|
* - error: any error that occurred during data fetching
|
|
90
97
|
* - currentVisit: the current visit object or null
|
|
91
98
|
* - bills: array of the patient's bills
|
|
99
|
+
* - billingDuration: an object containing billing duration information
|
|
92
100
|
*/
|
|
93
101
|
export const useBillingPrompt = (
|
|
94
102
|
patientUuid: string,
|
|
@@ -100,28 +108,42 @@ export const useBillingPrompt = (
|
|
|
100
108
|
|
|
101
109
|
const { paymentMethodsUuidsThatShouldNotShowPrompt, inPatientVisitTypeUuid } = config;
|
|
102
110
|
|
|
111
|
+
const hasLoaded = isLoadingBills && isLoadingVisit;
|
|
103
112
|
const isExcludedPaymentMethod = checkPaymentMethodExclusion(currentVisit, paymentMethodsUuidsThatShouldNotShowPrompt);
|
|
104
|
-
|
|
105
113
|
const patientBillBalance = calculateBillBalance(bills);
|
|
106
114
|
const hasOnlyOrders = hasOnlyOrderBills(bills);
|
|
115
|
+
const billingDuration = checkBillingDuration(bills, config);
|
|
107
116
|
|
|
108
117
|
if (promptType === 'patient-chart' && hasOnlyOrders) {
|
|
109
118
|
return {
|
|
110
119
|
shouldShowBillingPrompt: false,
|
|
111
|
-
isLoading:
|
|
120
|
+
isLoading: hasLoaded,
|
|
121
|
+
error,
|
|
122
|
+
currentVisit,
|
|
123
|
+
bills,
|
|
124
|
+
billingDuration,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (promptType === 'patient-chart' && config.promptDuration.enable && !billingDuration.isWithinPromptDuration) {
|
|
129
|
+
return {
|
|
130
|
+
shouldShowBillingPrompt: false,
|
|
131
|
+
isLoading: hasLoaded,
|
|
112
132
|
error,
|
|
113
133
|
currentVisit,
|
|
114
134
|
bills,
|
|
135
|
+
billingDuration,
|
|
115
136
|
};
|
|
116
137
|
}
|
|
117
138
|
|
|
118
139
|
return {
|
|
119
140
|
shouldShowBillingPrompt:
|
|
120
141
|
!isExcludedPaymentMethod && shouldShowPrompt(currentVisit, patientBillBalance, inPatientVisitTypeUuid),
|
|
121
|
-
isLoading:
|
|
142
|
+
isLoading: hasLoaded,
|
|
122
143
|
error,
|
|
123
144
|
currentVisit,
|
|
124
145
|
bills,
|
|
146
|
+
billingDuration,
|
|
125
147
|
};
|
|
126
148
|
};
|
|
127
149
|
|
|
@@ -160,3 +182,56 @@ export const usePatientBills = (patientUuid: string) => {
|
|
|
160
182
|
mutate,
|
|
161
183
|
};
|
|
162
184
|
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Checks if bills are within the configured prompt duration and provides billing timing information
|
|
188
|
+
*
|
|
189
|
+
* @param {Array<MappedBill>} bills - Array of patient bills containing dateCreated timestamps
|
|
190
|
+
* @param {Object} config - Configuration object containing prompt duration settings
|
|
191
|
+
* @param {number} config.promptDuration - Maximum number of hours to show prompt after bill creation
|
|
192
|
+
*
|
|
193
|
+
* @returns {Object} Billing duration information
|
|
194
|
+
* @returns {boolean} returns.isWithinPromptDuration - Whether the most recent bill is within prompt duration
|
|
195
|
+
* @returns {number} returns.hoursSinceLastBill - Hours elapsed since most recent bill
|
|
196
|
+
* @returns {string} returns.lastDateBilled - ISO timestamp of most recent bill
|
|
197
|
+
* @returns {MappedBill} returns.mostRecentBill - The most recent bill object
|
|
198
|
+
*
|
|
199
|
+
* @throws {Error} When bills array is empty or promptDuration is not configured
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const bills = [{ dateCreated: '2023-01-01T10:00:00Z' }];
|
|
203
|
+
* const config = { promptDuration: 24 };
|
|
204
|
+
* const result = checkBillingDuration(bills, config);
|
|
205
|
+
* // Returns: {
|
|
206
|
+
* // isWithinPromptDuration: true,
|
|
207
|
+
* // hoursSinceLastBill: 5,
|
|
208
|
+
* // lastDateBilled: '2023-01-01T10:00:00Z',
|
|
209
|
+
* // mostRecentBill: { dateCreated: '2023-01-01T10:00:00Z' }
|
|
210
|
+
* // }
|
|
211
|
+
*/
|
|
212
|
+
const checkBillingDuration = (bills: Array<MappedBill> = [], config: BillingConfig) => {
|
|
213
|
+
if (!config?.promptDuration?.enable) {
|
|
214
|
+
return {
|
|
215
|
+
isWithinPromptDuration: false,
|
|
216
|
+
hoursSinceLastBill: 0,
|
|
217
|
+
lastDateBilled: new Date(),
|
|
218
|
+
mostRecentBill: null,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const sortedBills = [...bills].sort((a, b) => dayjs(b.dateCreated).diff(dayjs(a.dateCreated)));
|
|
223
|
+
|
|
224
|
+
const mostRecentBill = sortedBills[0];
|
|
225
|
+
const lastDateBilled = new Date(mostRecentBill?.dateCreatedUnformatted);
|
|
226
|
+
const currentDate = new Date();
|
|
227
|
+
|
|
228
|
+
// Calculate hours since last bill
|
|
229
|
+
const hoursSinceLastBill = dayjs(currentDate).diff(dayjs(lastDateBilled), 'hour');
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
isWithinPromptDuration: hoursSinceLastBill <= config.promptDuration.duration,
|
|
233
|
+
hoursSinceLastBill,
|
|
234
|
+
lastDateBilled,
|
|
235
|
+
mostRecentBill,
|
|
236
|
+
};
|
|
237
|
+
};
|