Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/bill-item-actions/edit-bill-item.modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ const EditBillLineItemModal: React.FC<EditBillLineItemModalProps> = ({ bill, clo

const onSubmit = async (data: BillLineItemForm) => {
const url = `${apiBasePath}bill`;
if (bill?.status === 'PENDING') {
showSnackbar({
title: t('cannotEditBill', 'This bill can not be edited'),
subtitle: t('onlyPendingBillsCanBeEdited', 'Only pending bills can be editted'),
kind: 'error',
});
}
return;

const newItem = {
...item,
Expand Down
13 changes: 11 additions & 2 deletions src/billing-form/billing-checkin-form.component.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -19,10 +19,19 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
const { lineItems, isLoading: isLoadingLineItems, error: lineError } = useBillableItems();
const [attributes, setAttributes] = useState([]);
const [paymentMethod, setPaymentMethod] = useState<any>();
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({
Expand All @@ -38,7 +47,7 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
});
}
},
[t],
[t, currentVisit],
);

const handleBillingService = ({ selectedItem }) => {
Expand Down
42 changes: 37 additions & 5 deletions src/billing-form/billing-form.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -37,6 +44,7 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }
const [isSubmitting, setIsSubmitting] = useState(false);
const [selectedItems, setSelectedItems] = useState<ExtendedLineItem[]>([]);
const { data, error, isLoading } = useBillableServices();
const { currentVisit } = useVisit(patientUuid);

const selectBillableItem = (item: BillableItem) => {
if (!item) {
Expand Down Expand Up @@ -116,7 +124,22 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }
return true;
};

const postBillItems = async () => {
const postBillItems = async (event?: React.MouseEvent<HTMLButtonElement>) => {
if (event) {
event.preventDefault();
event.stopPropagation();
}
if (selectedItems.length === 0) {
return;
}
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;
}
Expand Down Expand Up @@ -167,7 +190,12 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }
};

return (
<Form className={styles.form}>
<Form
className={styles.form}
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}>
<div className={styles.grid}>
{isLoading ? (
<InlineLoading description={getCoreTranslation('loading') + '...'} />
Expand Down Expand Up @@ -278,9 +306,13 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }
<Button
className={styles.button}
kind="primary"
onClick={postBillItems}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
postBillItems(e);
}}
disabled={isSubmitting || selectedItems.length === 0}
type="submit">
type="button">
{isSubmitting ? (
<InlineLoading description={t('saving', 'Saving') + '...'} />
) : (
Expand Down
6 changes: 4 additions & 2 deletions src/billing.resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import type {

export const mapBillProperties = (bill: PatientInvoice): MappedBill => {
const activeLineItems = bill?.lineItems?.filter((item) => !item.voided) || [];
const isSpecialStatus = bill.status === ' PAID' || bill.status === 'POSTED';

const status =
activeLineItems.length > 0
const status = isSpecialStatus
? bill.status
: activeLineItems.length > 0
? activeLineItems.some((item) => item.paymentStatus === 'PENDING')
? 'PENDING'
: 'PAID'
Expand Down
33 changes: 23 additions & 10 deletions src/invoice/invoice-table.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const InvoiceTable: React.FC<InvoiceTableProps> = ({ bill, isLoadingBill }) => {
const tableRows: Array<typeof DataTableRow> = useMemo(
() =>
filteredLineItems?.map((item, index) => {
const canEditBill = bill?.status === 'PENDING';
return {
no: `${index + 1}`,
id: `${item.uuid}`,
Expand All @@ -96,20 +97,32 @@ const InvoiceTable: React.FC<InvoiceTableProps> = ({ bill, isLoadingBill }) => {
total: convertToCurrency(item.price * item.quantity, defaultCurrency),
actionButton: (
<span>
<Button
data-testid={`edit-button-${item.uuid}`}
renderIcon={Edit}
hasIconOnly
kind="ghost"
iconDescription={t('editThisBillItem', 'Edit this bill item')}
tooltipPosition="left"
onClick={() => handleSelectBillItem(item)}
/>
{canEditBill ? (
<Button
data-testid={`edit-button-${item.uuid}`}
renderIcon={Edit}
hasIconOnly
kind="ghost"
iconDescription={t('editThisBillItem', 'Edit this bill item')}
tooltipPosition="left"
onClick={() => handleSelectBillItem(item)}
/>
) : (
<Button
data-testid={`edit-button-${item.uuid}`}
renderIcon={Edit}
hasIconOnly
kind="ghost"
iconDescription={t('cannotEditPendingItem', 'Only pending bill items can be edited')}
disabled
tooltipPosition="left"
/>
)}
</span>
),
};
}) ?? [],
[filteredLineItems, bill?.receiptNumber, defaultCurrency, t, handleSelectBillItem],
[filteredLineItems, bill?.receiptNumber, bill?.status, defaultCurrency, t, handleSelectBillItem],
);

if (isLoadingBill) {
Expand Down
5 changes: 4 additions & 1 deletion translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,5 +226,8 @@
"uuidRequired": "UUID is required",
"validationError": "Validation error",
"visitTime": "Visit time",
"waiverForm": "Waiver form"
"waiverForm": "Waiver form",
"activeVisitRequired": "Patient must have an active visit before creating a bill",
"cannotEditBill": "cannot edit this bill",
"onlyPendingBillsCanBeEdited" : "Only pending bills can be edited"
}