@openmrs/esm-billing-app 1.1.2-pre.9 → 1.2.0
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/cache/31f1dfc7f71601df-meta.json +1 -0
- package/.turbo/cache/31f1dfc7f71601df.tar.zst +0 -0
- package/.turbo/turbo-build.log +13 -42
- package/__mocks__/bills.mock.ts +3 -2
- package/dist/1480.js +1 -0
- package/dist/1480.js.map +1 -0
- package/dist/1564.js +1 -0
- package/dist/1564.js.map +1 -0
- package/dist/1578.js +1 -0
- package/dist/1578.js.map +1 -0
- package/dist/1646.js +1 -0
- package/dist/1646.js.map +1 -0
- package/dist/1869.js +1 -0
- package/dist/1869.js.map +1 -0
- package/dist/1877.js +1 -0
- package/dist/1877.js.map +1 -0
- package/dist/1899.js +1 -0
- package/dist/1899.js.map +1 -0
- package/dist/196.js +2 -0
- package/dist/196.js.map +1 -0
- package/dist/2250.js +43 -0
- package/dist/2250.js.map +1 -0
- package/dist/2269.js +1 -0
- package/dist/2269.js.map +1 -0
- package/dist/2317.js +1 -0
- package/dist/2317.js.map +1 -0
- package/dist/2416.js +1 -0
- package/dist/2416.js.map +1 -0
- package/dist/2489.js +1 -0
- package/dist/2489.js.map +1 -0
- package/dist/282.js +1 -0
- package/dist/282.js.map +1 -0
- package/dist/2881.js +1 -0
- package/dist/2881.js.map +1 -0
- package/dist/2997.js +1 -0
- package/dist/2997.js.map +1 -0
- package/dist/3378.js +1 -0
- package/dist/3378.js.map +1 -0
- package/dist/3379.js +1 -0
- package/dist/3379.js.map +1 -0
- package/dist/3784.js +1 -0
- package/dist/3784.js.map +1 -0
- package/dist/3963.js +1 -0
- package/dist/3963.js.map +1 -0
- package/dist/4106.js +1 -0
- package/dist/4106.js.map +1 -0
- package/dist/4111.js +1 -0
- package/dist/4111.js.map +1 -0
- package/dist/434.js +1 -0
- package/dist/434.js.map +1 -0
- package/dist/4348.js +1 -0
- package/dist/4348.js.map +1 -0
- package/dist/4383.js +1 -0
- package/dist/4383.js.map +1 -0
- package/dist/4658.js +1 -0
- package/dist/4658.js.map +1 -0
- package/dist/4870.js +1 -0
- package/dist/4870.js.map +1 -0
- package/dist/4928.js +1 -0
- package/dist/4928.js.map +1 -0
- package/dist/5098.js +1 -0
- package/dist/5098.js.map +1 -0
- package/dist/5117.js +1 -0
- package/dist/5117.js.map +1 -0
- package/dist/5132.js +1 -0
- package/dist/5132.js.map +1 -0
- package/dist/5145.js +1 -0
- package/dist/5145.js.map +1 -0
- package/dist/5390.js +1 -0
- package/dist/5390.js.map +1 -0
- package/dist/5503.js +1 -0
- package/dist/5503.js.map +1 -0
- package/dist/556.js +1 -0
- package/dist/556.js.map +1 -0
- package/dist/5644.js +1 -0
- package/dist/5644.js.map +1 -0
- package/dist/5898.js +1 -0
- package/dist/5898.js.map +1 -0
- package/dist/5940.js +1 -0
- package/dist/5940.js.map +1 -0
- package/dist/6047.js +1 -0
- package/dist/6047.js.map +1 -0
- package/dist/6237.js +1 -0
- package/dist/6237.js.map +1 -0
- package/dist/6362.js +1 -0
- package/dist/6362.js.map +1 -0
- package/dist/6371.js +1 -0
- package/dist/6371.js.map +1 -0
- package/dist/6377.js +1 -0
- package/dist/6377.js.map +1 -0
- package/dist/6444.js +1 -0
- package/dist/6444.js.map +1 -0
- package/dist/6508.js +1 -0
- package/dist/6508.js.map +1 -0
- package/dist/6594.js +1 -0
- package/dist/6594.js.map +1 -0
- package/dist/6724.js +1 -0
- package/dist/6724.js.map +1 -0
- package/dist/6904.js +1 -0
- package/dist/6904.js.map +1 -0
- package/dist/7045.js +1 -0
- package/dist/7045.js.map +1 -0
- package/dist/7175.js +1 -0
- package/dist/7175.js.map +1 -0
- package/dist/7182.js +1 -0
- package/dist/7182.js.map +1 -0
- package/dist/7247.js +1 -0
- package/dist/7247.js.map +1 -0
- package/dist/7742.js +1 -0
- package/dist/7742.js.map +1 -0
- package/dist/7912.js +1 -0
- package/dist/7912.js.map +1 -0
- package/dist/8358.js +1 -0
- package/dist/8358.js.map +1 -0
- package/dist/8359.js +1 -0
- package/dist/8359.js.map +1 -0
- package/dist/8695.js +1 -0
- package/dist/8695.js.map +1 -0
- package/dist/903.js +1 -0
- package/dist/903.js.map +1 -0
- package/dist/9072.js +1 -0
- package/dist/9072.js.map +1 -0
- package/dist/9414.js +1 -0
- package/dist/9414.js.map +1 -0
- package/dist/9655.js +11 -0
- package/dist/9655.js.map +1 -0
- package/dist/9806.js +1 -0
- package/dist/9806.js.map +1 -0
- package/dist/990.js +1 -0
- package/dist/990.js.map +1 -0
- package/dist/main.js +17 -2
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-billing-app.js +6 -1
- package/dist/openmrs-esm-billing-app.js.buildmanifest.json +643 -436
- package/dist/openmrs-esm-billing-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/e2e/commands/billing-operations.ts +21 -0
- package/e2e/commands/types.ts +9 -1
- package/e2e/pages/discounts-page.ts +75 -0
- package/e2e/pages/index.ts +1 -0
- package/e2e/pages/invoice-page.ts +7 -7
- package/e2e/specs/bill-discounts.spec.ts +255 -0
- package/e2e/specs/billing-dashboard.spec.ts +3 -3
- package/e2e/specs/billing-patient-chart.spec.ts +2 -2
- package/package.json +13 -22
- package/rspack.config.js +1 -0
- package/src/bill-history/bill-action-menu.component.tsx +20 -2
- package/src/bill-history/bill-history.test.tsx +23 -22
- package/src/bill-item-actions/edit-bill-item.modal.tsx +1 -1
- package/src/bill-item-actions/edit-bill-item.test.tsx +29 -27
- package/src/billable-services/billable-service-form/billable-service-form.test.tsx +74 -73
- package/src/billable-services/billable-services-home.component.tsx +4 -2
- package/src/billable-services/billable-services.test.tsx +8 -7
- package/src/billable-services/dashboard/dashboard.test.tsx +3 -2
- package/src/billable-services-admin-card-link.test.tsx +2 -1
- package/src/billing-dashboard/billing-dashboard.test.tsx +19 -3
- package/src/billing-form/billing-checkin-form.component.tsx +7 -3
- package/src/billing-form/billing-checkin-form.test.tsx +22 -21
- package/src/billing-form/billing-form.resource.test.ts +7 -6
- package/src/billing-form/billing-form.test.tsx +77 -40
- package/src/billing-form/billing-form.workspace.tsx +25 -6
- package/src/billing-form/visit-attributes/visit-attributes-form.component.tsx +6 -2
- package/src/billing.resource.test.ts +43 -41
- package/src/billing.resource.ts +65 -16
- package/src/bills-table/bills-table.component.tsx +15 -4
- package/src/bills-table/bills-table.test.tsx +72 -71
- package/src/config-schema.ts +0 -7
- package/src/discounts/admin/discount-requests-left-panel-link.component.tsx +43 -0
- package/src/discounts/admin/discount-requests.component.tsx +316 -0
- package/src/discounts/admin/discount-requests.scss +133 -0
- package/src/discounts/admin/discount-requests.test.tsx +104 -0
- package/src/discounts/admin/review-bill-discounts/bill-line-items-table/bill-line-items-table.component.tsx +42 -0
- package/src/discounts/admin/review-bill-discounts/bill-line-items-table/bill-line-items-table.scss +76 -0
- package/src/discounts/admin/review-bill-discounts/bill-payments-table/bill-payments-table.component.tsx +50 -0
- package/src/discounts/admin/review-bill-discounts/bill-payments-table/bill-payments-table.scss +63 -0
- package/src/discounts/admin/review-bill-discounts/bill-receipt-rail/bill-receipt-rail.component.tsx +73 -0
- package/src/discounts/admin/review-bill-discounts/bill-receipt-rail/bill-receipt-rail.scss +54 -0
- package/src/discounts/admin/review-bill-discounts/bill-totals-summary/bill-totals-summary.component.tsx +95 -0
- package/src/discounts/admin/review-bill-discounts/bill-totals-summary/bill-totals-summary.scss +128 -0
- package/src/discounts/admin/review-bill-discounts/discount-card/discount-card.component.tsx +158 -0
- package/src/discounts/admin/review-bill-discounts/discount-card/discount-card.scss +164 -0
- package/src/discounts/admin/review-bill-discounts/discount-review-stack/discount-review-stack.component.tsx +86 -0
- package/src/discounts/admin/review-bill-discounts/discount-review-stack/discount-review-stack.scss +40 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.scss +14 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.test.tsx +153 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.tsx +167 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.utils.ts +42 -0
- package/src/discounts/discounts-table.component.tsx +109 -0
- package/src/discounts/discounts-table.scss +37 -0
- package/src/discounts/discounts-table.test.tsx +67 -0
- package/src/discounts/discounts.resource.ts +71 -0
- package/src/discounts/request-discount.modal.scss +88 -0
- package/src/discounts/request-discount.modal.test.tsx +161 -0
- package/src/discounts/request-discount.modal.tsx +253 -0
- package/src/index.ts +52 -21
- package/src/invoice/invoice-table.component.tsx +116 -18
- package/src/invoice/invoice-table.test.tsx +165 -13
- package/src/invoice/invoice.component.tsx +111 -7
- package/src/invoice/invoice.test.tsx +366 -66
- package/src/invoice/line-item-action-menu.component.tsx +31 -1
- package/src/invoice/payments/payment-form/payment-form.test.tsx +20 -19
- package/src/invoice/payments/payment-history/payment-history.test.tsx +13 -10
- package/src/invoice/payments/payments.component.tsx +20 -6
- package/src/invoice/payments/payments.test.tsx +88 -23
- package/src/invoice/printable-invoice/print-receipt.test.tsx +10 -28
- package/src/invoice/printable-invoice/printable-footer.test.tsx +5 -4
- package/src/invoice/printable-invoice/printable-invoice-header.component.tsx +3 -3
- package/src/invoice/printable-invoice/printable-invoice-header.test.tsx +26 -11
- package/src/invoice/printable-invoice/printable-invoice.component.tsx +38 -15
- package/src/left-panel-link.test.tsx +3 -3
- package/src/metrics-cards/metrics-cards.test.tsx +11 -10
- package/src/modal/delete-bill-confirmation.modal.test.tsx +134 -0
- package/src/modal/delete-bill-confirmation.modal.tsx +98 -0
- package/src/modal/delete-line-item-confirmation.modal.test.tsx +11 -9
- package/src/modal/finalize-bill-confirmation.modal.test.tsx +10 -8
- package/src/modal/require-payment-modal.test.tsx +12 -11
- package/src/payment-status-tag/payment-status-tag.component.tsx +50 -0
- package/src/payment-status-tag/payment-status-tag.scss +6 -0
- package/src/payment-status-tag/payment-status-tag.test.tsx +113 -0
- package/src/refunds/admin/refund-requests-left-panel-link.component.tsx +43 -0
- package/src/refunds/admin/refund-requests.component.tsx +324 -0
- package/src/refunds/admin/refund-requests.scss +133 -0
- package/src/refunds/admin/refund-requests.test.tsx +99 -0
- package/src/refunds/admin/review-bill-refunds/bill-line-items-table/bill-line-items-table.component.tsx +42 -0
- package/src/refunds/admin/review-bill-refunds/bill-line-items-table/bill-line-items-table.scss +76 -0
- package/src/refunds/admin/review-bill-refunds/bill-payments-table/bill-payments-table.component.tsx +50 -0
- package/src/refunds/admin/review-bill-refunds/bill-payments-table/bill-payments-table.scss +63 -0
- package/src/refunds/admin/review-bill-refunds/bill-receipt-rail/bill-receipt-rail.component.tsx +84 -0
- package/src/refunds/admin/review-bill-refunds/bill-receipt-rail/bill-receipt-rail.scss +54 -0
- package/src/refunds/admin/review-bill-refunds/bill-totals-summary/bill-totals-summary.component.tsx +83 -0
- package/src/refunds/admin/review-bill-refunds/bill-totals-summary/bill-totals-summary.scss +65 -0
- package/src/refunds/admin/review-bill-refunds/refund-card/refund-card.component.tsx +170 -0
- package/src/refunds/admin/review-bill-refunds/refund-card/refund-card.scss +155 -0
- package/src/refunds/admin/review-bill-refunds/refund-review-stack/refund-review-stack.component.tsx +86 -0
- package/src/refunds/admin/review-bill-refunds/refund-review-stack/refund-review-stack.scss +40 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.scss +14 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.test.tsx +313 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.tsx +188 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.utils.ts +66 -0
- package/src/refunds/refunds-table.component.tsx +137 -0
- package/src/refunds/refunds-table.scss +37 -0
- package/src/refunds/refunds-table.test.tsx +105 -0
- package/src/refunds/refunds.resource.test.ts +44 -0
- package/src/refunds/refunds.resource.ts +42 -0
- package/src/refunds/refunds.types.test.ts +15 -0
- package/src/refunds/request-refund.modal.scss +84 -0
- package/src/refunds/request-refund.modal.test.tsx +204 -0
- package/src/refunds/request-refund.modal.tsx +218 -0
- package/src/routes.json +36 -2
- package/src/types/index.ts +116 -1
- package/src/visit-bills/visit-bills-panel.component.tsx +151 -0
- package/src/visit-bills/visit-bills-panel.scss +31 -0
- package/src/visit-bills/visit-bills-panel.test.tsx +113 -0
- package/tools/empty-module.ts +1 -0
- package/tools/setup-tests.ts +9 -9
- package/translations/am.json +154 -16
- package/translations/ar.json +154 -16
- package/translations/ar_SY.json +154 -16
- package/translations/bn.json +154 -16
- package/translations/cs.json +154 -16
- package/translations/de.json +154 -16
- package/translations/en.json +154 -16
- package/translations/en_US.json +154 -16
- package/translations/es.json +154 -16
- package/translations/es_MX.json +154 -16
- package/translations/fr.json +154 -16
- package/translations/he.json +154 -16
- package/translations/hi.json +154 -16
- package/translations/hi_IN.json +154 -16
- package/translations/id.json +154 -16
- package/translations/it.json +154 -16
- package/translations/ka.json +154 -16
- package/translations/km.json +154 -16
- package/translations/ku.json +154 -16
- package/translations/ky.json +154 -16
- package/translations/lg.json +154 -16
- package/translations/ne.json +154 -16
- package/translations/pl.json +154 -16
- package/translations/pt.json +154 -16
- package/translations/pt_BR.json +154 -16
- package/translations/qu.json +154 -16
- package/translations/ro_RO.json +154 -16
- package/translations/ru_RU.json +154 -16
- package/translations/si.json +154 -16
- package/translations/sq.json +154 -16
- package/translations/sw.json +154 -16
- package/translations/sw_KE.json +154 -16
- package/translations/tr.json +154 -16
- package/translations/tr_TR.json +154 -16
- package/translations/uk.json +154 -16
- package/translations/uz.json +154 -16
- package/translations/uz@Latn.json +154 -16
- package/translations/uz_UZ.json +154 -16
- package/translations/vi.json +154 -16
- package/translations/zh.json +154 -16
- package/translations/zh_CN.json +179 -41
- package/translations/zh_TW.json +154 -16
- package/tsconfig.json +3 -3
- package/vitest.config.js +28 -0
- package/.turbo/cache/4e30f71f570fc412-meta.json +0 -1
- package/.turbo/cache/4e30f71f570fc412.tar.zst +0 -0
- package/dist/1119.js +0 -1
- package/dist/1197.js +0 -1
- package/dist/1435.js +0 -1
- package/dist/1435.js.map +0 -1
- package/dist/1807.js +0 -1
- package/dist/1807.js.map +0 -1
- package/dist/2146.js +0 -1
- package/dist/2177.js +0 -2
- package/dist/2177.js.LICENSE.txt +0 -9
- package/dist/2177.js.map +0 -1
- package/dist/2690.js +0 -1
- package/dist/2704.js +0 -1
- package/dist/2704.js.map +0 -1
- package/dist/3002.js +0 -1
- package/dist/3002.js.map +0 -1
- package/dist/3041.js +0 -1
- package/dist/3041.js.map +0 -1
- package/dist/3099.js +0 -1
- package/dist/3184.js +0 -2
- package/dist/3184.js.LICENSE.txt +0 -14
- package/dist/3184.js.map +0 -1
- package/dist/3584.js +0 -1
- package/dist/4055.js +0 -1
- package/dist/4132.js +0 -1
- package/dist/4225.js +0 -1
- package/dist/4225.js.map +0 -1
- package/dist/4300.js +0 -1
- package/dist/4335.js +0 -1
- package/dist/439.js +0 -1
- package/dist/4618.js +0 -1
- package/dist/4652.js +0 -1
- package/dist/4944.js +0 -1
- package/dist/5173.js +0 -1
- package/dist/5241.js +0 -1
- package/dist/5422.js +0 -1
- package/dist/5422.js.map +0 -1
- package/dist/5442.js +0 -1
- package/dist/5661.js +0 -1
- package/dist/6022.js +0 -1
- package/dist/6404.js +0 -1
- package/dist/6404.js.map +0 -1
- package/dist/6468.js +0 -1
- package/dist/6540.js +0 -2
- package/dist/6540.js.LICENSE.txt +0 -9
- package/dist/6540.js.map +0 -1
- package/dist/6589.js +0 -1
- package/dist/6606.js +0 -1
- package/dist/6606.js.map +0 -1
- package/dist/6679.js +0 -1
- package/dist/6792.js +0 -1
- package/dist/6792.js.map +0 -1
- package/dist/6840.js +0 -1
- package/dist/6859.js +0 -1
- package/dist/7097.js +0 -1
- package/dist/7159.js +0 -1
- package/dist/723.js +0 -1
- package/dist/7255.js +0 -1
- package/dist/7255.js.map +0 -1
- package/dist/7617.js +0 -1
- package/dist/795.js +0 -1
- package/dist/8163.js +0 -1
- package/dist/8341.js +0 -2
- package/dist/8341.js.LICENSE.txt +0 -52
- package/dist/8341.js.map +0 -1
- package/dist/8349.js +0 -1
- package/dist/8371.js +0 -1
- package/dist/8421.js +0 -1
- package/dist/8421.js.map +0 -1
- package/dist/8618.js +0 -1
- package/dist/890.js +0 -1
- package/dist/9214.js +0 -1
- package/dist/9538.js +0 -1
- package/dist/9569.js +0 -1
- package/dist/961.js +0 -2
- package/dist/961.js.LICENSE.txt +0 -19
- package/dist/961.js.map +0 -1
- package/dist/986.js +0 -1
- package/dist/9879.js +0 -1
- package/dist/9895.js +0 -1
- package/dist/9900.js +0 -1
- package/dist/9913.js +0 -1
- package/dist/main.js.LICENSE.txt +0 -62
- package/src/billable-services/bill-waiver/bill-selection.component.tsx +0 -76
- package/src/billable-services/bill-waiver/bill-waiver-form.component.tsx +0 -107
- package/src/billable-services/bill-waiver/bill-waiver-form.scss +0 -34
- package/src/billable-services/bill-waiver/bill-waiver.component.tsx +0 -34
- package/src/billable-services/bill-waiver/bill-waiver.scss +0 -10
- package/src/billable-services/bill-waiver/patient-bills.component.tsx +0 -134
- package/webpack.config.js +0 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React, { useCallback, useState, useMemo, useEffect, useRef } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { useSWRConfig } from 'swr';
|
|
3
4
|
import { Dropdown, InlineLoading, InlineNotification } from '@carbon/react';
|
|
4
5
|
import { showSnackbar, getCoreTranslation, useConfig } from '@openmrs/esm-framework';
|
|
5
6
|
import { useCashPoint, useBillableItems, createPatientBill, useLastVisitInfo } from './billing-form.resource';
|
|
6
7
|
import VisitAttributesForm from './visit-attributes/visit-attributes-form.component';
|
|
7
|
-
import { BillStatus } from '../types';
|
|
8
|
+
import { BillLineItemStatus, BillStatus } from '../types';
|
|
9
|
+
import { patientPaymentStatusCacheKey } from '../billing.resource';
|
|
8
10
|
import styles from './billing-checkin-form.scss';
|
|
9
11
|
|
|
10
12
|
type BillingCheckInFormProps = {
|
|
@@ -14,6 +16,7 @@ type BillingCheckInFormProps = {
|
|
|
14
16
|
|
|
15
17
|
const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, setExtraVisitInfo }) => {
|
|
16
18
|
const { t } = useTranslation();
|
|
19
|
+
const { mutate } = useSWRConfig();
|
|
17
20
|
const { categoryConcepts } = useConfig();
|
|
18
21
|
|
|
19
22
|
const { lastVisitInfo, isLoading: isLoadingLastVisitInfo, error: lastVisitError } = useLastVisitInfo(patientUuid);
|
|
@@ -66,6 +69,7 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
|
|
|
66
69
|
async (createBillPayload) => {
|
|
67
70
|
try {
|
|
68
71
|
await createPatientBill(createBillPayload);
|
|
72
|
+
mutate(patientPaymentStatusCacheKey(patientUuid));
|
|
69
73
|
showSnackbar({
|
|
70
74
|
title: t('patientBill', 'Patient bill'),
|
|
71
75
|
subtitle: t('billCreatedSuccessfully', 'Bill created successfully'),
|
|
@@ -79,7 +83,7 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
|
|
|
79
83
|
});
|
|
80
84
|
}
|
|
81
85
|
},
|
|
82
|
-
[t],
|
|
86
|
+
[mutate, t, patientUuid],
|
|
83
87
|
);
|
|
84
88
|
|
|
85
89
|
const handleBillingService = useCallback(
|
|
@@ -102,7 +106,7 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
|
|
|
102
106
|
priceName: 'Default',
|
|
103
107
|
priceUuid: priceForPaymentMode ? priceForPaymentMode.uuid : '',
|
|
104
108
|
lineItemOrder: 0,
|
|
105
|
-
|
|
109
|
+
status: BillLineItemStatus.PENDING,
|
|
106
110
|
},
|
|
107
111
|
],
|
|
108
112
|
cashPoint: cashPointUuid,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
3
|
import userEvent from '@testing-library/user-event';
|
|
3
4
|
import { screen, render } from '@testing-library/react';
|
|
4
5
|
import { useConfig } from '@openmrs/esm-framework';
|
|
@@ -6,11 +7,11 @@ import { type BillingConfig } from '../config-schema';
|
|
|
6
7
|
import { useBillableItems, useCashPoint, usePaymentMethods, useLastVisitInfo } from './billing-form.resource';
|
|
7
8
|
import BillingCheckInForm from './billing-checkin-form.component';
|
|
8
9
|
|
|
9
|
-
const mockUseConfig =
|
|
10
|
-
const mockUseCashPoint =
|
|
11
|
-
const mockUseBillableItems =
|
|
12
|
-
const mockUsePaymentMethods =
|
|
13
|
-
const mockUseLastVisitInfo =
|
|
10
|
+
const mockUseConfig = vi.mocked(useConfig<BillingConfig>);
|
|
11
|
+
const mockUseCashPoint = vi.mocked(useCashPoint);
|
|
12
|
+
const mockUseBillableItems = vi.mocked(useBillableItems);
|
|
13
|
+
const mockUsePaymentMethods = vi.mocked(usePaymentMethods);
|
|
14
|
+
const mockUseLastVisitInfo = vi.mocked(useLastVisitInfo);
|
|
14
15
|
|
|
15
16
|
const mockCashPoints = [
|
|
16
17
|
{
|
|
@@ -85,19 +86,19 @@ const mockPaymentMethods = [
|
|
|
85
86
|
},
|
|
86
87
|
];
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
useBillableItems:
|
|
90
|
-
useCashPoint:
|
|
91
|
-
createPatientBill:
|
|
92
|
-
usePaymentMethods:
|
|
93
|
-
useLastVisitInfo:
|
|
89
|
+
vi.mock('./billing-form.resource', () => ({
|
|
90
|
+
useBillableItems: vi.fn(),
|
|
91
|
+
useCashPoint: vi.fn(),
|
|
92
|
+
createPatientBill: vi.fn(),
|
|
93
|
+
usePaymentMethods: vi.fn(),
|
|
94
|
+
useLastVisitInfo: vi.fn(),
|
|
94
95
|
}));
|
|
95
96
|
|
|
96
|
-
const testProps = { patientUuid: 'some-patient-uuid', setExtraVisitInfo:
|
|
97
|
+
const testProps = { patientUuid: 'some-patient-uuid', setExtraVisitInfo: vi.fn() };
|
|
97
98
|
|
|
98
99
|
describe('BillingCheckInForm', () => {
|
|
99
100
|
beforeEach(() => {
|
|
100
|
-
|
|
101
|
+
vi.resetAllMocks();
|
|
101
102
|
mockUseConfig.mockReturnValue({
|
|
102
103
|
patientCategory: {
|
|
103
104
|
paymentDetails: 'fbc0702d-b4c9-4968-be63-af8ad3ad6239',
|
|
@@ -121,7 +122,7 @@ describe('BillingCheckInForm', () => {
|
|
|
121
122
|
mockUseLastVisitInfo.mockReturnValue({ lastVisitInfo: null, isLoading: false, error: null });
|
|
122
123
|
});
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
it('should show the loading spinner while retrieving data', () => {
|
|
125
126
|
mockUseBillableItems.mockReturnValueOnce({ lineItems: [], isLoading: true, error: null });
|
|
126
127
|
mockUseCashPoint.mockReturnValueOnce({ cashPoints: [], isLoading: true, error: null });
|
|
127
128
|
renderBillingCheckinForm();
|
|
@@ -129,7 +130,7 @@ describe('BillingCheckInForm', () => {
|
|
|
129
130
|
expect(screen.getByText(/Loading billing services.../)).toBeInTheDocument();
|
|
130
131
|
});
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
it('should show error state when an error occurs while fetching data', () => {
|
|
133
134
|
const error = new Error('Internal server error');
|
|
134
135
|
mockUseBillableItems.mockReturnValueOnce({ lineItems: [], isLoading: false, error });
|
|
135
136
|
mockUseCashPoint.mockReturnValueOnce({ cashPoints: [], isLoading: false, error });
|
|
@@ -139,7 +140,7 @@ describe('BillingCheckInForm', () => {
|
|
|
139
140
|
expect(screen.getByText(/error loading bill services/i)).toBeInTheDocument();
|
|
140
141
|
});
|
|
141
142
|
|
|
142
|
-
|
|
143
|
+
it('should show the last visit banner when last visit info is available', () => {
|
|
143
144
|
mockUseBillableItems.mockReturnValue({ lineItems: [], isLoading: false, error: null });
|
|
144
145
|
mockUseCashPoint.mockReturnValue({ cashPoints: [], isLoading: false, error: null });
|
|
145
146
|
mockUseLastVisitInfo.mockReturnValue({
|
|
@@ -153,7 +154,7 @@ describe('BillingCheckInForm', () => {
|
|
|
153
154
|
expect(screen.getByText(/3 days ago/i)).toBeInTheDocument();
|
|
154
155
|
});
|
|
155
156
|
|
|
156
|
-
|
|
157
|
+
it('should not show the last visit banner when there is no recent visit', () => {
|
|
157
158
|
mockUseBillableItems.mockReturnValue({ lineItems: [], isLoading: false, error: null });
|
|
158
159
|
mockUseCashPoint.mockReturnValue({ cashPoints: [], isLoading: false, error: null });
|
|
159
160
|
mockUseLastVisitInfo.mockReturnValue({ lastVisitInfo: null, isLoading: false, error: null });
|
|
@@ -162,7 +163,7 @@ describe('BillingCheckInForm', () => {
|
|
|
162
163
|
expect(screen.queryByText(/Last Visit Information/i)).not.toBeInTheDocument();
|
|
163
164
|
});
|
|
164
165
|
|
|
165
|
-
|
|
166
|
+
it('should show billable service dropdown when a paying method is selected', async () => {
|
|
166
167
|
const user = userEvent.setup();
|
|
167
168
|
mockUseCashPoint.mockReturnValue({ cashPoints: mockCashPoints, isLoading: false, error: null });
|
|
168
169
|
mockUseBillableItems.mockReturnValue({ lineItems: mockBillableItems, isLoading: false, error: null });
|
|
@@ -176,7 +177,7 @@ describe('BillingCheckInForm', () => {
|
|
|
176
177
|
expect(screen.getByRole('combobox', { name: /billable service/i })).toBeInTheDocument();
|
|
177
178
|
});
|
|
178
179
|
|
|
179
|
-
|
|
180
|
+
it('should hide billable service dropdown when switched to non-paying', async () => {
|
|
180
181
|
const user = userEvent.setup();
|
|
181
182
|
mockUseCashPoint.mockReturnValue({ cashPoints: mockCashPoints, isLoading: false, error: null });
|
|
182
183
|
mockUseBillableItems.mockReturnValue({ lineItems: mockBillableItems, isLoading: false, error: null });
|
|
@@ -186,7 +187,7 @@ describe('BillingCheckInForm', () => {
|
|
|
186
187
|
expect(screen.queryByRole('combobox', { name: /billable service/i })).not.toBeInTheDocument();
|
|
187
188
|
});
|
|
188
189
|
|
|
189
|
-
|
|
190
|
+
it('should render the form correctly and generate the required payload', async () => {
|
|
190
191
|
const user = userEvent.setup();
|
|
191
192
|
mockUseCashPoint.mockReturnValue({ cashPoints: mockCashPoints, isLoading: false, error: null });
|
|
192
193
|
mockUseBillableItems.mockReturnValue({ lineItems: mockBillableItems, isLoading: false, error: null });
|
|
@@ -229,7 +230,7 @@ describe('BillingCheckInForm', () => {
|
|
|
229
230
|
priceName: 'Default',
|
|
230
231
|
priceUuid: 'price-2',
|
|
231
232
|
lineItemOrder: 0,
|
|
232
|
-
|
|
233
|
+
status: 'PENDING',
|
|
233
234
|
},
|
|
234
235
|
],
|
|
235
236
|
cashPoint: '54065383-b4d4-42d2-af4d-d250a1fd2590',
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import useSWR from 'swr';
|
|
3
|
+
import { renderHook } from '@testing-library/react';
|
|
3
4
|
import { useLastVisitInfo } from './billing-form.resource';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
const mockUseSWR =
|
|
6
|
+
vi.mock('swr');
|
|
7
|
+
const mockUseSWR = vi.mocked(useSWR);
|
|
7
8
|
|
|
8
9
|
// Pin "now" so diffDays calculations are deterministic
|
|
9
10
|
const FIXED_NOW = new Date('2026-01-10T12:00:00Z').getTime();
|
|
10
11
|
|
|
11
12
|
describe('useLastVisitInfo', () => {
|
|
12
13
|
beforeAll(() => {
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
vi.useFakeTimers();
|
|
15
|
+
vi.setSystemTime(FIXED_NOW);
|
|
15
16
|
});
|
|
16
17
|
|
|
17
18
|
afterAll(() => {
|
|
18
|
-
|
|
19
|
+
vi.useRealTimers();
|
|
19
20
|
});
|
|
20
21
|
|
|
21
22
|
it('returns null lastVisitInfo when there is no visit data yet', () => {
|
|
@@ -1,42 +1,46 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
3
|
import userEvent from '@testing-library/user-event';
|
|
3
4
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
4
|
-
import { getDefaultsFromConfigSchema, showSnackbar, useConfig } from '@openmrs/esm-framework';
|
|
5
|
+
import { getDefaultsFromConfigSchema, showSnackbar, useConfig, useVisit } from '@openmrs/esm-framework';
|
|
5
6
|
import { configSchema, type BillingConfig } from '../config-schema';
|
|
6
7
|
import { processBillItems, updateBillItems, useBill, useBillableServices } from '../billing.resource';
|
|
8
|
+
import { type BillLineItemStatus, type BillStatus } from '../types';
|
|
7
9
|
import { useBillableServices as useBillableServicesList } from '../billable-services/billable-service.resource';
|
|
8
10
|
import { getBillableServiceUuid } from '../invoice/payments/utils';
|
|
9
11
|
import BillingForm from './billing-form.workspace';
|
|
10
12
|
|
|
11
|
-
const mockUseConfig =
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
const mockUseConfig = vi.mocked(useConfig<BillingConfig>);
|
|
14
|
+
const mockUseVisit = vi.mocked(useVisit);
|
|
15
|
+
const mockUseBillableServices = vi.mocked(useBillableServices);
|
|
16
|
+
const mockUseBill = vi.mocked(useBill);
|
|
17
|
+
const mockUseBillableServicesList = vi.mocked(useBillableServicesList);
|
|
18
|
+
const mockProcessBillItems = vi.mocked(processBillItems);
|
|
19
|
+
const mockUpdateBillItems = vi.mocked(updateBillItems);
|
|
20
|
+
const mockGetBillableServiceUuid = vi.mocked(getBillableServiceUuid);
|
|
21
|
+
const mockShowSnackbar = vi.mocked(showSnackbar);
|
|
22
|
+
|
|
23
|
+
vi.mock('../billing.resource', () => ({
|
|
24
|
+
processBillItems: vi.fn().mockResolvedValue({}),
|
|
25
|
+
updateBillItems: vi.fn().mockResolvedValue({}),
|
|
26
|
+
useBill: vi.fn(),
|
|
27
|
+
useBillableServices: vi.fn(),
|
|
28
|
+
patientPaymentStatusCacheKey: vi.fn().mockReturnValue('mocked-cache-key'),
|
|
25
29
|
}));
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
useBillableServices:
|
|
31
|
+
vi.mock('../billable-services/billable-service.resource', () => ({
|
|
32
|
+
useBillableServices: vi.fn(),
|
|
29
33
|
}));
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
getBillableServiceUuid:
|
|
35
|
+
vi.mock('../invoice/payments/utils', () => ({
|
|
36
|
+
getBillableServiceUuid: vi.fn(),
|
|
33
37
|
}));
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
calculateTotalAmount:
|
|
39
|
+
vi.mock('../helpers/functions', () => ({
|
|
40
|
+
calculateTotalAmount: vi.fn((items) =>
|
|
37
41
|
Array.isArray(items) ? items.reduce((sum, item) => sum + item.price * item.quantity, 0) : 0,
|
|
38
42
|
),
|
|
39
|
-
convertToCurrency:
|
|
43
|
+
convertToCurrency: vi.fn((amount) => `KES ${amount}`),
|
|
40
44
|
}));
|
|
41
45
|
|
|
42
46
|
window.i18next = {
|
|
@@ -65,7 +69,7 @@ const mockExistingBill = {
|
|
|
65
69
|
uuid: 'bill-123',
|
|
66
70
|
patientUuid: 'patient-uuid',
|
|
67
71
|
patientName: 'John Doe',
|
|
68
|
-
status: 'PENDING',
|
|
72
|
+
status: 'PENDING' as BillStatus,
|
|
69
73
|
cashPointUuid: 'cashpoint-uuid',
|
|
70
74
|
cashPointName: 'Main Cashier',
|
|
71
75
|
cashPointLocation: 'Main Hospital',
|
|
@@ -80,7 +84,7 @@ const mockExistingBill = {
|
|
|
80
84
|
display: 'Hemoglobin',
|
|
81
85
|
quantity: 1,
|
|
82
86
|
price: 100,
|
|
83
|
-
|
|
87
|
+
status: 'PENDING' as BillLineItemStatus,
|
|
84
88
|
lineItemOrder: 0,
|
|
85
89
|
voided: false,
|
|
86
90
|
voidReason: null,
|
|
@@ -97,8 +101,8 @@ const mockExistingBill = {
|
|
|
97
101
|
id: 1,
|
|
98
102
|
};
|
|
99
103
|
|
|
100
|
-
const closeWorkspace =
|
|
101
|
-
const onMutate =
|
|
104
|
+
const closeWorkspace = vi.fn();
|
|
105
|
+
const onMutate = vi.fn();
|
|
102
106
|
|
|
103
107
|
const defaultCreateProps = {
|
|
104
108
|
workspaceProps: { patientUuid: 'patient-uuid', onMutate },
|
|
@@ -112,7 +116,7 @@ const editModeProps = {
|
|
|
112
116
|
|
|
113
117
|
describe('BillingForm', () => {
|
|
114
118
|
beforeEach(() => {
|
|
115
|
-
|
|
119
|
+
vi.clearAllMocks();
|
|
116
120
|
mockUseConfig.mockReturnValue({
|
|
117
121
|
...getDefaultsFromConfigSchema(configSchema),
|
|
118
122
|
defaultCurrency: 'KES',
|
|
@@ -127,16 +131,17 @@ describe('BillingForm', () => {
|
|
|
127
131
|
error: null,
|
|
128
132
|
isLoading: false,
|
|
129
133
|
isValidating: false,
|
|
130
|
-
mutate:
|
|
134
|
+
mutate: vi.fn(),
|
|
131
135
|
});
|
|
132
136
|
mockUseBillableServicesList.mockReturnValue({
|
|
133
137
|
billableServices: [{ uuid: 'bs-uuid-1', name: 'Hemoglobin' }],
|
|
134
138
|
isLoading: false,
|
|
135
139
|
isValidating: false,
|
|
136
140
|
error: null,
|
|
137
|
-
mutate:
|
|
141
|
+
mutate: vi.fn(),
|
|
138
142
|
} as any);
|
|
139
143
|
mockGetBillableServiceUuid.mockReturnValue('bs-uuid-1');
|
|
144
|
+
mockUseVisit.mockReturnValue({ activeVisit: null } as any);
|
|
140
145
|
});
|
|
141
146
|
|
|
142
147
|
describe('Create mode (no billUuid)', () => {
|
|
@@ -178,7 +183,7 @@ describe('BillingForm', () => {
|
|
|
178
183
|
billableService: 'service-1',
|
|
179
184
|
quantity: 1,
|
|
180
185
|
price: 500,
|
|
181
|
-
|
|
186
|
+
status: 'PENDING',
|
|
182
187
|
}),
|
|
183
188
|
]),
|
|
184
189
|
}),
|
|
@@ -200,7 +205,7 @@ describe('BillingForm', () => {
|
|
|
200
205
|
error: null,
|
|
201
206
|
isLoading: false,
|
|
202
207
|
isValidating: false,
|
|
203
|
-
mutate:
|
|
208
|
+
mutate: vi.fn(),
|
|
204
209
|
});
|
|
205
210
|
});
|
|
206
211
|
|
|
@@ -227,7 +232,7 @@ describe('BillingForm', () => {
|
|
|
227
232
|
error: null,
|
|
228
233
|
isLoading: true,
|
|
229
234
|
isValidating: false,
|
|
230
|
-
mutate:
|
|
235
|
+
mutate: vi.fn(),
|
|
231
236
|
});
|
|
232
237
|
render(<BillingForm {...editModeProps} />);
|
|
233
238
|
expect(screen.getByText(/loading\.\.\./i)).toBeInTheDocument();
|
|
@@ -239,7 +244,7 @@ describe('BillingForm', () => {
|
|
|
239
244
|
error: new Error('Failed to load'),
|
|
240
245
|
isLoading: false,
|
|
241
246
|
isValidating: false,
|
|
242
|
-
mutate:
|
|
247
|
+
mutate: vi.fn(),
|
|
243
248
|
});
|
|
244
249
|
render(<BillingForm {...editModeProps} />);
|
|
245
250
|
expect(screen.getByText(/error loading bill/i)).toBeInTheDocument();
|
|
@@ -277,7 +282,7 @@ describe('BillingForm', () => {
|
|
|
277
282
|
billableService: 'service-2',
|
|
278
283
|
quantity: 1,
|
|
279
284
|
price: 1000,
|
|
280
|
-
|
|
285
|
+
status: 'PENDING',
|
|
281
286
|
}),
|
|
282
287
|
]),
|
|
283
288
|
}),
|
|
@@ -411,7 +416,7 @@ describe('BillingForm', () => {
|
|
|
411
416
|
error: null,
|
|
412
417
|
isLoading: false,
|
|
413
418
|
isValidating: false,
|
|
414
|
-
mutate:
|
|
419
|
+
mutate: vi.fn(),
|
|
415
420
|
});
|
|
416
421
|
const user = userEvent.setup();
|
|
417
422
|
render(<BillingForm {...editModeProps} />);
|
|
@@ -430,7 +435,7 @@ describe('BillingForm', () => {
|
|
|
430
435
|
error: null,
|
|
431
436
|
isLoading: false,
|
|
432
437
|
isValidating: false,
|
|
433
|
-
mutate:
|
|
438
|
+
mutate: vi.fn(),
|
|
434
439
|
});
|
|
435
440
|
const user = userEvent.setup();
|
|
436
441
|
render(<BillingForm {...defaultCreateProps} />);
|
|
@@ -460,7 +465,7 @@ describe('BillingForm', () => {
|
|
|
460
465
|
error: null,
|
|
461
466
|
isLoading: false,
|
|
462
467
|
isValidating: false,
|
|
463
|
-
mutate:
|
|
468
|
+
mutate: vi.fn(),
|
|
464
469
|
});
|
|
465
470
|
|
|
466
471
|
const user = userEvent.setup();
|
|
@@ -484,7 +489,7 @@ describe('BillingForm', () => {
|
|
|
484
489
|
isLoading: true,
|
|
485
490
|
isValidating: false,
|
|
486
491
|
error: null,
|
|
487
|
-
mutate:
|
|
492
|
+
mutate: vi.fn(),
|
|
488
493
|
} as any);
|
|
489
494
|
|
|
490
495
|
render(<BillingForm {...editModeProps} />);
|
|
@@ -498,7 +503,7 @@ describe('BillingForm', () => {
|
|
|
498
503
|
isLoading: false,
|
|
499
504
|
isValidating: false,
|
|
500
505
|
error: new Error('Failed to load services'),
|
|
501
|
-
mutate:
|
|
506
|
+
mutate: vi.fn(),
|
|
502
507
|
} as any);
|
|
503
508
|
|
|
504
509
|
render(<BillingForm {...editModeProps} />);
|
|
@@ -511,7 +516,7 @@ describe('BillingForm', () => {
|
|
|
511
516
|
isLoading: false,
|
|
512
517
|
isValidating: false,
|
|
513
518
|
error: new Error('Failed to load services'),
|
|
514
|
-
mutate:
|
|
519
|
+
mutate: vi.fn(),
|
|
515
520
|
} as any);
|
|
516
521
|
|
|
517
522
|
// The error notification replaces the form content, so we can't select items.
|
|
@@ -544,4 +549,36 @@ describe('BillingForm', () => {
|
|
|
544
549
|
expect(mockUpdateBillItems).not.toHaveBeenCalled();
|
|
545
550
|
});
|
|
546
551
|
});
|
|
552
|
+
|
|
553
|
+
describe('active visit in create-bill payload', () => {
|
|
554
|
+
it('should include visit UUID in payload when an active visit exists', async () => {
|
|
555
|
+
mockUseVisit.mockReturnValue({ activeVisit: { uuid: 'visit-uuid-789' } } as any);
|
|
556
|
+
const user = userEvent.setup();
|
|
557
|
+
render(<BillingForm {...defaultCreateProps} />);
|
|
558
|
+
|
|
559
|
+
const combobox = screen.getByRole('combobox');
|
|
560
|
+
await user.click(combobox);
|
|
561
|
+
await user.click(screen.getByText('Consultation'));
|
|
562
|
+
await user.click(screen.getByRole('button', { name: /save and close/i }));
|
|
563
|
+
|
|
564
|
+
await waitFor(() => {
|
|
565
|
+
expect(mockProcessBillItems).toHaveBeenCalledWith(expect.objectContaining({ visit: 'visit-uuid-789' }));
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it('should not include visit field in payload when no active visit exists', async () => {
|
|
570
|
+
mockUseVisit.mockReturnValue({ activeVisit: null } as any);
|
|
571
|
+
const user = userEvent.setup();
|
|
572
|
+
render(<BillingForm {...defaultCreateProps} />);
|
|
573
|
+
|
|
574
|
+
const combobox = screen.getByRole('combobox');
|
|
575
|
+
await user.click(combobox);
|
|
576
|
+
await user.click(screen.getByText('Consultation'));
|
|
577
|
+
await user.click(screen.getByRole('button', { name: /save and close/i }));
|
|
578
|
+
|
|
579
|
+
await waitFor(() => {
|
|
580
|
+
expect(mockProcessBillItems).toHaveBeenCalledWith(expect.not.objectContaining({ visit: expect.anything() }));
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
});
|
|
547
584
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useMemo, useState } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { useSWRConfig } from 'swr';
|
|
3
4
|
import {
|
|
4
5
|
Button,
|
|
5
6
|
ButtonSet,
|
|
@@ -13,18 +14,32 @@ import {
|
|
|
13
14
|
import {
|
|
14
15
|
useConfig,
|
|
15
16
|
useLayoutType,
|
|
17
|
+
useVisit,
|
|
16
18
|
showSnackbar,
|
|
17
19
|
getCoreTranslation,
|
|
18
20
|
TrashCanIcon,
|
|
19
21
|
type Workspace2DefinitionProps,
|
|
20
22
|
Workspace2,
|
|
21
23
|
} from '@openmrs/esm-framework';
|
|
22
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
processBillItems,
|
|
26
|
+
updateBillItems,
|
|
27
|
+
useBill,
|
|
28
|
+
useBillableServices,
|
|
29
|
+
patientPaymentStatusCacheKey,
|
|
30
|
+
} from '../billing.resource';
|
|
23
31
|
import { useBillableServices as useBillableServicesList } from '../billable-services/billable-service.resource';
|
|
24
32
|
import { getBillableServiceUuid } from '../invoice/payments/utils';
|
|
25
33
|
import { calculateTotalAmount, convertToCurrency } from '../helpers/functions';
|
|
26
34
|
import type { BillingConfig } from '../config-schema';
|
|
27
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
BillLineItemStatus,
|
|
37
|
+
BillStatus,
|
|
38
|
+
type CreateBillPayload,
|
|
39
|
+
type BillableItem,
|
|
40
|
+
type LineItem,
|
|
41
|
+
type ServicePrice,
|
|
42
|
+
} from '../types';
|
|
28
43
|
import styles from './billing-form.scss';
|
|
29
44
|
|
|
30
45
|
interface ExtendedLineItem extends LineItem {
|
|
@@ -45,6 +60,7 @@ const BillingForm: React.FC<Workspace2DefinitionProps<BillingFormProps>> = ({
|
|
|
45
60
|
}) => {
|
|
46
61
|
const isTablet = useLayoutType() === 'tablet';
|
|
47
62
|
const { t } = useTranslation();
|
|
63
|
+
const { mutate: swrMutate } = useSWRConfig();
|
|
48
64
|
const { defaultCurrency, postBilledItems } = useConfig<BillingConfig>();
|
|
49
65
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
50
66
|
const [selectedItems, setSelectedItems] = useState<ExtendedLineItem[]>([]);
|
|
@@ -56,6 +72,7 @@ const BillingForm: React.FC<Workspace2DefinitionProps<BillingFormProps>> = ({
|
|
|
56
72
|
error: billableServicesError,
|
|
57
73
|
} = useBillableServicesList();
|
|
58
74
|
const isEditMode = !!billUuid && !!bill;
|
|
75
|
+
const { activeVisit } = useVisit(patientUuid);
|
|
59
76
|
const existingItemsTotal = useMemo(
|
|
60
77
|
() => (isEditMode ? calculateTotalAmount(bill.lineItems) : 0),
|
|
61
78
|
[isEditMode, bill?.lineItems],
|
|
@@ -101,7 +118,7 @@ const BillingForm: React.FC<Workspace2DefinitionProps<BillingFormProps>> = ({
|
|
|
101
118
|
quantity: 1,
|
|
102
119
|
price: defaultPrice,
|
|
103
120
|
billableService: item.uuid,
|
|
104
|
-
|
|
121
|
+
status: BillLineItemStatus.PENDING,
|
|
105
122
|
lineItemOrder: 0,
|
|
106
123
|
selectedPaymentMethod: selectedPaymentMethod,
|
|
107
124
|
availablePaymentMethods: availablePaymentMethods,
|
|
@@ -172,7 +189,7 @@ const BillingForm: React.FC<Workspace2DefinitionProps<BillingFormProps>> = ({
|
|
|
172
189
|
quantity: item.quantity,
|
|
173
190
|
price: item.price,
|
|
174
191
|
lineItemOrder: 0,
|
|
175
|
-
|
|
192
|
+
status: BillLineItemStatus.PENDING,
|
|
176
193
|
billableService: item.uuid,
|
|
177
194
|
}));
|
|
178
195
|
|
|
@@ -192,7 +209,7 @@ const BillingForm: React.FC<Workspace2DefinitionProps<BillingFormProps>> = ({
|
|
|
192
209
|
quantity: item.quantity,
|
|
193
210
|
price: item.price,
|
|
194
211
|
lineItemOrder: item.lineItemOrder,
|
|
195
|
-
|
|
212
|
+
status: item.status,
|
|
196
213
|
billableService: serviceUuid,
|
|
197
214
|
priceName: item.priceName,
|
|
198
215
|
priceUuid: item.priceUuid,
|
|
@@ -210,13 +227,14 @@ const BillingForm: React.FC<Workspace2DefinitionProps<BillingFormProps>> = ({
|
|
|
210
227
|
|
|
211
228
|
await updateBillItems(payload);
|
|
212
229
|
} else {
|
|
213
|
-
const payload = {
|
|
230
|
+
const payload: CreateBillPayload = {
|
|
214
231
|
cashPoint: postBilledItems.cashPoint,
|
|
215
232
|
cashier: postBilledItems.cashier,
|
|
216
233
|
lineItems: newLineItems,
|
|
217
234
|
payments: [],
|
|
218
235
|
patient: patientUuid,
|
|
219
236
|
status: BillStatus.PENDING,
|
|
237
|
+
...(activeVisit?.uuid && { visit: activeVisit.uuid }),
|
|
220
238
|
};
|
|
221
239
|
|
|
222
240
|
await processBillItems(payload);
|
|
@@ -224,6 +242,7 @@ const BillingForm: React.FC<Workspace2DefinitionProps<BillingFormProps>> = ({
|
|
|
224
242
|
|
|
225
243
|
closeWorkspace({ discardUnsavedChanges: true });
|
|
226
244
|
onMutate?.();
|
|
245
|
+
swrMutate(patientPaymentStatusCacheKey(patientUuid));
|
|
227
246
|
|
|
228
247
|
showSnackbar({
|
|
229
248
|
title: isEditMode ? t('itemsAddedToBill', 'Items added to bill') : t('billProcessed', 'Bill processed'),
|
|
@@ -148,11 +148,15 @@ const VisitAttributesForm: React.FC<VisitAttributesFormProps> = ({ setAttributes
|
|
|
148
148
|
name="payment-details"
|
|
149
149
|
onChange={(selected) => field.onChange(selected)}
|
|
150
150
|
orientation="vertical">
|
|
151
|
-
<RadioButton
|
|
151
|
+
<RadioButton
|
|
152
|
+
labelText={t('paying', 'Paying')}
|
|
153
|
+
value={categoryConcepts.payingDetails}
|
|
154
|
+
id="payment-details-paying"
|
|
155
|
+
/>
|
|
152
156
|
<RadioButton
|
|
153
157
|
labelText={t('nonPaying', 'Non paying')}
|
|
154
158
|
value={categoryConcepts.nonPayingDetails}
|
|
155
|
-
id="
|
|
159
|
+
id="payment-details-non-paying"
|
|
156
160
|
/>
|
|
157
161
|
</RadioButtonGroup>
|
|
158
162
|
)}
|