@openmrs/esm-billing-app 1.0.2-pre.62 → 1.0.2-pre.624
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/README.md +55 -9
- package/__mocks__/react-i18next.js +6 -5
- package/dist/1119.js +1 -1
- package/dist/1146.js +1 -0
- package/dist/1146.js.map +1 -0
- package/dist/1197.js +1 -1
- package/dist/2146.js +1 -1
- package/dist/2177.js +2 -0
- package/dist/2177.js.map +1 -0
- package/dist/2352.js +1 -0
- package/dist/2352.js.map +1 -0
- package/dist/2690.js +1 -1
- package/dist/2747.js +2 -0
- package/dist/{4817.js.LICENSE.txt → 2747.js.LICENSE.txt} +0 -10
- package/dist/2747.js.map +1 -0
- package/dist/3041.js +1 -0
- package/dist/3041.js.map +1 -0
- package/dist/3099.js +1 -1
- package/dist/3184.js +2 -0
- package/dist/3184.js.LICENSE.txt +14 -0
- package/dist/3184.js.map +1 -0
- package/dist/3584.js +1 -1
- package/dist/4055.js +1 -1
- package/dist/4132.js +1 -1
- package/dist/4225.js +1 -1
- package/dist/4225.js.map +1 -1
- package/dist/4300.js +1 -1
- package/dist/4335.js +1 -1
- package/dist/4618.js +1 -1
- package/dist/4652.js +1 -1
- package/dist/4739.js +1 -0
- package/dist/{9055.js.map → 4739.js.map} +1 -1
- package/dist/4944.js +1 -1
- package/dist/5173.js +1 -1
- package/dist/5241.js +1 -1
- package/dist/5422.js +1 -0
- package/dist/5422.js.map +1 -0
- package/dist/5442.js +1 -1
- package/dist/5661.js +1 -1
- package/dist/590.js +2 -0
- package/dist/590.js.LICENSE.txt +14 -0
- package/dist/590.js.map +1 -0
- package/dist/6022.js +1 -1
- package/dist/6468.js +1 -1
- package/dist/6540.js +1 -1
- package/dist/6540.js.map +1 -1
- package/dist/6606.js +1 -2
- package/dist/6606.js.map +1 -1
- package/dist/6679.js +1 -1
- package/dist/6840.js +1 -1
- package/dist/6859.js +1 -1
- package/dist/7097.js +1 -1
- package/dist/7159.js +1 -1
- package/dist/723.js +1 -1
- package/dist/7239.js +1 -0
- package/dist/7239.js.map +1 -0
- package/dist/7255.js +1 -1
- package/dist/7255.js.map +1 -1
- package/dist/7617.js +1 -1
- package/dist/7692.js +1 -0
- package/dist/7692.js.map +1 -0
- package/dist/7935.js +1 -0
- package/dist/7935.js.map +1 -0
- package/dist/795.js +1 -0
- package/dist/8163.js +1 -1
- package/dist/8349.js +1 -1
- package/dist/8618.js +1 -1
- package/dist/8638.js +1 -0
- package/dist/8638.js.map +1 -0
- package/dist/890.js +1 -1
- package/dist/9214.js +1 -1
- package/dist/9538.js +1 -1
- package/dist/9569.js +1 -0
- package/dist/961.js +1 -1
- package/dist/961.js.map +1 -1
- package/dist/986.js +1 -1
- package/dist/9879.js +1 -1
- package/dist/9900.js +1 -1
- package/dist/9913.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-billing-app.js +1 -1
- package/dist/openmrs-esm-billing-app.js.buildmanifest.json +348 -195
- package/dist/openmrs-esm-billing-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/e2e/README.md +19 -18
- package/e2e/specs/sample-test.spec.ts +0 -1
- package/jest.config.js +2 -2
- package/package.json +7 -7
- package/src/bill-history/bill-history.component.tsx +6 -12
- package/src/bill-history/bill-history.test.tsx +37 -78
- package/src/bill-item-actions/edit-bill-item.component.tsx +7 -3
- package/src/bill-item-actions/edit-bill-item.test.tsx +17 -19
- package/src/billable-services/bill-waiver/patient-bills.component.tsx +3 -3
- package/src/billable-services/billable-service.resource.ts +4 -3
- package/src/billable-services/billable-services.component.tsx +6 -5
- package/src/billable-services/billable-services.test.tsx +3 -44
- package/src/billable-services/cash-point/cash-point-configuration.component.tsx +2 -2
- package/src/billable-services/create-edit/add-billable-service.component.tsx +10 -3
- package/src/billable-services/create-edit/add-billable-service.test.tsx +6 -6
- package/src/billable-services/payyment-modes/payment-modes-config.component.tsx +1 -1
- package/src/billing-form/billing-checkin-form.component.tsx +1 -2
- package/src/billing-form/billing-checkin-form.test.tsx +0 -2
- package/src/billing-form/billing-form.component.tsx +8 -4
- package/src/billing.resource.ts +13 -9
- package/src/bills-table/bills-table.test.tsx +97 -53
- package/src/config-schema.ts +52 -18
- package/src/invoice/invoice-table.component.tsx +9 -9
- package/src/invoice/invoice-table.scss +1 -5
- package/src/invoice/invoice-table.test.tsx +24 -39
- package/src/invoice/invoice.component.tsx +8 -6
- package/src/invoice/invoice.scss +7 -4
- package/src/invoice/invoice.test.tsx +12 -47
- package/src/invoice/payments/payment-form/payment-form.test.tsx +8 -10
- package/src/invoice/payments/payment-history/payment-history.component.tsx +6 -4
- package/src/invoice/payments/payment-history/payment-history.test.tsx +9 -14
- package/src/invoice/payments/payments.component.test.tsx +20 -6
- package/src/invoice/printable-invoice/print-receipt.component.tsx +1 -1
- package/src/invoice/printable-invoice/print-receipt.test.tsx +14 -25
- package/src/invoice/printable-invoice/printable-footer.component.tsx +2 -2
- package/src/invoice/printable-invoice/printable-footer.test.tsx +4 -13
- package/src/invoice/printable-invoice/printable-invoice-header.component.tsx +5 -4
- package/src/invoice/printable-invoice/printable-invoice-header.test.tsx +11 -11
- package/src/invoice/printable-invoice/printable-invoice.component.tsx +11 -11
- package/src/metrics-cards/metrics-cards.test.tsx +18 -5
- package/src/modal/require-payment-modal.test.tsx +24 -19
- package/translations/bn.json +7 -7
- package/translations/en.json +18 -0
- package/translations/en_US.json +170 -0
- package/translations/es.json +16 -16
- package/translations/id.json +163 -163
- package/translations/it.json +43 -43
- package/translations/ka.json +170 -0
- package/translations/ro_RO.json +165 -165
- package/translations/zh_CN.json +66 -66
- package/dist/1362.js +0 -1
- package/dist/1362.js.map +0 -1
- package/dist/3029.js +0 -2
- package/dist/3029.js.LICENSE.txt +0 -7
- package/dist/3029.js.map +0 -1
- package/dist/3511.js +0 -1
- package/dist/3511.js.map +0 -1
- package/dist/4817.js +0 -2
- package/dist/4817.js.map +0 -1
- package/dist/4993.js +0 -1
- package/dist/4993.js.map +0 -1
- package/dist/6941.js +0 -1
- package/dist/6941.js.map +0 -1
- package/dist/763.js +0 -1
- package/dist/763.js.map +0 -1
- package/dist/9055.js +0 -1
- /package/dist/{6606.js.LICENSE.txt → 2177.js.LICENSE.txt} +0 -0
|
@@ -2,8 +2,8 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { Button } from '@carbon/react';
|
|
3
3
|
import { Printer } from '@carbon/react/icons';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import styles from './print-receipt.scss';
|
|
6
5
|
import { apiBasePath } from '../../constants';
|
|
6
|
+
import styles from './print-receipt.scss';
|
|
7
7
|
|
|
8
8
|
interface PrintReceiptProps {
|
|
9
9
|
billId: number;
|
|
@@ -1,50 +1,39 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
4
|
import PrintReceipt from './print-receipt.component';
|
|
5
5
|
|
|
6
|
-
jest.mock('react-i18next', () => ({
|
|
7
|
-
useTranslation: jest.fn(),
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
jest.mock('@carbon/react/icons', () => ({
|
|
11
|
-
Printer: jest.fn(() => <div data-testid="printer-icon" />),
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
6
|
describe('PrintReceipt', () => {
|
|
15
|
-
const mockT = jest.fn((key) => key);
|
|
16
|
-
|
|
17
7
|
beforeEach(() => {
|
|
18
|
-
(useTranslation as jest.Mock).mockReturnValue({ t: mockT });
|
|
19
|
-
jest.useFakeTimers();
|
|
20
8
|
window.URL.createObjectURL = jest.fn();
|
|
21
9
|
});
|
|
22
10
|
|
|
23
|
-
afterEach(() => {
|
|
24
|
-
jest.useRealTimers();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
11
|
it('renders button with correct text and icon', () => {
|
|
28
12
|
render(<PrintReceipt billId={123} />);
|
|
29
|
-
expect(screen.getByText('
|
|
30
|
-
expect(screen.getByTestId('printer-icon')).toBeInTheDocument();
|
|
13
|
+
expect(screen.getByText('Print receipt')).toBeInTheDocument();
|
|
31
14
|
});
|
|
32
15
|
|
|
33
|
-
it('displays "Loading" and disables button when isRedirecting is true', () => {
|
|
16
|
+
it('displays "Loading" and disables button when isRedirecting is true', async () => {
|
|
17
|
+
const user = userEvent.setup();
|
|
18
|
+
|
|
34
19
|
render(<PrintReceipt billId={123} />);
|
|
20
|
+
|
|
35
21
|
const button = screen.getByRole('button');
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
|
|
23
|
+
await user.click(button);
|
|
24
|
+
expect(screen.getByText(/loading/i)).toBeInTheDocument();
|
|
38
25
|
expect(button).toBeDisabled();
|
|
39
26
|
});
|
|
40
27
|
|
|
41
|
-
it('applies correct CSS class to button', () => {
|
|
28
|
+
it('applies correct CSS class to button', async () => {
|
|
29
|
+
const user = userEvent.setup();
|
|
30
|
+
|
|
42
31
|
render(<PrintReceipt billId={123} />);
|
|
43
32
|
expect(screen.getByRole('button')).toHaveClass('button');
|
|
44
33
|
});
|
|
45
34
|
|
|
46
35
|
it('translates button text correctly', () => {
|
|
47
36
|
render(<PrintReceipt billId={123} />);
|
|
48
|
-
expect(
|
|
37
|
+
expect(screen.getByText('Print receipt')).toBeInTheDocument();
|
|
49
38
|
});
|
|
50
39
|
});
|
|
@@ -3,9 +3,9 @@ import { useDefaultFacility } from '../../billing.resource';
|
|
|
3
3
|
import styles from './printable-footer.scss';
|
|
4
4
|
|
|
5
5
|
const PrintableFooter = () => {
|
|
6
|
-
const { data
|
|
6
|
+
const { data } = useDefaultFacility();
|
|
7
7
|
|
|
8
|
-
if (
|
|
8
|
+
if (!data) {
|
|
9
9
|
return <div>--</div>;
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -3,28 +3,19 @@ import { screen, render } from '@testing-library/react';
|
|
|
3
3
|
import { useDefaultFacility } from '../../billing.resource';
|
|
4
4
|
import PrintableFooter from './printable-footer.component';
|
|
5
5
|
|
|
6
|
-
const mockUseDefaultFacility =
|
|
6
|
+
const mockUseDefaultFacility = jest.mocked<typeof useDefaultFacility>(useDefaultFacility);
|
|
7
7
|
|
|
8
8
|
jest.mock('../../billing.resource', () => ({
|
|
9
9
|
useDefaultFacility: jest.fn(),
|
|
10
10
|
}));
|
|
11
11
|
|
|
12
12
|
describe('PrintableFooter', () => {
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
jest.clearAllMocks();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
13
|
test('should render PrintableFooter component', () => {
|
|
18
|
-
mockUseDefaultFacility.mockReturnValue({
|
|
14
|
+
mockUseDefaultFacility.mockReturnValue({
|
|
15
|
+
data: { display: 'MTRH', uuid: 'mtrh-uuid', links: [] },
|
|
16
|
+
});
|
|
19
17
|
render(<PrintableFooter />);
|
|
20
18
|
const footer = screen.getByText('MTRH');
|
|
21
19
|
expect(footer).toBeInTheDocument();
|
|
22
20
|
});
|
|
23
|
-
|
|
24
|
-
test('should show placeholder text when facility isLoading', () => {
|
|
25
|
-
mockUseDefaultFacility.mockReturnValue({ data: { display: 'MTRH', uuid: 'mtrh-uuid' }, isLoading: true });
|
|
26
|
-
render(<PrintableFooter />);
|
|
27
|
-
const footer = screen.getByText('--');
|
|
28
|
-
expect(footer).toBeInTheDocument();
|
|
29
|
-
});
|
|
30
21
|
});
|
|
@@ -3,6 +3,7 @@ import { type PatientDetails } from '../../types';
|
|
|
3
3
|
import { useConfig } from '@openmrs/esm-framework';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { useDefaultFacility } from '../../billing.resource';
|
|
6
|
+
import type { BillingConfig } from '../../config-schema';
|
|
6
7
|
import styles from './printable-invoice-header.scss';
|
|
7
8
|
|
|
8
9
|
interface PrintableInvoiceHeaderProps {
|
|
@@ -11,7 +12,7 @@ interface PrintableInvoiceHeaderProps {
|
|
|
11
12
|
|
|
12
13
|
const PrintableInvoiceHeader: React.FC<PrintableInvoiceHeaderProps> = ({ patientDetails }) => {
|
|
13
14
|
const { t } = useTranslation();
|
|
14
|
-
const { logo } = useConfig();
|
|
15
|
+
const { logo, country } = useConfig<BillingConfig>();
|
|
15
16
|
const { data } = useDefaultFacility();
|
|
16
17
|
|
|
17
18
|
return (
|
|
@@ -20,8 +21,8 @@ const PrintableInvoiceHeader: React.FC<PrintableInvoiceHeaderProps> = ({ patient
|
|
|
20
21
|
<p className={styles.heading}>{t('invoice', 'Invoice')}</p>
|
|
21
22
|
{logo?.src ? (
|
|
22
23
|
<img className={styles.img} src={logo.src} alt={logo.alt} />
|
|
23
|
-
) : logo?.
|
|
24
|
-
logo.
|
|
24
|
+
) : logo?.alt ? (
|
|
25
|
+
logo.alt
|
|
25
26
|
) : (
|
|
26
27
|
// OpenMRS Logo
|
|
27
28
|
<svg
|
|
@@ -53,7 +54,7 @@ const PrintableInvoiceHeader: React.FC<PrintableInvoiceHeaderProps> = ({ patient
|
|
|
53
54
|
|
|
54
55
|
<div className={styles.facilityDetails}>
|
|
55
56
|
<p className={styles.facilityName}>{data?.display}</p>
|
|
56
|
-
<p className={styles.itemLabel}>
|
|
57
|
+
<p className={styles.itemLabel}>{country}</p>
|
|
57
58
|
</div>
|
|
58
59
|
</div>
|
|
59
60
|
</div>
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { screen, render } from '@testing-library/react';
|
|
3
3
|
import { useConfig } from '@openmrs/esm-framework';
|
|
4
|
+
import { type BillingConfig } from '../../config-schema';
|
|
4
5
|
import { useDefaultFacility } from '../../billing.resource';
|
|
5
6
|
import PrintableInvoiceHeader from './printable-invoice-header.component';
|
|
6
7
|
|
|
7
|
-
const mockUseDefaultFacility =
|
|
8
|
-
const mockUseConfig =
|
|
8
|
+
const mockUseDefaultFacility = jest.mocked(useDefaultFacility);
|
|
9
|
+
const mockUseConfig = jest.mocked(useConfig<BillingConfig>);
|
|
9
10
|
|
|
10
11
|
jest.mock('../../billing.resource', () => ({
|
|
11
12
|
useDefaultFacility: jest.fn(),
|
|
12
13
|
}));
|
|
13
14
|
|
|
14
|
-
jest.mock('@openmrs/esm-framework', () => ({
|
|
15
|
-
useConfig: jest.fn(),
|
|
16
|
-
}));
|
|
17
15
|
const testProps = {
|
|
18
16
|
patientDetails: {
|
|
19
17
|
name: 'John Doe',
|
|
@@ -26,9 +24,15 @@ const testProps = {
|
|
|
26
24
|
};
|
|
27
25
|
|
|
28
26
|
describe('PrintableInvoiceHeader', () => {
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
mockUseConfig.mockReturnValue({
|
|
29
|
+
logo: { src: 'logo.png', alt: 'logo' },
|
|
30
|
+
country: 'Kenya',
|
|
31
|
+
} as unknown as BillingConfig);
|
|
32
|
+
mockUseDefaultFacility.mockReturnValue({ data: { display: 'MTRH', uuid: 'mtrh-uuid', links: [] } });
|
|
33
|
+
});
|
|
34
|
+
|
|
29
35
|
test('should render PrintableInvoiceHeader component', () => {
|
|
30
|
-
mockUseConfig.mockReturnValue({ logo: { src: 'logo.png', alt: 'logo' } });
|
|
31
|
-
mockUseDefaultFacility.mockReturnValue({ data: { display: 'MTRH', uuid: 'mtrh-uuid' }, isLoading: false });
|
|
32
36
|
render(<PrintableInvoiceHeader {...testProps} />);
|
|
33
37
|
const header = screen.getByText('Invoice');
|
|
34
38
|
expect(header).toBeInTheDocument();
|
|
@@ -41,16 +45,12 @@ describe('PrintableInvoiceHeader', () => {
|
|
|
41
45
|
});
|
|
42
46
|
|
|
43
47
|
test('should display the logo when logo is provided', () => {
|
|
44
|
-
mockUseConfig.mockReturnValue({ logo: { src: 'logo.png', alt: 'logo' } });
|
|
45
|
-
mockUseDefaultFacility.mockReturnValue({ data: { display: 'MTRH', uuid: 'mtrh-uuid' }, isLoading: false });
|
|
46
48
|
render(<PrintableInvoiceHeader {...testProps} />);
|
|
47
49
|
const logo = screen.getByAltText('logo');
|
|
48
50
|
expect(logo).toBeInTheDocument();
|
|
49
51
|
});
|
|
50
52
|
|
|
51
53
|
test('should display the default logo when logo is not provided', () => {
|
|
52
|
-
mockUseConfig.mockReturnValue({ logo: {} });
|
|
53
|
-
mockUseDefaultFacility.mockReturnValue({ data: { display: 'MTRH', uuid: 'mtrh-uuid' }, isLoading: false });
|
|
54
54
|
render(<PrintableInvoiceHeader {...testProps} />);
|
|
55
55
|
const logo = screen.getByRole('img');
|
|
56
56
|
expect(logo).toBeInTheDocument();
|
|
@@ -29,10 +29,10 @@ const PrintableInvoice: React.FC<PrintableInvoiceProps> = ({ bill, patient, isLo
|
|
|
29
29
|
const layout = useLayoutType();
|
|
30
30
|
const responsiveSize = isDesktop(layout) ? 'sm' : 'lg';
|
|
31
31
|
const headerData = [
|
|
32
|
-
{ header: 'Inventory item', key: 'billItem' },
|
|
33
|
-
{ header: 'Quantity', key: 'quantity' },
|
|
34
|
-
{ header: 'Unit price', key: 'price' },
|
|
35
|
-
{ header: 'Total', key: 'total' },
|
|
32
|
+
{ header: t('inventoryItem', 'Inventory item'), key: 'billItem' },
|
|
33
|
+
{ header: t('quantity', 'Quantity'), key: 'quantity' },
|
|
34
|
+
{ header: t('unitPrice', 'Unit price'), key: 'price' },
|
|
35
|
+
{ header: t('total', 'Total'), key: 'total' },
|
|
36
36
|
];
|
|
37
37
|
|
|
38
38
|
const rowData =
|
|
@@ -47,10 +47,10 @@ const PrintableInvoice: React.FC<PrintableInvoiceProps> = ({ bill, patient, isLo
|
|
|
47
47
|
}) ?? [];
|
|
48
48
|
|
|
49
49
|
const invoiceTotal = {
|
|
50
|
-
'Total Amount': bill?.totalAmount,
|
|
51
|
-
'Amount Tendered': bill?.tenderedAmount,
|
|
52
|
-
'Discount Amount': 0,
|
|
53
|
-
'Amount due': bill?.totalAmount - bill?.tenderedAmount,
|
|
50
|
+
[t('totalAmount', 'Total Amount')]: bill?.totalAmount,
|
|
51
|
+
[t('amountTendered', 'Amount Tendered')]: bill?.tenderedAmount,
|
|
52
|
+
[t('discountAmount', 'Discount Amount')]: 0,
|
|
53
|
+
[t('amountDue', 'Amount due')]: bill?.totalAmount - bill?.tenderedAmount,
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
const patientDetails = useMemo(() => {
|
|
@@ -65,9 +65,9 @@ const PrintableInvoice: React.FC<PrintableInvoiceProps> = ({ bill, patient, isLo
|
|
|
65
65
|
}, [patient, t]);
|
|
66
66
|
|
|
67
67
|
const invoiceDetails = {
|
|
68
|
-
'Invoice #': bill?.receiptNumber,
|
|
69
|
-
'Invoice date': bill.dateCreated,
|
|
70
|
-
Status: bill?.status,
|
|
68
|
+
[t('invoiceNumber', 'Invoice #')]: bill?.receiptNumber,
|
|
69
|
+
[t('invoiceDate', 'Invoice date')]: bill.dateCreated,
|
|
70
|
+
[t('status', 'Status')]: bill?.status,
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
if (isLoading) {
|
|
@@ -3,10 +3,11 @@ import { render, screen } from '@testing-library/react';
|
|
|
3
3
|
import { useConfig } from '@openmrs/esm-framework';
|
|
4
4
|
import { billsSummary } from '../../__mocks__/bills.mock';
|
|
5
5
|
import { useBills } from '../billing.resource';
|
|
6
|
+
import { type MappedBill } from '../types';
|
|
6
7
|
import MetricsCards from './metrics-cards.component';
|
|
7
8
|
|
|
8
|
-
const mockUseBills =
|
|
9
|
-
const mockUseConfig =
|
|
9
|
+
const mockUseBills = jest.mocked(useBills);
|
|
10
|
+
const mockUseConfig = jest.mocked(useConfig);
|
|
10
11
|
|
|
11
12
|
jest.mock('../billing.resource', () => ({
|
|
12
13
|
useBills: jest.fn(),
|
|
@@ -14,13 +15,19 @@ jest.mock('../billing.resource', () => ({
|
|
|
14
15
|
|
|
15
16
|
describe('MetricsCards', () => {
|
|
16
17
|
test('renders loading state', () => {
|
|
17
|
-
mockUseBills.mockReturnValue({ isLoading: true, bills: [], error: null });
|
|
18
|
+
mockUseBills.mockReturnValue({ isLoading: true, bills: [], error: null, isValidating: false, mutate: jest.fn() });
|
|
18
19
|
renderMetricsCards();
|
|
19
20
|
expect(screen.getByText(/Loading bill metrics.../i)).toBeInTheDocument();
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
test('renders error state', () => {
|
|
23
|
-
mockUseBills.mockReturnValue({
|
|
24
|
+
mockUseBills.mockReturnValue({
|
|
25
|
+
isLoading: false,
|
|
26
|
+
bills: [],
|
|
27
|
+
error: new Error('Internal server error'),
|
|
28
|
+
isValidating: false,
|
|
29
|
+
mutate: jest.fn(),
|
|
30
|
+
});
|
|
24
31
|
renderMetricsCards();
|
|
25
32
|
expect(
|
|
26
33
|
screen.getByText(
|
|
@@ -30,7 +37,13 @@ describe('MetricsCards', () => {
|
|
|
30
37
|
});
|
|
31
38
|
|
|
32
39
|
test('renders metrics cards', () => {
|
|
33
|
-
mockUseBills.mockReturnValue({
|
|
40
|
+
mockUseBills.mockReturnValue({
|
|
41
|
+
isLoading: false,
|
|
42
|
+
bills: billsSummary as unknown as MappedBill[],
|
|
43
|
+
error: null,
|
|
44
|
+
isValidating: false,
|
|
45
|
+
mutate: jest.fn(),
|
|
46
|
+
});
|
|
34
47
|
mockUseConfig.mockImplementation(() => ({ defaultCurrency: 'USD' }));
|
|
35
48
|
renderMetricsCards();
|
|
36
49
|
expect(screen.getByRole('heading', { name: /cumulative bills/i })).toBeInTheDocument();
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
import '@testing-library/
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
|
|
4
5
|
import { useBills } from '../billing.resource';
|
|
6
|
+
import { type MappedBill } from '../types';
|
|
7
|
+
import { configSchema, type BillingConfig } from '../config-schema';
|
|
5
8
|
import RequirePaymentModal from './require-payment-modal.component';
|
|
6
9
|
|
|
7
|
-
jest.
|
|
8
|
-
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
jest.mock('@openmrs/esm-framework', () => ({
|
|
12
|
-
useConfig: () => ({ defaultCurrency: 'USD' }),
|
|
13
|
-
}));
|
|
10
|
+
const mockUseConfig = jest.mocked(useConfig<BillingConfig>);
|
|
11
|
+
const mockUseBills = jest.mocked<typeof useBills>(useBills);
|
|
14
12
|
|
|
15
13
|
jest.mock('../billing.resource', () => ({
|
|
16
14
|
useBills: jest.fn(),
|
|
@@ -25,19 +23,19 @@ describe('RequirePaymentModal', () => {
|
|
|
25
23
|
const patientUuid = '12345';
|
|
26
24
|
|
|
27
25
|
beforeEach(() => {
|
|
28
|
-
|
|
26
|
+
mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), defaultCurrency: 'USD' });
|
|
29
27
|
});
|
|
30
28
|
|
|
31
29
|
it('renders correctly', () => {
|
|
32
|
-
|
|
30
|
+
mockUseBills.mockReturnValue({ bills: [], isLoading: false, error: null, isValidating: false, mutate: jest.fn() });
|
|
33
31
|
render(<RequirePaymentModal closeModal={closeModal} patientUuid={patientUuid} />);
|
|
34
|
-
expect(screen.getByText('
|
|
32
|
+
expect(screen.getByText('Patient Billing Alert')).toBeInTheDocument();
|
|
35
33
|
});
|
|
36
34
|
|
|
37
35
|
it('displays loading state', () => {
|
|
38
|
-
|
|
36
|
+
mockUseBills.mockReturnValue({ bills: [], isLoading: true, error: null, isValidating: false, mutate: jest.fn() });
|
|
39
37
|
render(<RequirePaymentModal closeModal={closeModal} patientUuid={patientUuid} />);
|
|
40
|
-
expect(screen.getByText('
|
|
38
|
+
expect(screen.getByText('Loading bill items...')).toBeInTheDocument();
|
|
41
39
|
});
|
|
42
40
|
|
|
43
41
|
it('displays line items', () => {
|
|
@@ -50,17 +48,24 @@ describe('RequirePaymentModal', () => {
|
|
|
50
48
|
],
|
|
51
49
|
},
|
|
52
50
|
];
|
|
53
|
-
|
|
51
|
+
mockUseBills.mockReturnValue({
|
|
52
|
+
bills: bills as unknown as MappedBill[],
|
|
53
|
+
isLoading: false,
|
|
54
|
+
error: null,
|
|
55
|
+
isValidating: false,
|
|
56
|
+
mutate: jest.fn(),
|
|
57
|
+
});
|
|
54
58
|
render(<RequirePaymentModal closeModal={closeModal} patientUuid={patientUuid} />);
|
|
55
59
|
expect(screen.getByText('Service 1')).toBeInTheDocument();
|
|
56
60
|
expect(screen.getByText('Item 1')).toBeInTheDocument();
|
|
57
61
|
});
|
|
58
62
|
|
|
59
|
-
it('handles closeModal', () => {
|
|
60
|
-
|
|
63
|
+
it('handles closeModal', async () => {
|
|
64
|
+
const user = userEvent.setup();
|
|
65
|
+
mockUseBills.mockReturnValue({ bills: [], isLoading: false, error: null, isValidating: false, mutate: jest.fn() });
|
|
61
66
|
render(<RequirePaymentModal closeModal={closeModal} patientUuid={patientUuid} />);
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
await user.click(screen.getByText('Cancel'));
|
|
68
|
+
await user.click(screen.getByText('OK'));
|
|
64
69
|
expect(closeModal).toHaveBeenCalledTimes(2);
|
|
65
70
|
});
|
|
66
71
|
});
|
package/translations/bn.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"addPaymentMode": "Add Payment Mode",
|
|
9
9
|
"addPaymentOptions": "Add payment option",
|
|
10
10
|
"amount": "Amount",
|
|
11
|
-
"amountDue": "
|
|
11
|
+
"amountDue": "বাকি",
|
|
12
12
|
"amountToWaiveAriaLabel": "Enter amount to waive",
|
|
13
13
|
"amountToWaiveHelper": "Specify the amount to be deducted from the bill",
|
|
14
14
|
"amountToWaiveLabel": "Amount to Waive",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"billPaymentError": "Bill payment error",
|
|
32
32
|
"billPaymentRequiredMessage": "The current patient has pending bill. Advice patient to settle bill before receiving services",
|
|
33
33
|
"billServicesManagement": "Bill services management",
|
|
34
|
-
"billsList": "
|
|
34
|
+
"billsList": "মূল্য তালিকা",
|
|
35
35
|
"billTotal": "Bill total",
|
|
36
36
|
"billWaiver": "Bill waiver",
|
|
37
37
|
"billWaiverError": "Bill waiver failed {{error}}",
|
|
38
38
|
"billWaiverSuccess": "Bill waiver successful",
|
|
39
|
-
"cancel": "
|
|
39
|
+
"cancel": "বাতিল",
|
|
40
40
|
"cashPointConfig": "Cash Point Config",
|
|
41
41
|
"cashPointHistory": "Cash Point History",
|
|
42
42
|
"cashPointLocation": "Cash Point Location",
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
"confirmDeleteMessage": "Are you sure you want to delete this payment mode? Proceed cautiously.",
|
|
52
52
|
"createdSuccessfully": "Billable service created successfully",
|
|
53
53
|
"currentPrice": "Current price",
|
|
54
|
-
"delete": "
|
|
54
|
+
"delete": "ডিলিট",
|
|
55
55
|
"deletePaymentMode": "Delete Payment Mode",
|
|
56
|
-
"description": "
|
|
56
|
+
"description": "বিবরণ",
|
|
57
57
|
"descriptionPlaceholder": "e.g., Used for all cash transactions",
|
|
58
58
|
"discard": "Discard",
|
|
59
|
-
"discount": "
|
|
59
|
+
"discount": "মূল্যছাড়",
|
|
60
60
|
"duplicateCashPointError": "A cash point with the same name or UUID already exists. Please use a unique name and UUID.",
|
|
61
61
|
"duplicatePaymentModeError": "A payment mode with the same name already exists. Please create another payment mode",
|
|
62
62
|
"editBillableService": "Edit billable service",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"enterAmount": "Enter amount",
|
|
67
67
|
"enterConcept": "Associated concept",
|
|
68
68
|
"enterReferenceNumber": "Enter ref. number",
|
|
69
|
-
"error": "
|
|
69
|
+
"error": "ত্রুটি",
|
|
70
70
|
"errorDeletingPaymentMode": "An error occurred while deleting the payment mode.",
|
|
71
71
|
"errorFetchingCashPoints": "An error occurred while fetching cash points.",
|
|
72
72
|
"errorFetchingLocations": "An error occurred while fetching locations.",
|
package/translations/en.json
CHANGED
|
@@ -4,16 +4,21 @@
|
|
|
4
4
|
"addBillableServices": "Add Billable Services",
|
|
5
5
|
"addCashPoint": "Add Cash Point",
|
|
6
6
|
"addNewBillableService": "Add new billable service",
|
|
7
|
+
"addNewCashPoint": "Add New Cash Point",
|
|
8
|
+
"addNewPaymentMode": "Add New Payment Mode",
|
|
7
9
|
"addNewService": "Add new service",
|
|
8
10
|
"addPaymentMode": "Add Payment Mode",
|
|
9
11
|
"addPaymentOptions": "Add payment option",
|
|
10
12
|
"amount": "Amount",
|
|
11
13
|
"amountDue": "Amount Due",
|
|
14
|
+
"amountTendered": "Amount Tendered",
|
|
12
15
|
"amountToWaiveAriaLabel": "Enter amount to waive",
|
|
13
16
|
"amountToWaiveHelper": "Specify the amount to be deducted from the bill",
|
|
14
17
|
"amountToWaiveLabel": "Amount to Waive",
|
|
15
18
|
"billableService": "Billable service",
|
|
16
19
|
"billableServices": "Billable Services",
|
|
20
|
+
"billAmount": "Bill amount",
|
|
21
|
+
"billCode": "Bill code",
|
|
17
22
|
"billedItems": "Billed Items",
|
|
18
23
|
"billedTo": "Billed to",
|
|
19
24
|
"billErrorService": "Bill service error",
|
|
@@ -30,6 +35,8 @@
|
|
|
30
35
|
"billPayment": "Bill payment",
|
|
31
36
|
"billPaymentError": "Bill payment error",
|
|
32
37
|
"billPaymentRequiredMessage": "The current patient has pending bill. Advice patient to settle bill before receiving services",
|
|
38
|
+
"billProcessingError": "Bill processing error",
|
|
39
|
+
"billProcessingSuccess": "Bill processing has been successful",
|
|
33
40
|
"billServicesManagement": "Bill services management",
|
|
34
41
|
"billsList": "Bill list",
|
|
35
42
|
"billTotal": "Bill total",
|
|
@@ -51,12 +58,15 @@
|
|
|
51
58
|
"confirmDeleteMessage": "Are you sure you want to delete this payment mode? Proceed cautiously.",
|
|
52
59
|
"createdSuccessfully": "Billable service created successfully",
|
|
53
60
|
"currentPrice": "Current price",
|
|
61
|
+
"date": "Date",
|
|
62
|
+
"dateOfPayment": "Date of payment",
|
|
54
63
|
"delete": "Delete",
|
|
55
64
|
"deletePaymentMode": "Delete Payment Mode",
|
|
56
65
|
"description": "Description",
|
|
57
66
|
"descriptionPlaceholder": "e.g., Used for all cash transactions",
|
|
58
67
|
"discard": "Discard",
|
|
59
68
|
"discount": "Discount",
|
|
69
|
+
"discountAmount": "Discount Amount",
|
|
60
70
|
"duplicateCashPointError": "A cash point with the same name or UUID already exists. Please use a unique name and UUID.",
|
|
61
71
|
"duplicatePaymentModeError": "A payment mode with the same name already exists. Please create another payment mode",
|
|
62
72
|
"editBillableService": "Edit billable service",
|
|
@@ -83,8 +93,11 @@
|
|
|
83
93
|
"inlineLoading": "Loading bill items...",
|
|
84
94
|
"insuranceScheme": "Insurance scheme",
|
|
85
95
|
"invalidWaiverAmount": "Invalid waiver amount",
|
|
96
|
+
"inventoryItem": "Inventory item",
|
|
86
97
|
"invoice": "Invoice",
|
|
98
|
+
"invoiceDate": "Invoice date",
|
|
87
99
|
"invoiceError": "Invoice error",
|
|
100
|
+
"invoiceNumber": "Invoice #",
|
|
88
101
|
"item": "Item",
|
|
89
102
|
"itemsToBeBilled": "Items to be billed",
|
|
90
103
|
"launchBillForm": "Launch bill form",
|
|
@@ -103,6 +116,7 @@
|
|
|
103
116
|
"noResultsFor": "No results for",
|
|
104
117
|
"noResultsFound": "No results found",
|
|
105
118
|
"noServicesToDisplay": "There are no services to display",
|
|
119
|
+
"number": "No",
|
|
106
120
|
"ok": "OK",
|
|
107
121
|
"patientBillingAlert": "Patient Billing Alert",
|
|
108
122
|
"patientBills": "Patient bill",
|
|
@@ -127,6 +141,7 @@
|
|
|
127
141
|
"priceIsRequired": "Price is required",
|
|
128
142
|
"prices": "Prices",
|
|
129
143
|
"printBill": "Print bill",
|
|
144
|
+
"printError": "Error printing invoice",
|
|
130
145
|
"printReceipt": "Print receipt",
|
|
131
146
|
"processPayment": "Process Payment",
|
|
132
147
|
"quantity": "Quantity",
|
|
@@ -135,6 +150,7 @@
|
|
|
135
150
|
"referenceNumber": "Reference number",
|
|
136
151
|
"save": "Save",
|
|
137
152
|
"saveAndClose": "Save and close",
|
|
153
|
+
"saveBill": "Save Bill",
|
|
138
154
|
"saving": "Saving",
|
|
139
155
|
"searchConcepts": "Search associated concept",
|
|
140
156
|
"searching": "Searching",
|
|
@@ -142,6 +158,7 @@
|
|
|
142
158
|
"searchThisTable": "Search this table",
|
|
143
159
|
"selectBillableService": "Select a billable service...",
|
|
144
160
|
"selectCategory": "Select category",
|
|
161
|
+
"selectLocation": "Select Location",
|
|
145
162
|
"selectPatientCategory": "Select patient category",
|
|
146
163
|
"selectPaymentMethod": "Select payment method",
|
|
147
164
|
"sellingAmount": "Enter selling price",
|
|
@@ -152,6 +169,7 @@
|
|
|
152
169
|
"serviceNameExceedsLimit": "Service Name exceeds the character limit of {{MAX_NAME_LENGTH}}.",
|
|
153
170
|
"serviceShortName": "Short Name",
|
|
154
171
|
"servicesList": "Services list",
|
|
172
|
+
"serviceStatus": "Service Status",
|
|
155
173
|
"serviceType": "Service Type",
|
|
156
174
|
"shortName": "Short Name",
|
|
157
175
|
"shortNameExceedsLimit": "Short Name exceeds the character limit of {{MAX_NAME_LENGTH}}.",
|