Skip to content

Commit

Permalink
O3-2910 Incorrect Invoice Status Display for Partial Payments (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
CynthiaKamau authored Mar 28, 2024
1 parent 37f8d6d commit 3bf6096
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/billing-form/billing-form.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }
processBillItems(bill).then(
() => {
setIsSubmitting(false);

closeWorkspace();
mutate((key) => typeof key === 'string' && key.startsWith(url), undefined, { revalidate: true });
showSnackbar({
Expand Down
9 changes: 7 additions & 2 deletions src/billing.resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const useBills = (patientUuid: string = '', billStatus: string = '') => {
patientName: bill?.patient?.display.split('-')?.[1],
identifier: bill?.patient?.display.split('-')?.[0],
patientUuid: bill?.patient?.uuid,
status: bill?.status,
status: bill.lineItems.some((item) => item.paymentStatus === 'PENDING') ? 'PENDING' : 'PAID',
receiptNumber: bill?.receiptNumber,
cashier: bill?.cashier,
cashPointUuid: bill?.cashPoint?.uuid,
Expand Down Expand Up @@ -61,7 +61,12 @@ export const useBill = (billUuid: string) => {
patientName: bill?.patient?.display.split('-')?.[1],
identifier: bill?.patient?.display.split('-')?.[0],
patientUuid: bill?.patient?.uuid,
status: bill?.status,
status:
bill.lineItems.length > 1
? bill.lineItems.some((item) => item.paymentStatus === 'PENDING')
? 'PENDING'
: 'PAID'
: bill.status,
receiptNumber: bill?.receiptNumber,
cashier: bill?.cashier,
cashPointUuid: bill?.cashPoint?.uuid,
Expand Down
12 changes: 7 additions & 5 deletions src/invoice/invoice-table.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const InvoiceTable: React.FC<InvoiceTableProps> = ({ bill, isSelectable = true,
const lineItems = bill?.lineItems ?? [];
const layout = useLayoutType();
const responsiveSize = isDesktop(layout) ? 'sm' : 'lg';
const [selectedLineItems, setSelectedLineItems] = useState([]);
const pendingLineItems = lineItems?.filter((item) => item.paymentStatus === 'PENDING') ?? [];
const [selectedLineItems, setSelectedLineItems] = useState(pendingLineItems ?? []);
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm);
const { defaultCurrency } = useConfig();
Expand Down Expand Up @@ -73,15 +74,15 @@ const InvoiceTable: React.FC<InvoiceTableProps> = ({ bill, isSelectable = true,
return {
no: `${index + 1}`,
id: `${item.uuid}`,
billItem: item.item || item.billableService,
billItem: item.billableService ? item.billableService : item?.item,
billCode: bill?.receiptNumber,
status: bill?.status,
status: item?.paymentStatus,
quantity: item.quantity,
price: convertToCurrency(item.price, defaultCurrency),
total: convertToCurrency(item.price * item.quantity, defaultCurrency),
};
}) ?? [],
[bill?.receiptNumber, bill?.status, filteredLineItems],
[bill?.receiptNumber, filteredLineItems],
);

if (isLoadingBill) {
Expand Down Expand Up @@ -145,7 +146,7 @@ const InvoiceTable: React.FC<InvoiceTableProps> = ({ bill, isSelectable = true,
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
{rows.map((row, index) => (
<TableRow
key={row.id}
{...getRowProps({
Expand All @@ -156,6 +157,7 @@ const InvoiceTable: React.FC<InvoiceTableProps> = ({ bill, isSelectable = true,
aria-label="Select row"
{...getSelectionProps({ row })}
onChange={(checked: boolean) => handleRowSelection(row, checked)}
checked={Boolean(selectedLineItems?.find((item) => item?.uuid === row?.id))}
/>
)}
{row.cells.map((cell) => (
Expand Down
5 changes: 5 additions & 0 deletions src/invoice/invoice.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ const Invoice: React.FC = () => {
}
}, [isPrinting]);

useEffect(() => {
const unPaidLineItems = bill?.lineItems?.filter((item) => item.paymentStatus === 'PENDING') ?? [];
setSelectedLineItems(unPaidLineItems);
}, [bill?.lineItems]);

const invoiceDetails = {
'Total Amount': convertToCurrency(bill?.totalAmount, defaultCurrency),
'Amount Tendered': convertToCurrency(bill?.tenderedAmount, defaultCurrency),
Expand Down
18 changes: 8 additions & 10 deletions src/invoice/payments/payments.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,20 @@ const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
});

const hasMoreThanOneLineItem = bill?.lineItems?.length > 1;

const computedTotal = hasMoreThanOneLineItem ? computeTotalPrice(selectedLineItems) : bill?.totalAmount ?? 0;

const totalAmountTendered = formValues?.reduce((curr: number, prev) => curr + Number(prev.amount) ?? 0, 0) ?? 0;
const amountDue = Number(computedTotal) - (Number(bill?.tenderedAmount) + Number(totalAmountTendered));
const newAmountDue = Number(bill?.totalAmount - bill?.tenderedAmount);

const handleNavigateToBillingDashboard = () =>
navigate({
to: window.getOpenmrsSpaBase() + 'home/billing',
});

const handleProcessPayment = () => {
const paymentPayload = createPaymentPayload(bill, bill.patientUuid, formValues, amountDue, billableServices);
const paymentPayload = createPaymentPayload(bill, bill.patientUuid, formValues, amountDue, billableServices, selectedLineItems);
processBillPayment(paymentPayload, bill.uuid).then(
() => {
(res) => {
showSnackbar({
title: t('billPayment', 'Bill payment'),
subtitle: 'Bill payment processing has been successful',
Expand All @@ -78,8 +77,7 @@ const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
if (currentVisit) {
updateBillVisitAttribute(currentVisit);
}

handleNavigateToBillingDashboard();
window.location.reload();
},
(error) => {
showSnackbar({ title: 'Bill payment error', kind: 'error', subtitle: error?.message });
Expand All @@ -98,24 +96,24 @@ const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
</CardHeader>
<div>
{bill && <PaymentHistory bill={bill} />}
<PaymentForm disablePayment={amountDue <= 0} amountDue={amountDue} />
<PaymentForm disablePayment={computedTotal <= 0} amountDue={amountDue} />
</div>
</div>
<div className={styles.divider} />
<div className={styles.paymentTotals}>
<InvoiceBreakDown
label={t('totalAmount', 'Total Amount')}
value={convertToCurrency(computedTotal, defaultCurrency)}
value={convertToCurrency(bill?.totalAmount, defaultCurrency)}
/>
<InvoiceBreakDown
label={t('totalTendered', 'Total Tendered')}
value={convertToCurrency(bill?.tenderedAmount + totalAmountTendered ?? 0, defaultCurrency)}
value={convertToCurrency(bill?.tenderedAmount, defaultCurrency)}
/>
<InvoiceBreakDown label={t('discount', 'Discount')} value={'--'} />
<InvoiceBreakDown
hasBalance={amountDue < 0 ?? false}
label={amountDueDisplay(amountDue)}
value={convertToCurrency(amountDue ?? 0, defaultCurrency)}
value={convertToCurrency(bill?.totalAmount - bill?.tenderedAmount, defaultCurrency)}
/>
<div className={styles.processPayments}>
<Button onClick={handleNavigateToBillingDashboard} kind="secondary">
Expand Down
48 changes: 38 additions & 10 deletions src/invoice/payments/utils.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,63 @@
import { type OpenmrsResource } from '@openmrs/esm-framework';
import { type MappedBill } from '../../types';
import { type LineItem, type MappedBill } from '../../types';
import { type Payment } from './payments.component';

const hasLineItem = (lineItems: Array<LineItem>, item: LineItem) => {
if (lineItems?.length === 0) {
return false;
}
const foundItem = lineItems.find((lineItem) => lineItem.uuid === item.uuid);
return Boolean(foundItem);
};

export const createPaymentPayload = (
bill: MappedBill,
patientUuid: string,
formValues: Array<Payment>,
amountDue: number,
billableServices: Array<any>,
selectedLineItems: Array<LineItem>,
) => {
const { cashier } = bill;
const totalAmount = bill?.totalAmount;
const paymentStatus = amountDue <= 0 ? 'PAID' : 'PENDING';
const totalPaymentStatus = amountDue <= 0 ? 'PAID' : 'PENDING';
const previousPayments = bill.payments.map((payment) => ({
amount: payment.amount,
amountTendered: payment.amountTendered,
attributes: [],
instanceType: payment.instanceType.uuid,
}));

const billPayment = formValues.map((formValue) => ({
const newPayments = formValues.map((formValue) => ({
amount: parseFloat(totalAmount.toFixed(2)),
amountTendered: parseFloat(Number(formValue.amount).toFixed(2)),
attributes: [],
instanceType: formValue.method,
}));

const updatedPayments = newPayments.concat(previousPayments);
const totalAmountRendered = updatedPayments.reduce((acc, payment) => acc + payment.amountTendered, 0);
const updatedLineItems = bill?.lineItems.map((lineItem) => ({
...lineItem,
billableService: getBillableServiceUuid(billableServices, lineItem.billableService),
item: lineItem?.item,
paymentStatus: hasLineItem(selectedLineItems ?? [], lineItem)
? totalAmountRendered >= lineItem.price * lineItem.quantity
? 'PAID'
: 'PENDING'
: lineItem.paymentStatus,
}));

const allItemsBillPaymentStatus =
updatedLineItems.filter((item) => item.paymentStatus === 'PENDING').length === 0 ? 'PAID' : 'PENDING';

const processedPayment = {
cashPoint: bill.cashPointUuid,
cashier: cashier.uuid,
lineItems: bill?.lineItems.map((lineItem) => ({
...lineItem,
paymentStatus: 'PAID',
billableService: getBillableServiceUuid(billableServices, lineItem.billableService),
})),
payments: [...billPayment],
lineItems: updatedLineItems,
payments: [...updatedPayments],
patient: patientUuid,
status: paymentStatus,
status: selectedLineItems?.length > 0 ? allItemsBillPaymentStatus : totalPaymentStatus,
};

return processedPayment;
Expand Down
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export interface LineItem {
priceUuid: string;
lineItemOrder: number;
resourceVersion: string;
paymentStatus: string;
}

interface PatientLink {
Expand Down

0 comments on commit 3bf6096

Please sign in to comment.