From bd1e5b44047192c1a669cd543ebd002046c1e0fe Mon Sep 17 00:00:00 2001 From: ELVIS-KATO Date: Tue, 11 Nov 2025 06:50:48 +0300 Subject: [PATCH 1/3] Added a validation of active visit before billing --- .../billing-checkin-form.component.tsx | 13 ++++++- src/billing-form/billing-form.component.tsx | 39 ++++++++++++++++--- translations/en.json | 3 +- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/billing-form/billing-checkin-form.component.tsx b/src/billing-form/billing-checkin-form.component.tsx index 3f797515..4abfadc2 100644 --- a/src/billing-form/billing-checkin-form.component.tsx +++ b/src/billing-form/billing-checkin-form.component.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useState } from 'react'; import { Dropdown, InlineLoading, InlineNotification } from '@carbon/react'; import { useTranslation } from 'react-i18next'; -import { showSnackbar, getCoreTranslation } from '@openmrs/esm-framework'; +import { showSnackbar, getCoreTranslation, useVisit } from '@openmrs/esm-framework'; import { useCashPoint, useBillableItems, createPatientBill } from './billing-form.resource'; import VisitAttributesForm from './visit-attributes/visit-attributes-form.component'; import styles from './billing-checkin-form.scss'; @@ -19,10 +19,19 @@ const BillingCheckInForm: React.FC = ({ patientUuid, se const { lineItems, isLoading: isLoadingLineItems, error: lineError } = useBillableItems(); const [attributes, setAttributes] = useState([]); const [paymentMethod, setPaymentMethod] = useState(); + const { currentVisit } = useVisit(patientUuid); let lineList = []; const handleCreateExtraVisitInfo = useCallback( async (createBillPayload) => { + if (!currentVisit) { + showSnackbar({ + title: t('validationError', 'Validation error'), + subtitle: t('activeVisitRequired', 'Patient must have an active visit before creating a bill'), + kind: 'error', + }); + return; + } try { await createPatientBill(createBillPayload); showSnackbar({ @@ -38,7 +47,7 @@ const BillingCheckInForm: React.FC = ({ patientUuid, se }); } }, - [t], + [t, currentVisit], ); const handleBillingService = ({ selectedItem }) => { diff --git a/src/billing-form/billing-form.component.tsx b/src/billing-form/billing-form.component.tsx index f812c412..72f9ca6a 100644 --- a/src/billing-form/billing-form.component.tsx +++ b/src/billing-form/billing-form.component.tsx @@ -11,7 +11,14 @@ import { InlineNotification, NumberInput, } from '@carbon/react'; -import { useConfig, useLayoutType, showSnackbar, getCoreTranslation, TrashCanIcon } from '@openmrs/esm-framework'; +import { + useConfig, + useLayoutType, + showSnackbar, + getCoreTranslation, + TrashCanIcon, + useVisit, +} from '@openmrs/esm-framework'; import { processBillItems, useBillableServices } from '../billing.resource'; import { calculateTotalAmount, convertToCurrency } from '../helpers/functions'; import type { BillingConfig } from '../config-schema'; @@ -37,6 +44,7 @@ const BillingForm: React.FC = ({ patientUuid, closeWorkspace } const [isSubmitting, setIsSubmitting] = useState(false); const [selectedItems, setSelectedItems] = useState([]); const { data, error, isLoading } = useBillableServices(); + const { currentVisit } = useVisit(patientUuid); const selectBillableItem = (item: BillableItem) => { if (!item) { @@ -116,7 +124,19 @@ const BillingForm: React.FC = ({ patientUuid, closeWorkspace } return true; }; - const postBillItems = async () => { + const postBillItems = async (event?: React.FormEvent) => { + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + if (!currentVisit) { + showSnackbar({ + title: t('validationError', 'Validation error'), + subtitle: t('activeVisitRequired', 'Patient must have an active visit before creating a bill'), + kind: 'error', + }); + return; + } if (!validateSelectedItems()) { return; } @@ -167,7 +187,12 @@ const BillingForm: React.FC = ({ patientUuid, closeWorkspace } }; return ( -
+ { + e.preventDefault(); + e.stopPropagation(); + }}>
{isLoading ? ( @@ -278,9 +303,13 @@ const BillingForm: React.FC = ({ patientUuid, closeWorkspace }