@openmrs/esm-billing-app 1.0.2-pre.758 → 1.0.2-pre.759
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/4300.js +1 -1
- package/dist/942.js +1 -1
- package/dist/942.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-billing-app.js.buildmanifest.json +10 -10
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/invoice/payments/payment-form/payment-form.component.tsx +27 -20
- package/src/invoice/payments/payment-form/payment-form.scss +5 -6
- package/src/invoice/payments/payment-form/payment-form.test.tsx +204 -24
- package/src/invoice/payments/payments.component.tsx +46 -46
- package/src/invoice/payments/payments.test.tsx +155 -8
- package/src/invoice/payments/utils.ts +1 -1
- package/translations/en.json +13 -1
|
@@ -6,15 +6,15 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
6
6
|
import { navigate, showSnackbar, useConfig, useVisit } from '@openmrs/esm-framework';
|
|
7
7
|
import { Button } from '@carbon/react';
|
|
8
8
|
import { CardHeader } from '@openmrs/esm-patient-common-lib';
|
|
9
|
-
import { InvoiceBreakDown } from './invoice-breakdown/invoice-breakdown.component';
|
|
10
|
-
import PaymentHistory from './payment-history/payment-history.component';
|
|
11
|
-
import PaymentForm from './payment-form/payment-form.component';
|
|
12
9
|
import { convertToCurrency } from '../../helpers';
|
|
13
10
|
import { createPaymentPayload } from './utils';
|
|
11
|
+
import { InvoiceBreakDown } from './invoice-breakdown/invoice-breakdown.component';
|
|
14
12
|
import { processBillPayment } from '../../billing.resource';
|
|
15
|
-
import { useBillableServices } from '../../billable-services/billable-service.resource';
|
|
16
|
-
import { updateBillVisitAttribute } from './payment.resource';
|
|
17
13
|
import { type MappedBill } from '../../types';
|
|
14
|
+
import { updateBillVisitAttribute } from './payment.resource';
|
|
15
|
+
import { useBillableServices } from '../../billable-services/billable-service.resource';
|
|
16
|
+
import PaymentForm from './payment-form/payment-form.component';
|
|
17
|
+
import PaymentHistory from './payment-history/payment-history.component';
|
|
18
18
|
import styles from './payments.scss';
|
|
19
19
|
|
|
20
20
|
type PaymentProps = {
|
|
@@ -22,7 +22,7 @@ type PaymentProps = {
|
|
|
22
22
|
mutate: () => void;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export type Payment = { method: string; amount:
|
|
25
|
+
export type Payment = { method: string; amount: number | undefined; referenceCode?: number | string };
|
|
26
26
|
|
|
27
27
|
export type PaymentFormValue = {
|
|
28
28
|
payment: Array<Payment>;
|
|
@@ -30,12 +30,18 @@ export type PaymentFormValue = {
|
|
|
30
30
|
|
|
31
31
|
const Payments: React.FC<PaymentProps> = ({ bill, mutate }) => {
|
|
32
32
|
const { t } = useTranslation();
|
|
33
|
-
const { billableServices
|
|
33
|
+
const { billableServices } = useBillableServices();
|
|
34
34
|
const paymentSchema = z.object({
|
|
35
35
|
method: z.string().refine((value) => !!value, 'Payment method is required'),
|
|
36
36
|
amount: z
|
|
37
|
-
.number(
|
|
38
|
-
|
|
37
|
+
.number({
|
|
38
|
+
required_error: t('amountRequired', 'Amount is required'),
|
|
39
|
+
invalid_type_error: t('amountRequired', 'Amount is required'),
|
|
40
|
+
})
|
|
41
|
+
.positive({ message: t('amountMustBePositive', 'Amount must be greater than 0') })
|
|
42
|
+
.max(bill?.totalAmount - bill?.tenderedAmount, {
|
|
43
|
+
message: t('paymentAmountCannotExceedAmountDue', 'Payment amount cannot exceed amount due'),
|
|
44
|
+
}),
|
|
39
45
|
referenceCode: z.union([z.number(), z.string()]).optional(),
|
|
40
46
|
});
|
|
41
47
|
|
|
@@ -58,47 +64,41 @@ const Payments: React.FC<PaymentProps> = ({ bill, mutate }) => {
|
|
|
58
64
|
to: window.getOpenmrsSpaBase() + 'home/billing',
|
|
59
65
|
});
|
|
60
66
|
|
|
67
|
+
if (!bill) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
61
71
|
const amountDue = bill.totalAmount - bill.tenderedAmount;
|
|
62
72
|
|
|
63
|
-
const handleProcessPayment = () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
formValues,
|
|
71
|
-
amountRemaining,
|
|
72
|
-
billableServices,
|
|
73
|
-
);
|
|
74
|
-
paymentPayload.payments.forEach((payment) => {
|
|
75
|
-
payment.dateCreated = new Date(payment.dateCreated);
|
|
76
|
-
});
|
|
73
|
+
const handleProcessPayment = async () => {
|
|
74
|
+
const amountBeingTendered = formValues?.reduce((acc, curr) => acc + (curr.amount || 0), 0);
|
|
75
|
+
const amountRemaining = amountDue - amountBeingTendered;
|
|
76
|
+
const paymentPayload = createPaymentPayload(bill, bill?.patientUuid, formValues, amountRemaining, billableServices);
|
|
77
|
+
paymentPayload.payments.forEach((payment) => {
|
|
78
|
+
payment.dateCreated = new Date(payment.dateCreated);
|
|
79
|
+
});
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
81
|
+
try {
|
|
82
|
+
await processBillPayment(paymentPayload, bill.uuid);
|
|
83
|
+
showSnackbar({
|
|
84
|
+
title: t('billPayment', 'Bill payment'),
|
|
85
|
+
subtitle: t('paymentProcessedSuccessfully', 'Payment processed successfully'),
|
|
86
|
+
kind: 'success',
|
|
87
|
+
});
|
|
88
|
+
if (currentVisit) {
|
|
89
|
+
updateBillVisitAttribute(currentVisit);
|
|
90
|
+
}
|
|
91
|
+
methods.reset({ payment: [{ method: '', amount: undefined, referenceCode: '' }] });
|
|
92
|
+
mutate();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
showSnackbar({
|
|
95
|
+
title: t('errorProcessingPayment', 'Error processing payment'),
|
|
96
|
+
kind: 'error',
|
|
97
|
+
subtitle: error?.message,
|
|
98
|
+
});
|
|
95
99
|
}
|
|
96
100
|
};
|
|
97
101
|
|
|
98
|
-
if (!bill) {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
102
|
return (
|
|
103
103
|
<FormProvider {...methods}>
|
|
104
104
|
<div className={styles.wrapper}>
|
|
@@ -107,7 +107,7 @@ const Payments: React.FC<PaymentProps> = ({ bill, mutate }) => {
|
|
|
107
107
|
<span></span>
|
|
108
108
|
</CardHeader>
|
|
109
109
|
<div>
|
|
110
|
-
|
|
110
|
+
<PaymentHistory bill={bill} />
|
|
111
111
|
<PaymentForm disablePayment={amountDue <= 0} isSingleLineItem={bill.lineItems.length === 1} />
|
|
112
112
|
</div>
|
|
113
113
|
</div>
|
|
@@ -131,7 +131,7 @@ const Payments: React.FC<PaymentProps> = ({ bill, mutate }) => {
|
|
|
131
131
|
<Button onClick={handleNavigateToBillingDashboard} kind="secondary">
|
|
132
132
|
{t('discard', 'Discard')}
|
|
133
133
|
</Button>
|
|
134
|
-
<Button onClick={
|
|
134
|
+
<Button onClick={handleProcessPayment} disabled={!formValues?.length || !methods.formState.isValid}>
|
|
135
135
|
{t('processPayment', 'Process Payment')}
|
|
136
136
|
</Button>
|
|
137
137
|
</div>
|
|
@@ -9,25 +9,42 @@ import {
|
|
|
9
9
|
type VisitReturnType,
|
|
10
10
|
} from '@openmrs/esm-framework';
|
|
11
11
|
import { useBillableServices } from '../../billable-services/billable-service.resource';
|
|
12
|
-
import { type MappedBill
|
|
12
|
+
import { type MappedBill } from '../../types';
|
|
13
13
|
import { configSchema, type BillingConfig } from '../../config-schema';
|
|
14
|
+
import { usePaymentModes } from './payment.resource';
|
|
14
15
|
import Payments from './payments.component';
|
|
15
16
|
|
|
16
17
|
const mockUseVisit = jest.mocked(useVisit);
|
|
17
18
|
const mockUseConfig = jest.mocked(useConfig<BillingConfig>);
|
|
18
19
|
const mockUseBillableServices = jest.mocked(useBillableServices);
|
|
20
|
+
const mockUsePaymentModes = jest.mocked(usePaymentModes);
|
|
19
21
|
const mockFormatToParts = jest.fn().mockReturnValue([{ type: 'integer', value: '1000' }]);
|
|
20
22
|
const mockFormat = jest.fn().mockReturnValue('$1000.00');
|
|
23
|
+
const mockResolvedOptions = jest.fn().mockReturnValue({
|
|
24
|
+
locale: 'en-US',
|
|
25
|
+
numberingSystem: 'latn',
|
|
26
|
+
style: 'currency',
|
|
27
|
+
currency: 'USD',
|
|
28
|
+
minimumFractionDigits: 2,
|
|
29
|
+
maximumFractionDigits: 2,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
global.Intl.NumberFormat.supportedLocalesOf = jest.fn().mockReturnValue(['en-US']);
|
|
21
33
|
global.Intl.NumberFormat = jest.fn().mockImplementation(() => ({
|
|
22
34
|
formatToParts: mockFormatToParts,
|
|
23
35
|
format: mockFormat,
|
|
36
|
+
resolvedOptions: mockResolvedOptions,
|
|
24
37
|
})) as any;
|
|
25
|
-
global.Intl.NumberFormat.supportedLocalesOf = jest.fn().mockReturnValue(['en-US']);
|
|
26
38
|
|
|
27
39
|
jest.mock('../../billing.resource', () => ({
|
|
28
40
|
processBillPayment: jest.fn(),
|
|
29
41
|
}));
|
|
30
42
|
|
|
43
|
+
jest.mock('./payment.resource', () => ({
|
|
44
|
+
updateBillVisitAttribute: jest.fn(),
|
|
45
|
+
usePaymentModes: jest.fn(),
|
|
46
|
+
}));
|
|
47
|
+
|
|
31
48
|
jest.mock('../../billable-services/billable-service.resource', () => ({
|
|
32
49
|
useBillableServices: jest.fn(),
|
|
33
50
|
}));
|
|
@@ -93,7 +110,6 @@ describe('Payments', () => {
|
|
|
93
110
|
};
|
|
94
111
|
|
|
95
112
|
const mockMutate = jest.fn();
|
|
96
|
-
const mockSelectedLineItems: LineItem[] = [];
|
|
97
113
|
|
|
98
114
|
beforeEach(() => {
|
|
99
115
|
mockUseVisit.mockReturnValue({ currentVisit: null } as unknown as VisitReturnType);
|
|
@@ -105,6 +121,15 @@ describe('Payments', () => {
|
|
|
105
121
|
error: null,
|
|
106
122
|
mutate: jest.fn(),
|
|
107
123
|
});
|
|
124
|
+
mockUsePaymentModes.mockReturnValue({
|
|
125
|
+
paymentModes: [
|
|
126
|
+
{ uuid: '1', name: 'Cash', description: 'Cash payment', retired: false },
|
|
127
|
+
{ uuid: '2', name: 'Credit Card', description: 'Credit Card payment', retired: false },
|
|
128
|
+
],
|
|
129
|
+
isLoading: false,
|
|
130
|
+
error: null,
|
|
131
|
+
mutate: jest.fn(),
|
|
132
|
+
});
|
|
108
133
|
});
|
|
109
134
|
|
|
110
135
|
it('renders payment form and history', () => {
|
|
@@ -114,12 +139,11 @@ describe('Payments', () => {
|
|
|
114
139
|
expect(screen.getByText('Total Tendered:')).toBeInTheDocument();
|
|
115
140
|
});
|
|
116
141
|
|
|
117
|
-
it('
|
|
142
|
+
it('displays formatted currency amounts', () => {
|
|
118
143
|
render(<Payments bill={mockBill} mutate={mockMutate} />);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
expect(
|
|
122
|
-
expect(amountElements[amountElements.length - 1]).toBeInTheDocument();
|
|
144
|
+
// Verify that currency formatting is applied (mocked to return '$1000.00')
|
|
145
|
+
const formattedAmounts = screen.getAllByText('$1000.00');
|
|
146
|
+
expect(formattedAmounts.length).toBeGreaterThan(0);
|
|
123
147
|
});
|
|
124
148
|
|
|
125
149
|
it('disables Process Payment button when form is invalid', () => {
|
|
@@ -132,4 +156,127 @@ describe('Payments', () => {
|
|
|
132
156
|
await userEvent.click(screen.getByText('Discard'));
|
|
133
157
|
expect(navigate).toHaveBeenCalled();
|
|
134
158
|
});
|
|
159
|
+
|
|
160
|
+
it('should validate amount is required', () => {
|
|
161
|
+
const billWithAmountDue: MappedBill = {
|
|
162
|
+
...mockBill,
|
|
163
|
+
totalAmount: 100,
|
|
164
|
+
tenderedAmount: 0,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
render(<Payments bill={billWithAmountDue} mutate={mockMutate} />);
|
|
168
|
+
|
|
169
|
+
// Process Payment button should be disabled when no amount is entered
|
|
170
|
+
expect(screen.getByText('Process Payment')).toBeDisabled();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should handle undefined amount values correctly', () => {
|
|
174
|
+
const billWithAmountDue: MappedBill = {
|
|
175
|
+
...mockBill,
|
|
176
|
+
totalAmount: 100,
|
|
177
|
+
tenderedAmount: 0,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
render(<Payments bill={billWithAmountDue} mutate={mockMutate} />);
|
|
181
|
+
|
|
182
|
+
expect(screen.getByText('Process Payment')).toBeDisabled();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should display amount due when there is a balance', () => {
|
|
186
|
+
const billWithBalance: MappedBill = {
|
|
187
|
+
...mockBill,
|
|
188
|
+
totalAmount: 500,
|
|
189
|
+
tenderedAmount: 200,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
render(<Payments bill={billWithBalance} mutate={mockMutate} />);
|
|
193
|
+
|
|
194
|
+
expect(screen.getByText('Amount Due:')).toBeInTheDocument();
|
|
195
|
+
// The amount due section should be visible for bills with remaining balance
|
|
196
|
+
const formattedAmounts = screen.getAllByText('$1000.00');
|
|
197
|
+
expect(formattedAmounts.length).toBeGreaterThan(0);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should display amount due as absolute value when overpaid', () => {
|
|
201
|
+
const billWithOverpayment: MappedBill = {
|
|
202
|
+
...mockBill,
|
|
203
|
+
totalAmount: 100,
|
|
204
|
+
tenderedAmount: 150,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
render(<Payments bill={billWithOverpayment} mutate={mockMutate} />);
|
|
208
|
+
|
|
209
|
+
// Even with negative amount due (overpayment), the display should show positive value
|
|
210
|
+
expect(screen.getByText('Amount Due:')).toBeInTheDocument();
|
|
211
|
+
const formattedAmounts = screen.getAllByText('$1000.00');
|
|
212
|
+
expect(formattedAmounts.length).toBeGreaterThan(0);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should disable adding payment methods when amount due is zero or less', () => {
|
|
216
|
+
const fullyPaidBill: MappedBill = {
|
|
217
|
+
...mockBill,
|
|
218
|
+
totalAmount: 100,
|
|
219
|
+
tenderedAmount: 100,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
render(<Payments bill={fullyPaidBill} mutate={mockMutate} />);
|
|
223
|
+
|
|
224
|
+
expect(screen.getByText(/add payment method/i)).toBeDisabled();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should return null when bill is not provided', () => {
|
|
228
|
+
const { container } = render(<Payments bill={null} mutate={mockMutate} />);
|
|
229
|
+
expect(container.firstChild).toBeNull();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should render add payment method button for bills with amount due', () => {
|
|
233
|
+
const billWithAmountDue: MappedBill = {
|
|
234
|
+
...mockBill,
|
|
235
|
+
totalAmount: 100,
|
|
236
|
+
tenderedAmount: 0,
|
|
237
|
+
lineItems: [],
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
render(<Payments bill={billWithAmountDue} mutate={mockMutate} />);
|
|
241
|
+
|
|
242
|
+
// Verify add payment method button is available
|
|
243
|
+
expect(screen.getByText(/add payment method/i)).toBeInTheDocument();
|
|
244
|
+
expect(screen.getByText(/add payment method/i)).not.toBeDisabled();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('should display process payment button', () => {
|
|
248
|
+
const billWithAmountDue: MappedBill = {
|
|
249
|
+
...mockBill,
|
|
250
|
+
totalAmount: 100,
|
|
251
|
+
tenderedAmount: 0,
|
|
252
|
+
lineItems: [],
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
render(<Payments bill={billWithAmountDue} mutate={mockMutate} />);
|
|
256
|
+
|
|
257
|
+
// Process payment button should be visible
|
|
258
|
+
expect(screen.getByText('Process Payment')).toBeInTheDocument();
|
|
259
|
+
// Button should be disabled when no payment methods are added
|
|
260
|
+
expect(screen.getByText('Process Payment')).toBeDisabled();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should allow adding multiple payment methods for split payments', async () => {
|
|
264
|
+
const user = userEvent.setup();
|
|
265
|
+
const billWithAmountDue: MappedBill = {
|
|
266
|
+
...mockBill,
|
|
267
|
+
totalAmount: 100,
|
|
268
|
+
tenderedAmount: 0,
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
render(<Payments bill={billWithAmountDue} mutate={mockMutate} />);
|
|
272
|
+
|
|
273
|
+
// Add first payment method
|
|
274
|
+
await user.click(screen.getByText(/add payment method/i));
|
|
275
|
+
expect(screen.getByPlaceholderText(/enter amount/i)).toBeInTheDocument();
|
|
276
|
+
|
|
277
|
+
// Add second payment method
|
|
278
|
+
await user.click(screen.getByText(/add payment method/i));
|
|
279
|
+
const amountInputs = screen.getAllByPlaceholderText(/enter amount/i);
|
|
280
|
+
expect(amountInputs).toHaveLength(2);
|
|
281
|
+
});
|
|
135
282
|
});
|
|
@@ -21,7 +21,7 @@ export const createPaymentPayload = (
|
|
|
21
21
|
|
|
22
22
|
const newPayments = formValues.map((formValue) => ({
|
|
23
23
|
amount: parseFloat(totalAmount.toFixed(2)),
|
|
24
|
-
amountTendered: parseFloat(Number(formValue.amount).toFixed(2)),
|
|
24
|
+
amountTendered: parseFloat(Number(formValue.amount || 0).toFixed(2)),
|
|
25
25
|
attributes: [],
|
|
26
26
|
instanceType: formValue.method,
|
|
27
27
|
dateCreated: new Date(),
|
package/translations/en.json
CHANGED
|
@@ -8,11 +8,14 @@
|
|
|
8
8
|
"addNewCashPoint": "Add New Cash Point",
|
|
9
9
|
"addNewPaymentMode": "Add New Payment Mode",
|
|
10
10
|
"addNewService": "Add new service",
|
|
11
|
+
"addPaymentMethod": "Add payment method",
|
|
11
12
|
"addPaymentMode": "Add Payment Mode",
|
|
12
13
|
"addPaymentOption": "Add payment option",
|
|
13
14
|
"addPaymentOptions": "Add payment option",
|
|
14
15
|
"amount": "Amount",
|
|
15
16
|
"amountDue": "Amount Due",
|
|
17
|
+
"amountMustBePositive": "Amount must be greater than 0",
|
|
18
|
+
"amountRequired": "Amount is required",
|
|
16
19
|
"amountTendered": "Amount Tendered",
|
|
17
20
|
"amountToWaiveAriaLabel": "Enter amount to waive",
|
|
18
21
|
"amountToWaiveHelper": "Specify the amount to be deducted from the bill",
|
|
@@ -76,7 +79,7 @@
|
|
|
76
79
|
"editThisBillItem": "Edit this bill item",
|
|
77
80
|
"enterAmount": "Enter amount",
|
|
78
81
|
"enterConcept": "Associated concept",
|
|
79
|
-
"enterReferenceNumber": "Enter
|
|
82
|
+
"enterReferenceNumber": "Enter reference number",
|
|
80
83
|
"enterSellingPrice": "Enter selling price",
|
|
81
84
|
"enterServiceName": "Enter service name",
|
|
82
85
|
"enterServiceShortName": "Enter service short name",
|
|
@@ -88,6 +91,7 @@
|
|
|
88
91
|
"errorLoadingBillServices": "Error loading bill services",
|
|
89
92
|
"errorLoadingPaymentModes": "Payment modes error",
|
|
90
93
|
"errorPrintingInvoice": "Error printing invoice",
|
|
94
|
+
"errorProcessingPayment": "Error processing payment",
|
|
91
95
|
"errorSavingCashPoint": "An error occurred while saving the cash point.",
|
|
92
96
|
"errorSavingPaymentMode": "An error occurred while saving the payment mode.",
|
|
93
97
|
"filterBy": "Filter by",
|
|
@@ -130,6 +134,7 @@
|
|
|
130
134
|
"patientBills": "Patient bill",
|
|
131
135
|
"patientBillsDescription": "List of patient bills",
|
|
132
136
|
"patientCategory": "Patient category",
|
|
137
|
+
"paymentAmountCannotExceedAmountDue": "Payment amount cannot exceed amount due",
|
|
133
138
|
"paymentDetails": "Payment Details",
|
|
134
139
|
"paymentMethod": "Payment method",
|
|
135
140
|
"paymentMethods": "Payment methods",
|
|
@@ -143,6 +148,7 @@
|
|
|
143
148
|
"paymentModeSaved": "Payment mode was successfully saved.",
|
|
144
149
|
"paymentModesConfig": "Payment Modes Config",
|
|
145
150
|
"paymentOptionRequired": "At least one payment option is required",
|
|
151
|
+
"paymentProcessedSuccessfully": "Payment processed successfully",
|
|
146
152
|
"payments": "Payments",
|
|
147
153
|
"pleaseRequiredFields": "Please fill all required fields",
|
|
148
154
|
"policyNumber": "Policy number",
|
|
@@ -159,6 +165,8 @@
|
|
|
159
165
|
"quantity": "Quantity",
|
|
160
166
|
"quantityRequired": "Quantity is required",
|
|
161
167
|
"referenceNumber": "Reference number",
|
|
168
|
+
"remove": "Remove",
|
|
169
|
+
"removePaymentMethod": "Remove payment method",
|
|
162
170
|
"saveAndClose": "Save and close",
|
|
163
171
|
"saveBill": "Save Bill",
|
|
164
172
|
"saving": "Saving",
|
|
@@ -167,11 +175,14 @@
|
|
|
167
175
|
"searchItems": "Search items and services",
|
|
168
176
|
"searchThisTable": "Search this table",
|
|
169
177
|
"selectBillableService": "Select a billable service...",
|
|
178
|
+
"selectedItems": "Selected Items",
|
|
170
179
|
"selectLocation": "Select Location",
|
|
171
180
|
"selectPatientCategory": "Select patient category",
|
|
172
181
|
"selectPaymentMethod": "Select payment method",
|
|
182
|
+
"selectPaymentMethodRequired": "Please select a payment method for all items",
|
|
173
183
|
"selectPaymentMode": "Select payment mode",
|
|
174
184
|
"selectServiceType": "Select service type",
|
|
185
|
+
"sellingAmount": "Enter selling price",
|
|
175
186
|
"sellingPrice": "Selling Price",
|
|
176
187
|
"serviceMetrics": "Service Metrics",
|
|
177
188
|
"serviceName": "Service Name",
|
|
@@ -195,6 +206,7 @@
|
|
|
195
206
|
"updatedSuccessfully": "Billable service updated successfully",
|
|
196
207
|
"uuid": "UUID",
|
|
197
208
|
"uuidRequired": "UUID is required",
|
|
209
|
+
"validationError": "Validation Error",
|
|
198
210
|
"visitTime": "Visit time",
|
|
199
211
|
"waiverForm": "Waiver form"
|
|
200
212
|
}
|