@kenyaemr/esm-billing-app 5.3.10-pre.1650 → 5.3.10-pre.1652

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/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"billableServicesHome","route":"billable-services"},{"component":"requirePaymentModal","routeRegex":"^patient/.+/chart","online":true,"offline":false}],"extensions":[{"component":"billingDashboardLink","name":"billing-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"billing","title":"billing","slot":"billing-dashboard-slot"}},{"component":"benefitsPackageDashboardLink","name":"benefits-package-dashboard-link","slot":"patient-chart-dashboard-slot","meta":{"name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot","path":"insurance-benefits","columns":1,"columnSpan":1},"featureFlag":"healthInformationExchange"},{"component":"benefitsPackage","name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot"},{"component":"root","name":"billing-dashboard-root","slot":"billing-dashboard-slot"},{"component":"benefitsEligibilyRequestForm","name":"benefits-eligibility-request-form"},{"component":"benefitsPreAuthForm","name":"benefits-pre-auth-form"},{"name":"billing-patient-summary","component":"billingPatientSummary","slot":"patient-chart-billing-dashboard-slot","order":10,"meta":{"columnSpan":4}},{"name":"billing-summary-dashboard-link","component":"billingSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":11,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-billing-dashboard-slot","path":"Billing","layoutMode":"anchored"}},{"name":"billing-check-in-form","slot":"extra-visit-attribute-slot","component":"billingCheckInForm"},{"name":"require-billing-modal","component":"requirePaymentModal"},{"name":"patient-banner-billing-tags","component":"visitAttributeTags","slot":"patient-banner-tags-slot","order":2},{"name":"initiate-payment-modal","component":"initiatePaymentDialog"},{"name":"delete-billableservice-modal","component":"deleteBillableServiceModal"},{"name":"refund-bill-modal","component":"refundBillModal"},{"name":"delete-bill-modal","component":"deleteBillModal"},{"name":"lab-order-billable-item","component":"labOrder","slot":"top-of-lab-order-form-slot"},{"name":"procedure-order-billable-item","component":"procedureOrder","slot":"top-of-procedure-order-form-slot"},{"name":"imaging-order-billable-item","component":"imagingOrder","slot":"top-of-imaging-order-form-slot"},{"name":"price-info-order","component":"priceInfoOrder"},{"name":"drug-order-billable-item","component":"drugOrder","slot":"medication-info-slot"},{"name":"billing-test-order-action","component":"testOrderAction","slot":"tests-ordered-actions-slot","order":0},{"component":"billingOverviewLink","name":"billing-overview-link","slot":"billing-dashboard-link-slot"},{"component":"paymentHistoryLink","name":"payment-history-link","slot":"billing-dashboard-link-slot"},{"component":"paymentPointsLink","name":"payment-points-link","slot":"billing-dashboard-link-slot"},{"component":"paymentModesLink","name":"payment-modes-link","slot":"billing-dashboard-link-slot"},{"component":"billManagerLink","name":"bill-manager-link","slot":"billing-dashboard-link-slot"},{"component":"chargeableItemsLink","name":"chargeable-items-link","slot":"billing-dashboard-link-slot"},{"component":"billableExemptionsLink","name":"billable-exemptions-link","slot":"billing-dashboard-link-slot"},{"component":"claimsManagementSideNavGroup","name":"claims-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"claims-management","title":"Claims management Overview","slot":"case-management-slot"},"featureFlag":"healthInformationExchange"},{"component":"claimsManagementOverviewDashboardLink","name":"claims-management-overview-link","slot":"claims-management-dashboard-link-slot"},{"component":"preAuthRequestsDashboardLink","name":"preauthrequest-overview-link","slot":"claims-management-dashboard-link-slot"},{"component":"claimsOverview","name":"claims-overview-dashboard-link","slot":"claims-management-overview-slot"},{"component":"waiveBillActionButton","name":"waive-bill-action-button","slot":"bill-actions-slot"},{"component":"deleteBillActionButton","name":"delete-bill-action-button","slot":"bill-actions-slot"},{"component":"refundLineItem","name":"refund-line-item","slot":"bill-actions-overflow-menu-slot"},{"name":"edit-line-item","component":"editLineItem","slot":"bill-actions-overflow-menu-slot"},{"name":"cancel-line-item","component":"cancelLineItem","slot":"bill-actions-overflow-menu-slot"}],"workspaces":[{"name":"waive-bill-form","component":"waiveBillForm","title":"Waive Bill Form","type":"other-form"},{"name":"edit-bill-form","component":"editBillForm","title":"Edit Bill Form","type":"other-form"},{"name":"billable-service-form","component":"addServiceForm","title":"Create Charge Item Form","type":"other-form"},{"name":"commodity-form","component":"addCommodityForm","title":"Create Charge Item Form","type":"other-form"},{"name":"billing-form","component":"billingForm","title":"Billing Form","type":"other-form","width":"extra-wide"},{"name":"payment-mode-workspace","component":"paymentModeWorkspace","title":"Payment Mode Workspace","type":"other-form"},{"name":"cancel-bill-workspace","component":"cancelBillWorkspace","title":"Cancel Bill Workspace","type":"other-form"}],"modals":[{"name":"create-payment-point","component":"createPaymentPoint"},{"name":"clock-in-modal","component":"clockIn"},{"name":"clock-out-modal","component":"clockOut"},{"name":"bulk-import-billable-services-modal","component":"bulkImportBillableServicesModal"},{"name":"delete-payment-mode-modal","component":"deletePaymentModeModal"},{"name":"retry-claim-request-modal","component":"retryClaimRequestModal"},{"name":"paid-bill-receipt-print-preview-modal","component":"paidBillReceiptPrintPreviewModal"}],"version":"5.3.10-pre.1650"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"billableServicesHome","route":"billable-services"},{"component":"requirePaymentModal","routeRegex":"^patient/.+/chart","online":true,"offline":false}],"extensions":[{"component":"billingDashboardLink","name":"billing-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"billing","title":"billing","slot":"billing-dashboard-slot"}},{"component":"benefitsPackageDashboardLink","name":"benefits-package-dashboard-link","slot":"patient-chart-dashboard-slot","meta":{"name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot","path":"insurance-benefits","columns":1,"columnSpan":1},"featureFlag":"healthInformationExchange"},{"component":"benefitsPackage","name":"benefits-package","slot":"patient-chart-benefits-dashboard-slot"},{"component":"root","name":"billing-dashboard-root","slot":"billing-dashboard-slot"},{"component":"benefitsEligibilyRequestForm","name":"benefits-eligibility-request-form"},{"component":"benefitsPreAuthForm","name":"benefits-pre-auth-form"},{"name":"billing-patient-summary","component":"billingPatientSummary","slot":"patient-chart-billing-dashboard-slot","order":10,"meta":{"columnSpan":4}},{"name":"billing-summary-dashboard-link","component":"billingSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":11,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-billing-dashboard-slot","path":"Billing","layoutMode":"anchored"}},{"name":"billing-check-in-form","slot":"extra-visit-attribute-slot","component":"billingCheckInForm"},{"name":"require-billing-modal","component":"requirePaymentModal"},{"name":"patient-banner-billing-tags","component":"visitAttributeTags","slot":"patient-banner-tags-slot","order":2},{"name":"initiate-payment-modal","component":"initiatePaymentDialog"},{"name":"delete-billableservice-modal","component":"deleteBillableServiceModal"},{"name":"refund-bill-modal","component":"refundBillModal"},{"name":"delete-bill-modal","component":"deleteBillModal"},{"name":"lab-order-billable-item","component":"labOrder","slot":"top-of-lab-order-form-slot"},{"name":"procedure-order-billable-item","component":"procedureOrder","slot":"top-of-procedure-order-form-slot"},{"name":"imaging-order-billable-item","component":"imagingOrder","slot":"top-of-imaging-order-form-slot"},{"name":"price-info-order","component":"priceInfoOrder"},{"name":"drug-order-billable-item","component":"drugOrder","slot":"medication-info-slot"},{"name":"billing-test-order-action","component":"testOrderAction","slot":"tests-ordered-actions-slot","order":0},{"component":"billingOverviewLink","name":"billing-overview-link","slot":"billing-dashboard-link-slot"},{"component":"paymentHistoryLink","name":"payment-history-link","slot":"billing-dashboard-link-slot"},{"component":"paymentPointsLink","name":"payment-points-link","slot":"billing-dashboard-link-slot"},{"component":"paymentModesLink","name":"payment-modes-link","slot":"billing-dashboard-link-slot"},{"component":"billManagerLink","name":"bill-manager-link","slot":"billing-dashboard-link-slot"},{"component":"chargeableItemsLink","name":"chargeable-items-link","slot":"billing-dashboard-link-slot"},{"component":"billableExemptionsLink","name":"billable-exemptions-link","slot":"billing-dashboard-link-slot"},{"component":"claimsManagementSideNavGroup","name":"claims-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"claims-management","title":"Claims management Overview","slot":"case-management-slot"},"featureFlag":"healthInformationExchange"},{"component":"claimsManagementOverviewDashboardLink","name":"claims-management-overview-link","slot":"claims-management-dashboard-link-slot"},{"component":"preAuthRequestsDashboardLink","name":"preauthrequest-overview-link","slot":"claims-management-dashboard-link-slot"},{"component":"claimsOverview","name":"claims-overview-dashboard-link","slot":"claims-management-overview-slot"},{"component":"waiveBillActionButton","name":"waive-bill-action-button","slot":"bill-actions-slot"},{"component":"deleteBillActionButton","name":"delete-bill-action-button","slot":"bill-actions-slot"},{"component":"refundLineItem","name":"refund-line-item","slot":"bill-actions-overflow-menu-slot"},{"name":"edit-line-item","component":"editLineItem","slot":"bill-actions-overflow-menu-slot"},{"name":"cancel-line-item","component":"cancelLineItem","slot":"bill-actions-overflow-menu-slot"}],"workspaces":[{"name":"waive-bill-form","component":"waiveBillForm","title":"Waive Bill Form","type":"other-form"},{"name":"edit-bill-form","component":"editBillForm","title":"Edit Bill Form","type":"other-form"},{"name":"billable-service-form","component":"addServiceForm","title":"Create Charge Item Form","type":"other-form"},{"name":"commodity-form","component":"addCommodityForm","title":"Create Charge Item Form","type":"other-form"},{"name":"billing-form","component":"billingForm","title":"Billing Form","type":"other-form","width":"extra-wide"},{"name":"payment-mode-workspace","component":"paymentModeWorkspace","title":"Payment Mode Workspace","type":"other-form"},{"name":"cancel-bill-workspace","component":"cancelBillWorkspace","title":"Cancel Bill Workspace","type":"other-form"}],"modals":[{"name":"create-payment-point","component":"createPaymentPoint"},{"name":"clock-in-modal","component":"clockIn"},{"name":"clock-out-modal","component":"clockOut"},{"name":"bulk-import-billable-services-modal","component":"bulkImportBillableServicesModal"},{"name":"delete-payment-mode-modal","component":"deletePaymentModeModal"},{"name":"retry-claim-request-modal","component":"retryClaimRequestModal"},{"name":"paid-bill-receipt-print-preview-modal","component":"paidBillReceiptPrintPreviewModal"}],"version":"5.3.10-pre.1652"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-billing-app",
3
- "version": "5.3.10-pre.1650",
3
+ "version": "5.3.10-pre.1652",
4
4
  "description": "Billing app for KenyaEMR",
5
5
  "browser": "dist/kenyaemr-esm-billing-app.js",
6
6
  "main": "src/index.ts",
@@ -59,7 +59,10 @@ export const PaymentHistoryTable = ({
59
59
  return {
60
60
  ...row,
61
61
  totalAmount: convertToCurrency(row.payments.reduce((acc, payment) => acc + payment.amountTendered, 0)),
62
- referenceCodes: row.payments.map(({ attributes }) => attributes.map(({ value }) => value).join(' ')).join(', '),
62
+ referenceCodes: row.payments
63
+ .map(({ attributes }) => attributes.map(({ value }) => value).join(', '))
64
+ .filter((code) => code !== '')
65
+ .join(', '),
63
66
  };
64
67
  });
65
68
 
@@ -83,6 +86,7 @@ export const PaymentHistoryTable = ({
83
86
  'Total Amount Paid': row.payments.reduce((acc, payment) => acc + payment.amountTendered, 0),
84
87
  'Reason/Reference': row.payments
85
88
  .map(({ attributes }) => attributes.map(({ value }) => value).join(' '))
89
+ .filter((code) => code !== '')
86
90
  .join(', '),
87
91
  };
88
92
  });
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ import { type MappedBill } from '../types';
3
+
4
+ export function usePaymentSchema(bill: MappedBill) {
5
+ const paymentSchema = z
6
+ .object({
7
+ method: z
8
+ .object({
9
+ uuid: z.string(),
10
+ name: z.string(),
11
+ attributeTypes: z.array(
12
+ z.object({
13
+ uuid: z.string(),
14
+ description: z.string(),
15
+ required: z.boolean(),
16
+ }),
17
+ ),
18
+ })
19
+ .nullable()
20
+ .refine((val) => val !== null, { message: 'Payment method is required' }),
21
+ amount: z.number().refine((value) => {
22
+ const amountDue = Number(bill.totalAmount) - (Number(bill.tenderedAmount) + Number(value));
23
+ return amountDue >= 0 && value > 0;
24
+ }, 'Amount paid should not be greater than amount due'),
25
+ referenceCode: z.string(),
26
+ })
27
+ .refine(
28
+ (data) => {
29
+ const hasRequiredAttribute = data.method?.attributeTypes.some((attr) => attr.required === true);
30
+ if (hasRequiredAttribute) {
31
+ return data.referenceCode.trim().length > 0;
32
+ }
33
+ return true;
34
+ },
35
+ {
36
+ message: 'Reference code is required for this payment method',
37
+ path: ['referenceCode'],
38
+ },
39
+ );
40
+
41
+ return paymentSchema;
42
+ }
@@ -6,12 +6,12 @@ import { Button, Dropdown, NumberInputSkeleton, TextInput, NumberInput } from '@
6
6
  import { ErrorState } from '@openmrs/esm-patient-common-lib';
7
7
  import styles from './payment-form.scss';
8
8
  import { usePaymentModes } from '../../../billing.resource';
9
- import { PaymentFormValue } from '../../../types';
9
+ import { PaymentFormValue, PaymentMethod } from '../../../types';
10
10
 
11
11
  type PaymentFormProps = {
12
12
  disablePayment: boolean;
13
13
  amountDue: number;
14
- append: (obj: { method: string; amount: number; referenceCode: string }) => void;
14
+ append: (obj: { method: PaymentMethod; amount: number; referenceCode: string }) => void;
15
15
  fields: FieldArrayWithId<PaymentFormValue, 'payment', 'id'>[];
16
16
  remove: UseFieldArrayRemove;
17
17
  };
@@ -22,12 +22,18 @@ const PaymentForm: React.FC<PaymentFormProps> = ({ disablePayment, amountDue, ap
22
22
  control,
23
23
  formState: { errors },
24
24
  setFocus,
25
+ getValues,
25
26
  } = useFormContext<PaymentFormValue>();
26
27
  const { paymentModes, isLoading, error } = usePaymentModes();
27
28
 
29
+ const shouldShowReferenceCode = (index: number) => {
30
+ const formValues = getValues();
31
+ return formValues?.payment?.[index]?.method?.attributeTypes?.some((attribute) => attribute.required);
32
+ };
33
+
28
34
  const handleAppendPaymentMode = useCallback(() => {
29
35
  {
30
- append({ method: '', amount: 0, referenceCode: '' });
36
+ append({ method: null, amount: 0, referenceCode: '' });
31
37
  setFocus(`payment.${fields.length}.method`);
32
38
  }
33
39
  }, [append]);
@@ -59,7 +65,7 @@ const PaymentForm: React.FC<PaymentFormProps> = ({ disablePayment, amountDue, ap
59
65
  id="paymentMethod"
60
66
  onChange={({ selectedItem }) => {
61
67
  setFocus(`payment.${index}.amount`);
62
- field.onChange(selectedItem?.uuid);
68
+ field.onChange(selectedItem);
63
69
  }}
64
70
  titleText={t('paymentMethod', 'Payment method')}
65
71
  label={t('selectPaymentMethod', 'Select payment method')}
@@ -85,19 +91,23 @@ const PaymentForm: React.FC<PaymentFormProps> = ({ disablePayment, amountDue, ap
85
91
  />
86
92
  )}
87
93
  />
88
- <Controller
89
- name={`payment.${index}.referenceCode`}
90
- control={control}
91
- render={({ field }) => (
92
- <TextInput
93
- {...field}
94
- id="paymentReferenceCode"
95
- labelText={t('referenceNumber', 'Reference number')}
96
- placeholder={t('enterReferenceNumber', 'Enter ref. number')}
97
- type="text"
98
- />
99
- )}
100
- />
94
+ {shouldShowReferenceCode(index) && (
95
+ <Controller
96
+ name={`payment.${index}.referenceCode`}
97
+ control={control}
98
+ render={({ field }) => (
99
+ <TextInput
100
+ {...field}
101
+ id="paymentReferenceCode"
102
+ labelText={t('referenceNumber', 'Reference number')}
103
+ placeholder={t('enterReferenceNumber', 'Enter ref. number')}
104
+ type="text"
105
+ invalid={!!errors?.payment?.[index]?.referenceCode}
106
+ invalidText={errors?.payment?.[index]?.referenceCode?.message}
107
+ />
108
+ )}
109
+ />
110
+ )}
101
111
  <div className={styles.removeButtonContainer}>
102
112
  <TrashCan onClick={() => handleRemovePaymentMode(index)} className={styles.removeButton} size={20} />
103
113
  </div>
@@ -1,8 +1,8 @@
1
+ import React from 'react';
1
2
  import { Button, InlineNotification } from '@carbon/react';
2
3
  import { zodResolver } from '@hookform/resolvers/zod';
3
4
  import { navigate, showSnackbar } from '@openmrs/esm-framework';
4
5
  import { CardHeader } from '@openmrs/esm-patient-common-lib';
5
- import React, { useState } from 'react';
6
6
  import { FormProvider, useFieldArray, useForm, useWatch } from 'react-hook-form';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { mutate } from 'swr';
@@ -17,6 +17,7 @@ import PaymentForm from './payment-form/payment-form.component';
17
17
  import PaymentHistory from './payment-history/payment-history.component';
18
18
  import styles from './payments.scss';
19
19
  import { createPaymentPayload } from './utils';
20
+ import { usePaymentSchema } from '../../hooks/usePaymentSchema';
20
21
 
21
22
  type PaymentProps = {
22
23
  bill: MappedBill;
@@ -25,18 +26,11 @@ type PaymentProps = {
25
26
 
26
27
  const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
27
28
  const { t } = useTranslation();
28
- const paymentSchema = z.object({
29
- method: z.string().refine((value) => !!value, 'Payment method is required'),
30
- amount: z.number().refine((value) => {
31
- const amountDue = Number(bill.totalAmount) - (Number(bill.tenderedAmount) + Number(value));
32
- return amountDue >= 0;
33
- }, 'Amount paid should not be greater than amount due'),
34
- referenceCode: z.union([z.number(), z.string()]).optional(),
35
- });
29
+ const paymentSchema = usePaymentSchema(bill);
36
30
  const { globalActiveSheet } = useClockInStatus();
37
31
 
38
32
  const methods = useForm<PaymentFormValue>({
39
- mode: 'all',
33
+ mode: 'onSubmit',
40
34
  defaultValues: { payment: [] },
41
35
  resolver: zodResolver(z.object({ payment: z.array(paymentSchema) })),
42
36
  });
@@ -46,7 +40,6 @@ const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
46
40
  name: 'payment',
47
41
  control: methods.control,
48
42
  });
49
- const [paymentSuccessful, setPaymentSuccessful] = useState(false);
50
43
 
51
44
  const totalWaivedAmount = computeWaivedAmount(bill);
52
45
  const totalAmountTendered = formValues?.reduce((curr: number, prev) => curr + Number(prev.amount), 0) ?? 0;
@@ -85,7 +78,6 @@ const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
85
78
  });
86
79
  const url = `/ws/rest/v1/cashier/bill/${bill.uuid}`;
87
80
  mutate((key) => typeof key === 'string' && key.startsWith(url), undefined, { revalidate: true });
88
- setPaymentSuccessful(true);
89
81
  },
90
82
  (error) => {
91
83
  showSnackbar({
@@ -123,7 +115,7 @@ const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
123
115
  <InlineNotification
124
116
  title={t('incompletePayment', 'Incomplete payment')}
125
117
  subtitle={t(
126
- 'paymentErrorSubtitle',
118
+ 'incompletePaymentSubtitle',
127
119
  'Please ensure all selected line items are fully paid, Total amount expected is {{selectedLineItemsAmountDue}}',
128
120
  {
129
121
  selectedLineItemsAmountDue: convertToCurrency(selectedLineItemsAmountDue),
@@ -136,9 +128,9 @@ const Payments: React.FC<PaymentProps> = ({ bill, selectedLineItems }) => {
136
128
  )}
137
129
  {hasAmountPaidExceeded && (
138
130
  <InlineNotification
139
- title={t('paymentError', 'Payment error')}
131
+ title={t('overPayment', 'Over payment')}
140
132
  subtitle={t(
141
- 'paymentErrorSubtitle',
133
+ 'overPaymentSubtitle',
142
134
  'Amount paid {{totalAmountTendered}} should not be greater than amount due {{selectedLineItemsAmountDue}} for selected line items',
143
135
  {
144
136
  totalAmountTendered: convertToCurrency(totalAmountTendered),
@@ -116,7 +116,7 @@ describe('Payment', () => {
116
116
  voided: false,
117
117
  },
118
118
  {
119
- billableService: null,
119
+ billableService: 'Hemoglobin',
120
120
  display: 'BillLineItem',
121
121
  item: 'Hemoglobin',
122
122
  lineItemOrder: 0,
@@ -121,7 +121,10 @@ export const createPaymentPayload = (
121
121
  const existingPayments = payments.map((payment) => ({
122
122
  amount: payment.amount,
123
123
  amountTendered: payment.amountTendered,
124
- attributes: [],
124
+ attributes: payment.attributes.map((attribute) => ({
125
+ attributeType: attribute.attributeType?.uuid,
126
+ value: attribute.value,
127
+ })),
125
128
  instanceType: payment.instanceType.uuid,
126
129
  }));
127
130
 
@@ -129,8 +132,11 @@ export const createPaymentPayload = (
129
132
  const currentPayments = paymentFormValues.map((formValue) => ({
130
133
  amount: parseFloat(totalAmount.toFixed(2)),
131
134
  amountTendered: parseFloat(Number(formValue.amount).toFixed(2)),
132
- attributes: [],
133
- instanceType: formValue.method,
135
+ attributes: formValue.method?.attributeTypes?.map((attribute) => ({
136
+ attributeType: attribute.uuid,
137
+ value: formValue.referenceCode,
138
+ })),
139
+ instanceType: formValue.method?.uuid,
134
140
  }));
135
141
 
136
142
  // Combine and calculate payments
@@ -163,13 +169,20 @@ export const createPaymentPayload = (
163
169
  : // If no items were selected, update payment status for all line items
164
170
  lineItems.map((lineItem) => ({
165
171
  ...lineItem,
166
- billableService: extractServiceIdentifier(lineItem),
167
172
  item: extractServiceIdentifier(lineItem),
173
+ billableService: extractServiceIdentifier(lineItem),
168
174
  paymentStatus: isBillableItemFullyPaid(totalPaidAmount, lineItem),
169
175
  }));
170
176
 
171
177
  // Combine selected and remaining items into final processed list
172
- const processedLineItems = [...processedSelectedBillableItems, ...remainingLineItems];
178
+ const processedLineItems = [
179
+ ...processedSelectedBillableItems,
180
+ ...remainingLineItems.map((item) => ({
181
+ ...item,
182
+ item: extractServiceIdentifier(item),
183
+ billableService: extractServiceIdentifier(item),
184
+ })),
185
+ ];
173
186
 
174
187
  // Determine final bill status
175
188
  const hasUnpaidItems = processedLineItems.some((item) => item.paymentStatus === PaymentStatus.PENDING);
@@ -86,11 +86,11 @@ describe('PaymentModeWorkspace', () => {
86
86
  // key in name, description and retired
87
87
  const nameInput = screen.getByRole('textbox', { name: /Payment mode name/i });
88
88
  const descriptionInput = screen.getByRole('textbox', { name: /Payment mode description/i });
89
- const retiredToggle = screen.getByRole('switch', { name: /Retired/i });
89
+ const enablePaymentToggle = screen.getByRole('switch', { name: /Enable payment mode/i });
90
90
 
91
91
  await user.type(nameInput, 'Test Name');
92
92
  await user.type(descriptionInput, 'Test Description');
93
- await user.click(retiredToggle);
93
+ await user.click(enablePaymentToggle);
94
94
 
95
95
  // Click to add attribute type
96
96
  const addAttributeTypeButton = screen.getByRole('button', { name: /Add attribute type/i });
@@ -102,7 +102,6 @@ describe('PaymentModeWorkspace', () => {
102
102
  const attributeRegExpInput = screen.getByRole('textbox', { name: /Enter regular expression/i });
103
103
  const attributeRetiredToggle = screen.getByRole('switch', { name: /Attribute retired/i });
104
104
  const attributeRequiredToggle = screen.getByRole('switch', { name: /Attribute required/i });
105
- const attributeFormatDropdown = screen.getByRole('combobox', { name: /Attribute format/i });
106
105
 
107
106
  // Key in attribute type details
108
107
  await user.type(attributeTypeNameInput, 'Test Attribute Name');
@@ -167,7 +167,7 @@ const PaymentModeWorkspace: React.FC<PaymentModeWorkspaceProps> = ({
167
167
  render={({ field }) => (
168
168
  <Toggle
169
169
  {...field}
170
- labelText={t('paymentModeRetired', 'Retired')}
170
+ labelText={t('enablePaymentMode', 'Enable payment mode')}
171
171
  labelA="Off"
172
172
  labelB="On"
173
173
  toggled={field.value}
@@ -290,7 +290,7 @@ export interface Payment {
290
290
  resourceVersion: string;
291
291
  }
292
292
 
293
- export type FormPayment = { method: string; amount: string | number; referenceCode?: number | string };
293
+ export type FormPayment = { method: PaymentMethod; amount: string | number; referenceCode?: number | string };
294
294
 
295
295
  export type PaymentFormValue = {
296
296
  payment: Array<FormPayment>;
@@ -139,6 +139,7 @@
139
139
  "identifier": "Identifier",
140
140
  "inactive": "Inactive",
141
141
  "incompletePayment": "Incomplete payment",
142
+ "incompletePaymentSubtitle": "Please ensure all selected line items are fully paid, Total amount expected is {{selectedLineItemsAmountDue}}",
142
143
  "initiatePay": "Initiate Payment",
143
144
  "inputSampleSchema": "Input sample schema",
144
145
  "insuranceScheme": "Insurance scheme",
@@ -186,6 +187,8 @@
186
187
  "noTransactionHistorySubtitle": "No transaction history loaded for the selected filters",
187
188
  "notSearchedState": "Please search for a patient in the input above",
188
189
  "overflowMenu": "Overflow menu",
190
+ "overPayment": "Over payment",
191
+ "overPaymentSubtitle": "Amount paid {{totalAmountTendered}} should not be greater than amount due {{selectedLineItemsAmountDue}} for selected line items",
189
192
  "package": "Package",
190
193
  "packages": "Packages",
191
194
  "packagesOptions": "Choose packages",
@@ -199,8 +202,6 @@
199
202
  "patientMissingSHAId": "Patient missing SHA identification number",
200
203
  "patientMissingSHANumber": "Patient is missing SHA number, SHA validation cannot be done, Advise patient to visit registration desk",
201
204
  "patientName": "Patient Name",
202
- "paymentError": "Payment error",
203
- "paymentErrorSubtitle": "Amount paid {{totalAmountTendered}} should not be greater than amount due {{selectedLineItemsAmountDue}} for selected line items",
204
205
  "paymentHistory": "Payment History",
205
206
  "paymentMethod": "Payment method",
206
207
  "paymentMethodDescription": "Payment method {{methodName}}",