@kenyaemr/esm-billing-app 5.4.1-pre.2093 → 5.4.1-pre.2099

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":"order-action-button","component":"orderActionButton","slots":["prescription-action-button-slot","imaging-orders-action","procedure-orders-action","tests-ordered-actions-slot"],"order":0},{"component":"billingOverviewLink","name":"billing-overview-link","order":0,"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","order":0,"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":"create-bill-workspace","component":"createBillWorkspace","title":"Create Bill Workspace","type":"other-form"},{"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"},{"name":"bill-deposit-workspace","component":"billDepositWorkspace","title":"Bill Deposit Workspace","type":"other-form"}],"modals":[{"name":"create-payment-point","component":"createPaymentPoint"},{"name":"clock-out-modal","component":"clockOut"},{"name":"bulk-import-billable-services-modal","component":"bulkImportBillableServicesModal"},{"name":"delete-payment-mode-modal","component":"deletePaymentModeModal"},{"name":"manage-claim-request-modal","component":"manageClaimRequestModal"},{"name":"paid-bill-receipt-print-preview-modal","component":"paidBillReceiptPrintPreviewModal"},{"name":"clock-in-modal","component":"clockIn"},{"name":"create-bill-item-modal","component":"createBillItemModal"}],"version":"5.4.1-pre.2093"}
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":"order-action-button","component":"orderActionButton","slots":["prescription-action-button-slot","imaging-orders-action","procedure-orders-action","tests-ordered-actions-slot"],"order":0},{"component":"billingOverviewLink","name":"billing-overview-link","order":0,"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","order":0,"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":"create-bill-workspace","component":"createBillWorkspace","title":"Create Bill Workspace","type":"other-form"},{"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"},{"name":"bill-deposit-workspace","component":"billDepositWorkspace","title":"Bill Deposit Workspace","type":"other-form"}],"modals":[{"name":"create-payment-point","component":"createPaymentPoint"},{"name":"clock-out-modal","component":"clockOut"},{"name":"bulk-import-billable-services-modal","component":"bulkImportBillableServicesModal"},{"name":"delete-payment-mode-modal","component":"deletePaymentModeModal"},{"name":"manage-claim-request-modal","component":"manageClaimRequestModal"},{"name":"paid-bill-receipt-print-preview-modal","component":"paidBillReceiptPrintPreviewModal"},{"name":"clock-in-modal","component":"clockIn"},{"name":"create-bill-item-modal","component":"createBillItemModal"}],"version":"5.4.1-pre.2099"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-billing-app",
3
- "version": "5.4.1-pre.2093",
3
+ "version": "5.4.1-pre.2099",
4
4
  "description": "Billing app for KenyaEMR",
5
5
  "browser": "dist/kenyaemr-esm-billing-app.js",
6
6
  "main": "src/index.ts",
@@ -0,0 +1,262 @@
1
+ import {
2
+ DataTable,
3
+ DataTableSkeleton,
4
+ OverflowMenu,
5
+ OverflowMenuItem,
6
+ Pagination,
7
+ Table,
8
+ TableBody,
9
+ TableCell,
10
+ TableContainer,
11
+ TableHead,
12
+ TableHeader,
13
+ TableRow,
14
+ Tag,
15
+ } from '@carbon/react';
16
+ import { formatDate, isDesktop, parseDate, showModal, useLayoutType, usePagination } from '@openmrs/esm-framework';
17
+ import { CardHeader, EmptyState, usePaginationInfo } from '@openmrs/esm-patient-common-lib';
18
+ import React, { useMemo, useState } from 'react';
19
+ import { useTranslation } from 'react-i18next';
20
+ import { Claim, ClaimsPreAuthFilter, DataTableRow, Header, TableProps } from '../../../types';
21
+ import ClaimsFilterHeader from '../header/filter-header.component';
22
+ import styles from './claims-list-table.scss';
23
+ import { useFacilityClaims } from './use-facility-claims';
24
+ import { statusColors } from '../../utils';
25
+
26
+ const ClaimStatus = ({ row }: { row: DataTableRow }) => {
27
+ const { claims } = useFacilityClaims();
28
+ const { t } = useTranslation();
29
+
30
+ const claim = claims.find((claim) => claim.id === row.id) as Claim;
31
+
32
+ // Default to 'gray' if status not found in the mapping
33
+ const tagType = statusColors[claim.status] || 'gray';
34
+
35
+ return (
36
+ <div className={styles.claimStatus}>
37
+ <Tag type={tagType}>{claim.status}</Tag>
38
+ </div>
39
+ );
40
+ };
41
+
42
+ const ClaimsTable: React.FC<TableProps> = ({ title, emptyStateText, emptyStateHeader, includeClaimCode = false }) => {
43
+ const { claims, isLoading } = useFacilityClaims();
44
+ const { t } = useTranslation();
45
+ const [filters, setFilters] = useState<ClaimsPreAuthFilter>({
46
+ status: 'all',
47
+ });
48
+
49
+ const status = useMemo(
50
+ () => [
51
+ { value: 'all', label: t('all', 'All') },
52
+ { value: 'ENTERED', label: t('entered', 'Entered') },
53
+ { value: 'ERRORED', label: t('errored', 'Errored') },
54
+ { value: 'REJECTED', label: t('rejected', 'Rejected') },
55
+ { value: 'CHECKED', label: t('checked', 'Checked') },
56
+ { value: 'VALUATED', label: t('valuated', 'Valuated') },
57
+ { value: 'APPROVED', label: t('approved', 'Approved') },
58
+ ],
59
+ [t],
60
+ );
61
+
62
+ const [pageSize, setPageSize] = useState(5);
63
+
64
+ const filterClaims = (claim: Claim) => {
65
+ const status = filters?.status;
66
+ const search = filters?.search?.toLowerCase();
67
+ const fromDate = filters?.fromDate ? new Date(filters.fromDate) : null;
68
+ const toDate = filters?.toDate ? new Date(filters.toDate) : null;
69
+
70
+ const patientName = claim.patientName?.toLowerCase();
71
+ const providerName = claim.providerName?.toLowerCase();
72
+ const timeStamp = new Date(claim.dateFrom);
73
+ const preauthStatus = claim.status;
74
+
75
+ // Check status (allow 'all' to bypass the filter)
76
+ const statusMatch = status === 'all' || preauthStatus === status;
77
+
78
+ // Check search filter (patient name or provider name contains the search term)
79
+ const searchMatch = !search || patientName?.includes(search) || providerName?.includes(search);
80
+
81
+ // Check date range filter (timestamp is between fromDate and toDate if provided)
82
+ const dateMatch = (!fromDate || timeStamp >= fromDate) && (!toDate || timeStamp <= toDate);
83
+
84
+ // Return true if all conditions match
85
+ return statusMatch && searchMatch && dateMatch;
86
+ };
87
+
88
+ const filteredClaims = claims.filter(filterClaims);
89
+ const { paginated, goTo, results, currentPage } = usePagination(filteredClaims, pageSize);
90
+ const { pageSizes } = usePaginationInfo(pageSize, claims.length, currentPage, results.length);
91
+ const responsiveSize = isDesktop(useLayoutType()) ? 'sm' : 'lg';
92
+ const layout = useLayoutType();
93
+ const size = layout === 'tablet' ? 'lg' : 'md';
94
+
95
+ const getHeaders = (): Header[] => {
96
+ let baseHeaders = [
97
+ { key: 'status', header: t('status', 'Status') },
98
+ { key: 'providerName', header: t('provider', 'Provider') },
99
+ { key: 'patientName', header: t('patient', 'Patient') },
100
+ { key: 'claimedTotal', header: t('claimedAmount', 'Claimed Amount') },
101
+ { key: 'approvedTotal', header: t('approvedTotal', 'Approved Total') },
102
+ { key: 'dateFrom', header: t('dateCreated', 'Date Created') },
103
+ { key: 'action', header: t('action', 'Action') },
104
+ ];
105
+
106
+ if (includeClaimCode) {
107
+ return [{ key: 'claimCode', header: t('claimCode', 'Claim Code') }, ...baseHeaders];
108
+ }
109
+
110
+ return baseHeaders;
111
+ };
112
+
113
+ const headers = getHeaders();
114
+
115
+ if (isLoading) {
116
+ return (
117
+ <div className={styles.dataTableSkeleton}>
118
+ <DataTableSkeleton
119
+ headers={headers}
120
+ showToolbar={false}
121
+ showHeader={false}
122
+ columnCount={Object.keys(headers).length}
123
+ zebra
124
+ rowCount={pageSize}
125
+ />
126
+ </div>
127
+ );
128
+ }
129
+
130
+ if (claims.length === 0) {
131
+ return (
132
+ <div className={styles.claimsTable}>
133
+ <EmptyState displayText={t(emptyStateText)} headerTitle={t(emptyStateHeader)} />
134
+ </div>
135
+ );
136
+ }
137
+
138
+ const handleClaimAction = (claimId: string, modalType: 'retry' | 'update') => {
139
+ const dispose = showModal('manage-claim-request-modal', {
140
+ closeModal: () => dispose(),
141
+ claimId,
142
+ modalType,
143
+ });
144
+ };
145
+
146
+ // Cell rendering functions
147
+ const renderStatusCell = (row: DataTableRow) => {
148
+ return <ClaimStatus row={row} />;
149
+ };
150
+
151
+ const renderActionCell = (row: DataTableRow, rowStatus: string, size: string) => {
152
+ return (
153
+ <OverflowMenu size={size} flipped>
154
+ {['ENTERED', 'ERRORED'].includes(rowStatus) && (
155
+ <OverflowMenuItem
156
+ itemText={t('retryRequest', 'Retry request')}
157
+ onClick={() => handleClaimAction(row.id, 'retry')}
158
+ />
159
+ )}
160
+ <OverflowMenuItem
161
+ itemText={t('updateStatus', 'Update status')}
162
+ onClick={() => handleClaimAction(row.id, 'update')}
163
+ />
164
+ </OverflowMenu>
165
+ );
166
+ };
167
+
168
+ const renderDateFromCell = (cellValue: string) => {
169
+ return formatDate(parseDate(cellValue));
170
+ };
171
+
172
+ const renderApprovedTotalCell = (row: DataTableRow, rowStatus: string, cellValue: any) => {
173
+ if (['APPROVED'].includes(rowStatus)) {
174
+ const claimedTotal = row.cells.find((c) => c.info.header === 'claimedTotal')?.value;
175
+ return claimedTotal || cellValue;
176
+ }
177
+ return cellValue;
178
+ };
179
+
180
+ const renderCellContent = (cell: any, row: DataTableRow, rowStatus: string) => {
181
+ const header = cell.info.header;
182
+
183
+ if (header === 'status') {
184
+ return renderStatusCell(row);
185
+ }
186
+
187
+ if (header === 'action') {
188
+ return renderActionCell(row, rowStatus, size);
189
+ }
190
+
191
+ if (header === 'dateFrom') {
192
+ return renderDateFromCell(cell.value);
193
+ }
194
+
195
+ if (header === 'approvedTotal') {
196
+ return renderApprovedTotalCell(row, rowStatus, cell.value);
197
+ }
198
+
199
+ return cell.value;
200
+ };
201
+
202
+ return (
203
+ <div className={styles.dataTableSkeleton}>
204
+ <div className={styles.tableHeader}>
205
+ <CardHeader title={t(title)}>{''}</CardHeader>
206
+ <ClaimsFilterHeader filters={filters} onFilterChanged={setFilters} statusOptions={status} />
207
+ </div>
208
+ <DataTable rows={results} headers={headers} isSortable useZebraStyles>
209
+ {({ rows, headers, getHeaderProps, getRowProps, getTableProps }) => (
210
+ <TableContainer className={styles.claimsTable}>
211
+ <Table {...getTableProps()} aria-label="sample table">
212
+ <TableHead>
213
+ <TableRow>
214
+ {headers.map((header) => (
215
+ <TableHeader
216
+ key={header.key}
217
+ {...getHeaderProps({
218
+ header,
219
+ })}>
220
+ {header.header}
221
+ </TableHeader>
222
+ ))}
223
+ </TableRow>
224
+ </TableHead>
225
+ <TableBody>
226
+ {rows.map((row) => {
227
+ const rowStatus = row.cells.find((cell) => cell.info.header === 'status')?.value;
228
+ return (
229
+ <TableRow key={row.id} {...getRowProps({ row })}>
230
+ {row.cells.map((cell) => (
231
+ <TableCell key={cell.id}>{renderCellContent(cell, row, rowStatus)}</TableCell>
232
+ ))}
233
+ </TableRow>
234
+ );
235
+ })}
236
+ </TableBody>
237
+ </Table>
238
+ {paginated && !isLoading && (
239
+ <Pagination
240
+ forwardText=""
241
+ backwardText=""
242
+ page={currentPage}
243
+ pageSize={pageSize}
244
+ pageSizes={pageSizes}
245
+ totalItems={filteredClaims.length}
246
+ size={responsiveSize}
247
+ onChange={({ page: newPage, pageSize }) => {
248
+ if (newPage !== currentPage) {
249
+ goTo(newPage);
250
+ }
251
+ setPageSize(pageSize);
252
+ }}
253
+ />
254
+ )}
255
+ </TableContainer>
256
+ )}
257
+ </DataTable>
258
+ </div>
259
+ );
260
+ };
261
+
262
+ export default ClaimsTable;