@zeniai/client-epic-state 4.19.84-betaVR1 → 4.19.84-betaVR11
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/lib/esm/index.js +4 -1
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +7 -3
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +1 -1
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +1 -1
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +1 -1
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +14 -4
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +20 -3
- package/lib/esm/view/expenseAutomationView/payload/missingReceiptsPayload.js +38 -9
- package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +25 -14
- package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +32 -31
- package/lib/esm/view/expenseAutomationView/types/missingReceiptsViewState.js +39 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +44 -33
- package/lib/tsconfig.typecheck.tsbuildinfo +1 -0
- package/lib/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +7 -3
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +1 -1
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +1 -1
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +1 -1
- package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +13 -3
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +7 -1
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +20 -3
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.d.ts +12 -1
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.js +39 -9
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +3 -3
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +25 -14
- package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +32 -31
- package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +27 -9
- package/lib/view/expenseAutomationView/types/missingReceiptsViewState.js +49 -1
- package/package.json +2 -2
package/lib/esm/index.js
CHANGED
|
@@ -169,6 +169,7 @@ import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fet
|
|
|
169
169
|
import { getExpenseAutomationFluxAnalysisView } from './view/expenseAutomationView/selectors/fluxAnalysisViewSelector';
|
|
170
170
|
import { getExpenseAutomationReconciliationView, isAccountReconReport, } from './view/expenseAutomationView/selectors/reconciliationViewSelector';
|
|
171
171
|
import { getExpenseAutomationTransactionView } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
|
|
172
|
+
import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, } from './view/expenseAutomationView/types/missingReceiptsViewState';
|
|
172
173
|
import { toMissingReceiptsSortKey as toExpenseAutomationMissingReceiptsSortKey, } from './view/expenseAutomationView/types/missingReceiptsViewState';
|
|
173
174
|
import { toReconciliationTabsType, } from './view/expenseAutomationView/types/reconciliationViewState';
|
|
174
175
|
import { toTransactionsTabKey as toExpenseAutomationTransactionsTabKey, toTransactionsSortKey, } from './view/expenseAutomationView/types/transactionsViewState';
|
|
@@ -415,7 +416,9 @@ export { newBalancesFilterClassesView };
|
|
|
415
416
|
export { toCOABalanceTypeStrict, toCOABalanceType as toCOABlanaceType, isCalculatedBalanceType, };
|
|
416
417
|
export { stringToUnion, stringToUnionStrict };
|
|
417
418
|
export { fetchMonthEndCloseChecks, fetchMonthClosePerformanceTrend, getMonthEndCloseChecksViewByTenantId, ALL_MONTH_END_CLOSE_CHECKS_FREQUENCY, };
|
|
418
|
-
export {
|
|
419
|
+
export {
|
|
420
|
+
// Bulk Upload Types
|
|
421
|
+
BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, fetchExpenseAutomationMissingReceipts,
|
|
419
422
|
// Bulk Upload Actions
|
|
420
423
|
bulkUploadReceipts, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete, fetchCompletedTransactions, fetchCompletedTransactionsSuccess, fetchCompletedTransactionsFailure, fetchFluxAnalysisView, clearExpenseAutomationFluxAnalysisView, updateOperatingExpensesIdsForReview as updateFluxOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview as updateFluxAnalysisSelectedSectionIdsForReview, reviewFluxAnalysisView, updateExpenseAutomationMissingReceiptUploadState, updateExpenseAutomationMissingReceiptsUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, getExpenseAutomationFluxAnalysisView, updateCurrentSelectedView, updateCurrentSelectedPeriod, getExpenseAutomationTransactionView, updateFluxAnalysisViewUIState, updateFluxAnalysisViewPageMetaData, MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, saveExpenseAutomationReconciliationDetail, updateExpenseAutomationReconcileTabListScrollState, updateExpenseAutomationReconReviewTabListSortState, updateExpenseAutomationReconcileTabListSortState, updateExpenseAutomationReconcileTabLocalData, updateExpenseAutomationAccountReconciliationSelectedTab, updateExpenseAutomationAccountReconciliationSelectedAccountId, getExpenseAutomationReconciliationView, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, getAccountReconByAccountIdAndSelectedPeriod, toReconciliationTabsType, isAccountReconReport, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, toReconciliationAccountSource, deleteAccountStatement, uploadAccountStatement, updateStatementUploadChosen, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, };
|
|
421
424
|
export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
|
|
@@ -12,9 +12,13 @@ export const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.p
|
|
|
12
12
|
.postFormData(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/receipts/bulk-upload`, formData)
|
|
13
13
|
.pipe(mergeMap((response) => {
|
|
14
14
|
if (isSuccessResponse(response) && response.data != null) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const batchId = String(response.data.batch_id ?? '').trim();
|
|
16
|
+
if (batchId === '') {
|
|
17
|
+
return of(bulkUploadReceiptsFailure({
|
|
18
|
+
error: createZeniAPIStatus('Unexpected Error', 'Bulk upload succeeded but batch_id was missing or empty.'),
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
return of(bulkUploadReceiptsSuccess({ batchId }));
|
|
18
22
|
}
|
|
19
23
|
return of(bulkUploadReceiptsFailure({ error: response.status }));
|
|
20
24
|
}), catchError((error) => of(bulkUploadReceiptsFailure({
|
package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js
CHANGED
|
@@ -32,7 +32,7 @@ export const fetchBulkUploadBatchDetailsEpic = (actions$, state$, zeniAPI) => ac
|
|
|
32
32
|
actions.push(updateTransactions(transactionPayloads, (value) => value.transaction_id));
|
|
33
33
|
}
|
|
34
34
|
actions.push(fetchBulkUploadBatchDetailsSuccess(toBatchDetails(response.data, zeniAPI.apiEndPoints.fileMicroServiceBaseUrl)));
|
|
35
|
-
actions.push(fetchBulkUploadBatches(true));
|
|
35
|
+
actions.push(fetchBulkUploadBatches({ cacheOverride: true }));
|
|
36
36
|
return from(actions);
|
|
37
37
|
}), catchError((error) => of(fetchBulkUploadBatchDetailsFailure({
|
|
38
38
|
error: createZeniAPIStatus('Unexpected Error', 'Fetch batch details errored out: ' + JSON.stringify(error)),
|
package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createZeniAPIStatus } from '../../../../responsePayload';
|
|
|
6
6
|
import { filterBatchListItemsForBatchDetailsFetch } from '../../payload/missingReceiptsPayload';
|
|
7
7
|
import { fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, } from '../../reducers/missingReceiptsViewReducer';
|
|
8
8
|
import { fetchBatchDetailsByIds } from './fetchMultipleBatchDetailsEpic';
|
|
9
|
-
const MORE_BATCH_PAGE_SIZE =
|
|
9
|
+
const MORE_BATCH_PAGE_SIZE = 5;
|
|
10
10
|
export const fetchMoreBatchDetailsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchMoreBatchDetails.match),
|
|
11
11
|
/** One page at a time — avoids duplicate loads if IO + scroll fallback both fire. */
|
|
12
12
|
exhaustMap(() => {
|
package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js
CHANGED
|
@@ -4,7 +4,7 @@ import { updateTransactions } from '../../../../entity/transaction/transactionRe
|
|
|
4
4
|
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
|
|
5
5
|
import { extractTransactionPayloadsFromBatchFiles, filterBatchListItemsForBatchDetailsFetch, isBatchDetailsApiStatusCompleted, shouldFetchBatchDetailsForBatchId, toBatchDetails, } from '../../payload/missingReceiptsPayload';
|
|
6
6
|
import { batchDetailFetchFailed, fetchBulkUploadBatchDetails, fetchBulkUploadBatchesSuccess, fetchMoreBatchDetailsComplete, setInitialBatchDetailsLoading, storeBatchDetails, } from '../../reducers/missingReceiptsViewReducer';
|
|
7
|
-
const INITIAL_BATCH_PAGE_SIZE =
|
|
7
|
+
const INITIAL_BATCH_PAGE_SIZE = 5;
|
|
8
8
|
export function fetchBatchDetailsByIds(batchIds, zeniAPI) {
|
|
9
9
|
if (batchIds.length === 0) {
|
|
10
10
|
return EMPTY;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { from, merge, of } from 'rxjs';
|
|
1
|
+
import { EMPTY, from, merge, of } from 'rxjs';
|
|
2
2
|
import { catchError, debounceTime, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
3
|
import { convertToPeriod } from '../../../../commonStateTypes/timePeriod';
|
|
4
4
|
import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
|
|
@@ -15,10 +15,20 @@ import { toTransactionsSortKey } from '../../types/transactionsViewState';
|
|
|
15
15
|
export const MANUAL_TRANSACTION_SEARCH_AUTO_CATEGORIZED = false;
|
|
16
16
|
export const searchTransactionsForManualMatchEpic = (actions$, state$, zeniAPI) => {
|
|
17
17
|
const searchActions$ = actions$.pipe(filter(searchTransactionsForManualMatch.match));
|
|
18
|
-
const pagination$ = searchActions$.pipe(filter((
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const pagination$ = searchActions$.pipe(filter((action) => action.payload.pageToken != null));
|
|
19
|
+
/**
|
|
20
|
+
* No API for empty or 1-char queries; immediate merge so switchMap cancels any in-flight HTTP.
|
|
21
|
+
*/
|
|
22
|
+
const newSearchTooShortOrClear$ = searchActions$.pipe(filter((action) => action.payload.pageToken == null &&
|
|
23
|
+
action.payload.query.trim().length < 2));
|
|
24
|
+
const newSearchDebounced$ = searchActions$.pipe(filter((action) => action.payload.pageToken == null &&
|
|
25
|
+
action.payload.query.trim().length >= 2), debounceTime(300));
|
|
26
|
+
return merge(pagination$, newSearchTooShortOrClear$, newSearchDebounced$).pipe(switchMap((action) => {
|
|
21
27
|
const { query, pageToken } = action.payload;
|
|
28
|
+
if (pageToken == null &&
|
|
29
|
+
query.trim().length < 2) {
|
|
30
|
+
return EMPTY;
|
|
31
|
+
}
|
|
22
32
|
const state = state$.value;
|
|
23
33
|
const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationMissingReceiptsViewState: { bulkUpload: { manualSearch, sortKey, sortOrder }, }, } = state;
|
|
24
34
|
const currentTenant = getCurrentTenant(state);
|
package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EMPTY, from, merge, of, timer } from 'rxjs';
|
|
2
2
|
import { catchError, debounceTime, filter, mergeMap, switchMap, takeUntil, } from 'rxjs/operators';
|
|
3
|
+
import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
|
|
3
4
|
import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
|
|
4
5
|
import { isSuccessResponse } from '../../../../responsePayload';
|
|
5
6
|
import { extractTransactionPayloadsFromBatchFiles, isBatchDetailsApiStatusCompleted, toBatchDetails, } from '../../payload/missingReceiptsPayload';
|
|
@@ -18,9 +19,15 @@ export const pusherBatchStatusCompletionEpic = (actions$) => actions$.pipe(filte
|
|
|
18
19
|
}),
|
|
19
20
|
requestMissingReceiptsTabNavigation({ tab: 'unmatched' }),
|
|
20
21
|
])));
|
|
22
|
+
/**
|
|
23
|
+
* Fallback polling when Pusher is slow or unavailable. Network errors on a poll tick show one
|
|
24
|
+
* error snackbar per upload session (first failure only) so the user is not spammed every
|
|
25
|
+
* interval; Pusher or a later successful poll still completes the flow.
|
|
26
|
+
*/
|
|
21
27
|
export const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceiptsSuccess.match), mergeMap((action) => {
|
|
22
28
|
const { batchId } = action.payload;
|
|
23
|
-
|
|
29
|
+
let pollErrorNotified = false;
|
|
30
|
+
return timer(FALLBACK_FIRST_DELAY_MS, FALLBACK_POLL_INTERVAL_MS).pipe(takeUntil(merge(actions$.pipe(filter(clearBulkUpload.match)), actions$.pipe(filter(pusherBatchStatusUpdate.match), filter((action) => action.payload.batchId === batchId)), actions$.pipe(filter(fetchBulkUploadBatchDetailsSuccess.match), filter((action) => action.payload.batchId === batchId)))), switchMap(() => zeniAPI
|
|
24
31
|
.getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/${batchId}`)
|
|
25
32
|
.pipe(mergeMap((response) => {
|
|
26
33
|
/** Same batch-details URL; polls until `status` is completed (Pusher may win first). */
|
|
@@ -32,11 +39,21 @@ export const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => act
|
|
|
32
39
|
actions.push(updateTransactions(transactionPayloads, (value) => value.transaction_id));
|
|
33
40
|
}
|
|
34
41
|
actions.push(fetchBulkUploadBatchDetailsSuccess(toBatchDetails(response.data, zeniAPI.apiEndPoints.fileMicroServiceBaseUrl)));
|
|
35
|
-
actions.push(fetchBulkUploadBatches(true));
|
|
42
|
+
actions.push(fetchBulkUploadBatches({ cacheOverride: true }));
|
|
36
43
|
actions.push(requestMissingReceiptsTabNavigation({ tab: 'unmatched' }));
|
|
37
44
|
return from(actions);
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
return EMPTY;
|
|
41
|
-
}), catchError(() =>
|
|
48
|
+
}), catchError(() => {
|
|
49
|
+
if (!pollErrorNotified) {
|
|
50
|
+
pollErrorNotified = true;
|
|
51
|
+
return of(openSnackbar({
|
|
52
|
+
messageSection: 'receipts_upload',
|
|
53
|
+
messageText: 'failed',
|
|
54
|
+
type: 'error',
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
return EMPTY;
|
|
58
|
+
}))));
|
|
42
59
|
}));
|
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
import { toURL } from '../../../commonPayloadTypes/urlPayload';
|
|
2
2
|
import { getTransactionPayloadAmount, } from '../../../entity/transaction/payloadTypes/transactionPayload';
|
|
3
|
+
import { toBatchStatusValue, toMatchSource, } from '../types/missingReceiptsViewState';
|
|
3
4
|
// -- Converter functions --
|
|
5
|
+
/**
|
|
6
|
+
* Maps batch-details API `files[].status` strings to canonical {@link BatchFileStatus}.
|
|
7
|
+
* Legacy aliases are supported during rollout; unknown strings map to `failed` so Redux never
|
|
8
|
+
* holds untyped status values.
|
|
9
|
+
*/
|
|
10
|
+
export function parseBatchFileStatus(raw) {
|
|
11
|
+
const normalizedStatus = raw.trim().toLowerCase().replace(/-/g, '_');
|
|
12
|
+
switch (normalizedStatus) {
|
|
13
|
+
case 'exact_match':
|
|
14
|
+
case 'matched':
|
|
15
|
+
return 'exact_match';
|
|
16
|
+
case 'possible_matches':
|
|
17
|
+
case 'possible_match':
|
|
18
|
+
case 'possiblematch':
|
|
19
|
+
case 'un_matched':
|
|
20
|
+
case 'unmatched':
|
|
21
|
+
return 'possible_matches';
|
|
22
|
+
case 'no_match':
|
|
23
|
+
case 'nomatch':
|
|
24
|
+
return 'no_match';
|
|
25
|
+
case 'failed':
|
|
26
|
+
return 'failed';
|
|
27
|
+
default:
|
|
28
|
+
return 'failed';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
4
31
|
export function toBatchFile(payload, filesEndPoint) {
|
|
5
32
|
return {
|
|
6
33
|
attachmentId: payload.attachment_id,
|
|
7
|
-
candidates: payload.candidates?.map((
|
|
8
|
-
transactionId:
|
|
9
|
-
matchScore:
|
|
34
|
+
candidates: payload.candidates?.map((candidate) => ({
|
|
35
|
+
transactionId: candidate.transaction_id,
|
|
36
|
+
matchScore: candidate.match_score,
|
|
10
37
|
})),
|
|
11
38
|
fileDownloadUrl: payload.file_id != null && filesEndPoint != null
|
|
12
39
|
? `${filesEndPoint}/1.0/files/${payload.file_id}?query=${encodeURIComponent(JSON.stringify({ download_file: true }))}`
|
|
@@ -14,9 +41,11 @@ export function toBatchFile(payload, filesEndPoint) {
|
|
|
14
41
|
fileId: payload.file_id,
|
|
15
42
|
filePreviewUrl: payload.file_preview_url,
|
|
16
43
|
filename: payload.filename,
|
|
17
|
-
matchSource: payload.match_source
|
|
44
|
+
matchSource: payload.match_source != null
|
|
45
|
+
? toMatchSource(payload.match_source)
|
|
46
|
+
: undefined,
|
|
18
47
|
matchedTransactionId: payload.matched_transaction?.transaction_id,
|
|
19
|
-
status: payload.status,
|
|
48
|
+
status: parseBatchFileStatus(payload.status),
|
|
20
49
|
};
|
|
21
50
|
}
|
|
22
51
|
export function extractTransactionPayloadsFromBatchFiles(files) {
|
|
@@ -66,8 +95,8 @@ export function toBatchDetails(payload, filesEndPoint) {
|
|
|
66
95
|
return {
|
|
67
96
|
batchId: payload.batch_id,
|
|
68
97
|
createdAt: payload.created_at,
|
|
69
|
-
files: payload.files.map((
|
|
70
|
-
status: payload.status,
|
|
98
|
+
files: payload.files.map((file) => toBatchFile(file, filesEndPoint)),
|
|
99
|
+
status: toBatchStatusValue(payload.status),
|
|
71
100
|
summary: toBatchSummary(payload.summary),
|
|
72
101
|
};
|
|
73
102
|
}
|
|
@@ -81,7 +110,7 @@ export function isBatchListStatusCompleted(status) {
|
|
|
81
110
|
* statuses for UI; only `completed` rows should trigger batch-details requests.
|
|
82
111
|
*/
|
|
83
112
|
export function filterBatchListItemsForBatchDetailsFetch(batches) {
|
|
84
|
-
return batches.filter((
|
|
113
|
+
return batches.filter((batch) => isBatchListStatusCompleted(batch.status));
|
|
85
114
|
}
|
|
86
115
|
/**
|
|
87
116
|
* Batch details API response `status` field — only completed payloads should be stored from
|
|
@@ -92,7 +121,7 @@ export function isBatchDetailsApiStatusCompleted(status) {
|
|
|
92
121
|
}
|
|
93
122
|
export function findBatchListItemForBatchId(batchListByPeriod, batchId) {
|
|
94
123
|
for (const list of Object.values(batchListByPeriod)) {
|
|
95
|
-
const found = list.find((
|
|
124
|
+
const found = list.find((batch) => batch.batchId === batchId);
|
|
96
125
|
if (found != null) {
|
|
97
126
|
return found;
|
|
98
127
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
2
|
import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
|
|
3
|
+
import { MIN_MANUAL_TRANSACTION_SEARCH_LENGTH, } from '../types/missingReceiptsViewState';
|
|
3
4
|
export const getCompletedTransactionsCacheKey = (periodId, sortKey, sortOrder, subTab) => `completed-${subTab}-${sortKey}-${sortOrder === 'ascending' ? 'asc' : 'desc'}-${periodId}`;
|
|
4
5
|
export const initialBulkUploadState = {
|
|
5
6
|
batchDetailsById: {},
|
|
@@ -285,19 +286,11 @@ const expenseAutomationMissingReceiptsView = createSlice({
|
|
|
285
286
|
};
|
|
286
287
|
},
|
|
287
288
|
prepare(input) {
|
|
288
|
-
|
|
289
|
-
return {
|
|
290
|
-
payload: {
|
|
291
|
-
cacheOverride: input === true,
|
|
292
|
-
invalidateBatchDetailsCache: false,
|
|
293
|
-
},
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
const o = input ?? {};
|
|
289
|
+
const fetchOptions = input ?? {};
|
|
297
290
|
return {
|
|
298
291
|
payload: {
|
|
299
|
-
cacheOverride:
|
|
300
|
-
invalidateBatchDetailsCache:
|
|
292
|
+
cacheOverride: fetchOptions.cacheOverride === true,
|
|
293
|
+
invalidateBatchDetailsCache: fetchOptions.invalidateBatchDetailsCache === true,
|
|
301
294
|
},
|
|
302
295
|
};
|
|
303
296
|
},
|
|
@@ -350,17 +343,17 @@ const expenseAutomationMissingReceiptsView = createSlice({
|
|
|
350
343
|
};
|
|
351
344
|
const details = draft.bulkUpload.batchDetailsById[batchId];
|
|
352
345
|
if (details != null) {
|
|
353
|
-
const file = details.files.find((
|
|
346
|
+
const file = details.files.find((batchFile) => batchFile.attachmentId === attachmentId);
|
|
354
347
|
if (file != null) {
|
|
355
348
|
const originalStatus = file.status;
|
|
356
|
-
file.status = '
|
|
349
|
+
file.status = 'exact_match';
|
|
357
350
|
file.matchedTransactionId = transactionId;
|
|
358
351
|
file.candidates = undefined;
|
|
359
352
|
details.summary.matched += 1;
|
|
360
353
|
if (originalStatus === 'no_match') {
|
|
361
354
|
details.summary.noMatch = Math.max(0, details.summary.noMatch - 1);
|
|
362
355
|
}
|
|
363
|
-
else {
|
|
356
|
+
else if (originalStatus === 'possible_matches') {
|
|
364
357
|
details.summary.possibleMatches = Math.max(0, details.summary.possibleMatches - 1);
|
|
365
358
|
}
|
|
366
359
|
}
|
|
@@ -392,6 +385,24 @@ const expenseAutomationMissingReceiptsView = createSlice({
|
|
|
392
385
|
reducer(draft, action) {
|
|
393
386
|
const { query, pageToken } = action.payload;
|
|
394
387
|
const isLoadMore = pageToken != null;
|
|
388
|
+
const trimmed = query.trim();
|
|
389
|
+
/**
|
|
390
|
+
* Cleared or too-short query: no API (see epic). Reset fully (no In-Progress).
|
|
391
|
+
* Only bump `manualSearchUiResetKey` when clearing a real search — not when the UI
|
|
392
|
+
* dispatches `""` on every keystroke while length is below MIN (web-components always sends
|
|
393
|
+
* `onSearch("")` in that case), or ReceiptCard remounts and the input loses focus.
|
|
394
|
+
*/
|
|
395
|
+
if (!isLoadMore &&
|
|
396
|
+
trimmed.length < MIN_MANUAL_TRANSACTION_SEARCH_LENGTH) {
|
|
397
|
+
const hadActiveSearch = draft.bulkUpload.manualSearch.searchQuery.trim().length >=
|
|
398
|
+
MIN_MANUAL_TRANSACTION_SEARCH_LENGTH ||
|
|
399
|
+
draft.bulkUpload.manualSearch.results.length > 0;
|
|
400
|
+
draft.bulkUpload.manualSearch = initialBulkUploadState.manualSearch;
|
|
401
|
+
if (hadActiveSearch) {
|
|
402
|
+
draft.bulkUpload.manualSearchUiResetKey += 1;
|
|
403
|
+
}
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
395
406
|
draft.bulkUpload.manualSearch.searchQuery = query;
|
|
396
407
|
if (isLoadMore) {
|
|
397
408
|
draft.bulkUpload.manualSearch.isLoadingMore = true;
|
|
@@ -5,6 +5,7 @@ import { getSupportedTransactionById, getSupportedTransactionsByIds, } from '../
|
|
|
5
5
|
import { getAllSteps } from '../selectorTypes/expenseAutomationViewSelectorTypes';
|
|
6
6
|
import { isBatchListStatusCompleted } from '../payload/missingReceiptsPayload';
|
|
7
7
|
import { getCompletedTransactionsCacheKey } from '../reducers/missingReceiptsViewReducer';
|
|
8
|
+
import { isUnmatchedTabFileStatus, } from '../types/missingReceiptsViewState';
|
|
8
9
|
export function getExpenseAutomationMissingReceiptsView(state) {
|
|
9
10
|
const { expenseAutomationMissingReceiptsViewState, expenseAutomationViewState, transactionState, monthEndCloseChecksState, } = state;
|
|
10
11
|
const currentTenant = getCurrentTenant(state);
|
|
@@ -58,7 +59,7 @@ export function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
58
59
|
: [];
|
|
59
60
|
/**
|
|
60
61
|
* Primary "Unmatched" batch = first completed batch in platform list order, preferring the
|
|
61
|
-
* first batch that still has
|
|
62
|
+
* first batch that still has possible_matches/no_match work when any completed batch has such work.
|
|
62
63
|
* Batches without details yet: wait if the list row still reports unmatched work; otherwise skip
|
|
63
64
|
* so we do not block the whole tab while other rows are not fetched yet.
|
|
64
65
|
*/
|
|
@@ -67,41 +68,41 @@ export function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
67
68
|
const unmatchedSectionBatchId = bulkUpload.phase === 'matching' || bulkUpload.phase === 'uploading'
|
|
68
69
|
? bulkUpload.currentBatchId ?? primaryBatchIdFromDetailsOrder
|
|
69
70
|
: primaryBatchIdFromDetailsOrder;
|
|
70
|
-
const completedBatchesInApiOrder = batchList.filter((
|
|
71
|
+
const completedBatchesInApiOrder = batchList.filter((batchListItem) => isBatchListStatusCompleted(batchListItem.status));
|
|
71
72
|
const currentBatchDetails = unmatchedSectionBatchId != null
|
|
72
73
|
? bulkUpload.batchDetailsById[unmatchedSectionBatchId]
|
|
73
74
|
: undefined;
|
|
74
75
|
const resolvedFiles = currentBatchDetails?.files.map((file) => resolveBatchFile(file, currentBatchDetails.batchId, transactionState));
|
|
75
76
|
const failedIds = new Set(bulkUpload.failedBatchDetailIds);
|
|
76
|
-
const hasMoreBatchDetails = completedBatchesInApiOrder.some((
|
|
77
|
-
!failedIds.has(
|
|
77
|
+
const hasMoreBatchDetails = completedBatchesInApiOrder.some((batchListItem) => bulkUpload.batchDetailsById[batchListItem.batchId] == null &&
|
|
78
|
+
!failedIds.has(batchListItem.batchId));
|
|
78
79
|
const getSortValue = (file) => {
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
80
|
+
const matchedTransaction = file.matchedTransaction;
|
|
81
|
+
if (matchedTransaction == null) {
|
|
81
82
|
return null;
|
|
82
83
|
}
|
|
83
84
|
switch (bulkUpload.sortKey) {
|
|
84
85
|
case 'vendor':
|
|
85
|
-
return (
|
|
86
|
+
return (matchedTransaction.vendorName ?? matchedTransaction.description)?.toLowerCase() ?? null;
|
|
86
87
|
case 'category': {
|
|
87
|
-
const line =
|
|
88
|
+
const line = matchedTransaction.lines?.[0];
|
|
88
89
|
return line?.account?.accountName?.toLowerCase() ?? null;
|
|
89
90
|
}
|
|
90
91
|
case 'class': {
|
|
91
|
-
const line =
|
|
92
|
+
const line = matchedTransaction.lines?.[0];
|
|
92
93
|
return line?.class?.className?.toLowerCase() ?? null;
|
|
93
94
|
}
|
|
94
95
|
case 'date':
|
|
95
|
-
return
|
|
96
|
+
return matchedTransaction.date.valueOf();
|
|
96
97
|
case 'amount':
|
|
97
|
-
return
|
|
98
|
+
return matchedTransaction.amount.amount;
|
|
98
99
|
default:
|
|
99
100
|
return null;
|
|
100
101
|
}
|
|
101
102
|
};
|
|
102
103
|
const bulkUploadSortDirection = bulkUpload.sortOrder === 'ascending' ? 'asc' : 'desc';
|
|
103
|
-
const matchedFiles = orderBy(resolvedFiles?.filter((
|
|
104
|
-
const unmatchedFiles = orderBy(resolvedFiles?.filter((
|
|
104
|
+
const matchedFiles = orderBy(resolvedFiles?.filter((resolvedFile) => resolvedFile.status === 'exact_match') ?? [], getSortValue, bulkUploadSortDirection);
|
|
105
|
+
const unmatchedFiles = orderBy(resolvedFiles?.filter((resolvedFile) => isUnmatchedTabFileStatus(resolvedFile.status)) ?? [], getSortValue, bulkUploadSortDirection);
|
|
105
106
|
const progress = currentBatchStatus != null
|
|
106
107
|
? {
|
|
107
108
|
...currentBatchStatus.progress,
|
|
@@ -118,16 +119,16 @@ export function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
118
119
|
* that has details loaded (otherwise past is empty and receipts vanish from the UI).
|
|
119
120
|
*/
|
|
120
121
|
const pastBatches = unmatchedSectionBatchId != null
|
|
121
|
-
? batchList.filter((
|
|
122
|
+
? batchList.filter((batchListItem) => batchListItem.batchId !== unmatchedSectionBatchId)
|
|
122
123
|
: batchList;
|
|
123
|
-
const pastUnmatchedFiles = pastBatches.flatMap((
|
|
124
|
-
const details = bulkUpload.batchDetailsById[
|
|
124
|
+
const pastUnmatchedFiles = pastBatches.flatMap((pastBatch) => {
|
|
125
|
+
const details = bulkUpload.batchDetailsById[pastBatch.batchId];
|
|
125
126
|
if (details == null) {
|
|
126
127
|
return [];
|
|
127
128
|
}
|
|
128
129
|
return details.files
|
|
129
|
-
.filter((
|
|
130
|
-
.map((
|
|
130
|
+
.filter((batchFile) => isUnmatchedTabFileStatus(batchFile.status))
|
|
131
|
+
.map((batchFile) => resolveBatchFile(batchFile, pastBatch.batchId, transactionState));
|
|
131
132
|
});
|
|
132
133
|
const completedTransactionsCacheKey = monthYearPeriodId != null
|
|
133
134
|
? getCompletedTransactionsCacheKey(monthYearPeriodId, bulkUpload.sortKey, bulkUpload.sortOrder, bulkUpload.completedSubTab)
|
|
@@ -146,11 +147,11 @@ export function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
146
147
|
summary: currentBatchDetails.summary,
|
|
147
148
|
}
|
|
148
149
|
: undefined;
|
|
149
|
-
const manualSearchResults = bulkUpload.manualSearch.results.map((
|
|
150
|
-
const
|
|
150
|
+
const manualSearchResults = bulkUpload.manualSearch.results.map((result) => {
|
|
151
|
+
const transaction = getSupportedTransactionById(transactionState, result.transactionId);
|
|
151
152
|
return {
|
|
152
|
-
...
|
|
153
|
-
vendorLogo:
|
|
153
|
+
...result,
|
|
154
|
+
vendorLogo: result.vendorLogo ?? transaction?.logo?.href,
|
|
154
155
|
};
|
|
155
156
|
});
|
|
156
157
|
return {
|
|
@@ -200,7 +201,7 @@ export function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
200
201
|
};
|
|
201
202
|
}
|
|
202
203
|
function batchDetailsHasUnmatchedWork(details) {
|
|
203
|
-
return details.files.some((
|
|
204
|
+
return details.files.some((file) => isUnmatchedTabFileStatus(file.status));
|
|
204
205
|
}
|
|
205
206
|
/** List row summary before batch details load — aligns with unmatched / possible-match work. */
|
|
206
207
|
function batchListItemHasUnmatchedWork(batch) {
|
|
@@ -217,17 +218,17 @@ function batchListItemHasUnmatchedWork(batch) {
|
|
|
217
218
|
*/
|
|
218
219
|
function getPrimaryBatchIdFromBatchListOrder(batchListInPlatformOrder, batchDetailsById, failedBatchDetailIds) {
|
|
219
220
|
const failedIds = new Set(failedBatchDetailIds);
|
|
220
|
-
const anyCompletedBatchHasUnmatchedWork = batchListInPlatformOrder.some((
|
|
221
|
-
if (failedIds.has(
|
|
221
|
+
const anyCompletedBatchHasUnmatchedWork = batchListInPlatformOrder.some((batch) => {
|
|
222
|
+
if (failedIds.has(batch.batchId)) {
|
|
222
223
|
return false;
|
|
223
224
|
}
|
|
224
|
-
const
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
batchDetailsHasUnmatchedWork(
|
|
225
|
+
const details = batchDetailsById[batch.batchId];
|
|
226
|
+
if (details != null &&
|
|
227
|
+
details.status === 'completed' &&
|
|
228
|
+
batchDetailsHasUnmatchedWork(details)) {
|
|
228
229
|
return true;
|
|
229
230
|
}
|
|
230
|
-
return
|
|
231
|
+
return details == null && batchListItemHasUnmatchedWork(batch);
|
|
231
232
|
});
|
|
232
233
|
for (const batch of batchListInPlatformOrder) {
|
|
233
234
|
if (failedIds.has(batch.batchId)) {
|
|
@@ -264,7 +265,7 @@ function resolveBatchFile(file, batchId, transactionState) {
|
|
|
264
265
|
? { transaction, matchScore: ref.matchScore }
|
|
265
266
|
: undefined;
|
|
266
267
|
})
|
|
267
|
-
.filter((
|
|
268
|
+
.filter((candidate) => candidate != null);
|
|
268
269
|
return {
|
|
269
270
|
attachmentId: file.attachmentId,
|
|
270
271
|
batchId,
|
|
@@ -7,3 +7,42 @@ const MISSING_RECEIPTS_SORT_KEYS = [
|
|
|
7
7
|
'amount',
|
|
8
8
|
];
|
|
9
9
|
export const toMissingReceiptsSortKey = (v) => stringToUnion(v, MISSING_RECEIPTS_SORT_KEYS);
|
|
10
|
+
// -- Bulk Receipt Upload Types --
|
|
11
|
+
/**
|
|
12
|
+
* Minimum trimmed query length before manual-match search calls the expense-automation API.
|
|
13
|
+
* Kept in sync with `ManualSearchInput` in web-components (fires search only when length ≥ this).
|
|
14
|
+
*/
|
|
15
|
+
export const MIN_MANUAL_TRANSACTION_SEARCH_LENGTH = 2;
|
|
16
|
+
const BATCH_STATUS_VALUES = ['pending', 'processing', 'completed'];
|
|
17
|
+
export const toBatchStatusValue = (v) => stringToUnion(v.trim().toLowerCase(), BATCH_STATUS_VALUES);
|
|
18
|
+
/** Canonical batch file statuses (API ingress may use aliases; see `parseBatchFileStatus`). */
|
|
19
|
+
export const BATCH_FILE_STATUSES = [
|
|
20
|
+
'exact_match',
|
|
21
|
+
'possible_matches',
|
|
22
|
+
'no_match',
|
|
23
|
+
'failed',
|
|
24
|
+
];
|
|
25
|
+
export const toBatchFileStatus = (v) => stringToUnion(v.trim().toLowerCase().replace(/-/g, '_'), BATCH_FILE_STATUSES);
|
|
26
|
+
const UNMATCHED_TAB_FILE_STATUSES = ['possible_matches', 'no_match'];
|
|
27
|
+
/** True for files that belong in the Unmatched tab (possible matches or no match). */
|
|
28
|
+
export function isUnmatchedTabFileStatus(status) {
|
|
29
|
+
return UNMATCHED_TAB_FILE_STATUSES.includes(status);
|
|
30
|
+
}
|
|
31
|
+
const BULK_UPLOAD_PHASES = ['idle', 'uploading', 'matching', 'completed'];
|
|
32
|
+
export const toBulkUploadPhase = (v) => stringToUnion(v.trim().toLowerCase(), BULK_UPLOAD_PHASES);
|
|
33
|
+
const BULK_UPLOAD_RESULTS_TABS = ['completed', 'unmatched'];
|
|
34
|
+
export const toBulkUploadResultsTab = (v) => stringToUnion(v.trim().toLowerCase(), BULK_UPLOAD_RESULTS_TABS);
|
|
35
|
+
const MISSING_RECEIPTS_TABS = ['missing', 'completed', 'unmatched'];
|
|
36
|
+
export const toMissingReceiptsTab = (v) => stringToUnion(v.trim().toLowerCase(), MISSING_RECEIPTS_TABS);
|
|
37
|
+
const COMPLETED_SUB_TABS = ['all', 'ai_accountant', 'manual'];
|
|
38
|
+
export const toCompletedSubTab = (v) => stringToUnion(v.trim().toLowerCase(), COMPLETED_SUB_TABS);
|
|
39
|
+
const MATCH_SOURCES = ['ai', 'manual'];
|
|
40
|
+
export const toMatchSource = (v) => stringToUnion(v.trim().toLowerCase(), MATCH_SOURCES);
|
|
41
|
+
const BULK_UPLOAD_SORT_KEYS = [
|
|
42
|
+
'amount',
|
|
43
|
+
'category',
|
|
44
|
+
'class',
|
|
45
|
+
'date',
|
|
46
|
+
'vendor',
|
|
47
|
+
];
|
|
48
|
+
export const toBulkUploadSortKey = (v) => stringToUnion(v.trim().toLowerCase(), BULK_UPLOAD_SORT_KEYS);
|
package/lib/index.d.ts
CHANGED
|
@@ -281,7 +281,7 @@ import { getExpenseAutomationReconciliationView, isAccountReconReport } from './
|
|
|
281
281
|
import { getExpenseAutomationTransactionView } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
|
|
282
282
|
import { FluxAnalysisActionType, FluxAnalysisReviewStatus, FluxAnalysisSortKey, FluxAnalysisViewUIState, FluxBalancesByMonth } from './view/expenseAutomationView/types/fluxAnalysisViewState';
|
|
283
283
|
import { AccountSettingsLocalData, JEScheduleLocalData } from './view/expenseAutomationView/types/jeSchedulesViewState';
|
|
284
|
-
import { BatchDetails, BatchFile, BatchFileStatus, BatchListItem, BatchStatus, BatchStatusValue, BatchSummary, BulkUploadPhase, BulkUploadResultsTab, BulkUploadSortKey, BulkUploadState, CandidateRef, CompletedSubTab, MatchCandidate, MatchSource, MissingReceiptsTab } from './view/expenseAutomationView/types/missingReceiptsViewState';
|
|
284
|
+
import { BATCH_FILE_STATUSES, BatchDetails, BatchFile, BatchFileStatus, BatchListItem, BatchStatus, BatchStatusValue, BatchSummary, BulkUploadPhase, BulkUploadResultsTab, BulkUploadSortKey, BulkUploadState, CandidateRef, CompletedSubTab, isUnmatchedTabFileStatus, MatchCandidate, MatchSource, MissingReceiptsTab, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab } from './view/expenseAutomationView/types/missingReceiptsViewState';
|
|
285
285
|
import { CompletedTransactionsSelectorData, ResolvedBatchFile, ResolvedCandidate, ResolvedBatchDetails } from './view/expenseAutomationView/selectorTypes/missingReceiptsSelectorTypes';
|
|
286
286
|
import { MissingReceiptsSortKey as ExpenseAutomationMissingReceiptsSortKey, MissingReceiptsViewState as ExpenseAutomationMissingReceiptsViewState, MissingReceiptsViewUIState as ExpenseAutomationMissingReceiptsViewUIState, toMissingReceiptsSortKey as toExpenseAutomationMissingReceiptsSortKey } from './view/expenseAutomationView/types/missingReceiptsViewState';
|
|
287
287
|
import { AccountReconciliationLocalData, ReconciliationViewTabType as ExpenseAutomationReconciliationViewTab, ReconReconcileSortKey, ReconReviewSortKey, ReconciliationReconcileTabLocalData, ReconciliationReviewTabLocalData, SaveReconcileDetailActionPayload as SaveExpenseAutomationReconciliationActionType, toReconciliationTabsType } from './view/expenseAutomationView/types/reconciliationViewState';
|
|
@@ -623,7 +623,7 @@ export { TransactionsOrder, COABalancesSliceOrder, EntityOrder, Section, Section
|
|
|
623
623
|
export { ClassesViewSelectorReportV2 };
|
|
624
624
|
export { BalancesTimeseries, TrendTimeseries, BalanceKind };
|
|
625
625
|
export { fetchMonthEndCloseChecks, fetchMonthClosePerformanceTrend, MonthClosePerformanceTrend, MonthEndCloseCheck, getMonthEndCloseChecksViewByTenantId, MonthEndCloseChecksView, MonthEndCloseCheckFrequency, MonthCloseCheckMetrics, ALL_MONTH_END_CLOSE_CHECKS_FREQUENCY, MonthEndAuditSummary, };
|
|
626
|
-
export { ExpenseAutomationViewSelector, ExpenseAutomationStepDetails, ExpenseAutomationViewType, ExpenseAutomationMissingReceiptsViewSelector, BulkUploadSelectorData, ExpenseAutomationFluxAnalysisViewSelector, FluxAnalysisVendorView, FluxAnalysisViewSectionReport, FluxVendorAccountsAndClassesView, ExpenseAutomationMissingReceiptsViewUIState, ExpenseAutomationMissingReceiptsViewState, ExpenseAutomationViewState, ExpenseAutomationTransactionsTab, ExpenseAutomationMissingReceiptsSortKey, BatchDetails, BatchFile, BatchFileStatus, BatchListItem, BatchStatus, BatchStatusValue, BatchSummary, BulkUploadPhase, BulkUploadResultsTab, BulkUploadSortKey, BulkUploadState, CandidateRef, CompletedSubTab, CompletedTransactionsSelectorData, MatchCandidate, MatchSource, MissingReceiptsTab, ResolvedBatchFile, ResolvedBatchDetails, ResolvedCandidate, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, fetchExpenseAutomationMissingReceipts, bulkUploadReceipts, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete, fetchCompletedTransactions, fetchCompletedTransactionsSuccess, fetchCompletedTransactionsFailure, fetchFluxAnalysisView, clearExpenseAutomationFluxAnalysisView, updateOperatingExpensesIdsForReview as updateFluxOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview as updateFluxAnalysisSelectedSectionIdsForReview, reviewFluxAnalysisView, updateExpenseAutomationMissingReceiptUploadState, updateExpenseAutomationMissingReceiptsUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, FluxAnalysisOperatingExpenseView, FluxAnalysisSectionType, getExpenseAutomationFluxAnalysisView, FluxAnalysisSortKey, FluxAnalysisActionType, FluxBalancesByMonth, updateCurrentSelectedView, updateCurrentSelectedPeriod, getExpenseAutomationTransactionView, ReconReconcileSortKey, ReconciliationReconcileTabLocalData, FluxAnalysisReviewStatus, updateFluxAnalysisViewUIState, FluxAnalysisViewUIState, updateFluxAnalysisViewPageMetaData, MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, SaveExpenseAutomationReconciliationActionType, saveExpenseAutomationReconciliationDetail, updateExpenseAutomationReconcileTabListScrollState, updateExpenseAutomationReconReviewTabListSortState, updateExpenseAutomationReconcileTabListSortState, updateExpenseAutomationReconcileTabLocalData, updateExpenseAutomationAccountReconciliationSelectedTab, updateExpenseAutomationAccountReconciliationSelectedAccountId, ExpenseAutomationReconciliationViewSelector, getExpenseAutomationReconciliationView, AccountReconciliationBySection, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, UploadStatementDocumentAIResponse, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, AccountReconciliationByAccount, AccountReconciliationEntity, getAccountReconByAccountIdAndSelectedPeriod, ExpenseAutomationReconciliationViewTab, toReconciliationTabsType, isAccountReconReport, ReconReviewSortKey, AccountReconSectionID, ReconciliationReviewTabLocalData, TransactionsToReview, RecommendedActionCodeType, ReconciliationStatusCodeType, BalanceDataStatusCodeType, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, BankStatusCodeType, ReconciliationAccountSourceType, toReconciliationAccountSource, StatementStatusCodeType, AccountReconciliationLocalData, StatementDataStatusCodeType, deleteAccountStatement, uploadAccountStatement, UploadStatementDocumentAIPayload, updateStatementUploadChosen, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, };
|
|
626
|
+
export { ExpenseAutomationViewSelector, ExpenseAutomationStepDetails, ExpenseAutomationViewType, ExpenseAutomationMissingReceiptsViewSelector, BulkUploadSelectorData, ExpenseAutomationFluxAnalysisViewSelector, FluxAnalysisVendorView, FluxAnalysisViewSectionReport, FluxVendorAccountsAndClassesView, ExpenseAutomationMissingReceiptsViewUIState, ExpenseAutomationMissingReceiptsViewState, ExpenseAutomationViewState, ExpenseAutomationTransactionsTab, ExpenseAutomationMissingReceiptsSortKey, BATCH_FILE_STATUSES, BatchDetails, BatchFile, BatchFileStatus, BatchListItem, isUnmatchedTabFileStatus, BatchStatus, BatchStatusValue, BatchSummary, BulkUploadPhase, BulkUploadResultsTab, BulkUploadSortKey, BulkUploadState, CandidateRef, CompletedSubTab, CompletedTransactionsSelectorData, MatchCandidate, MatchSource, MissingReceiptsTab, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, ResolvedBatchFile, ResolvedBatchDetails, ResolvedCandidate, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, fetchExpenseAutomationMissingReceipts, bulkUploadReceipts, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete, fetchCompletedTransactions, fetchCompletedTransactionsSuccess, fetchCompletedTransactionsFailure, fetchFluxAnalysisView, clearExpenseAutomationFluxAnalysisView, updateOperatingExpensesIdsForReview as updateFluxOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview as updateFluxAnalysisSelectedSectionIdsForReview, reviewFluxAnalysisView, updateExpenseAutomationMissingReceiptUploadState, updateExpenseAutomationMissingReceiptsUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, FluxAnalysisOperatingExpenseView, FluxAnalysisSectionType, getExpenseAutomationFluxAnalysisView, FluxAnalysisSortKey, FluxAnalysisActionType, FluxBalancesByMonth, updateCurrentSelectedView, updateCurrentSelectedPeriod, getExpenseAutomationTransactionView, ReconReconcileSortKey, ReconciliationReconcileTabLocalData, FluxAnalysisReviewStatus, updateFluxAnalysisViewUIState, FluxAnalysisViewUIState, updateFluxAnalysisViewPageMetaData, MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, SaveExpenseAutomationReconciliationActionType, saveExpenseAutomationReconciliationDetail, updateExpenseAutomationReconcileTabListScrollState, updateExpenseAutomationReconReviewTabListSortState, updateExpenseAutomationReconcileTabListSortState, updateExpenseAutomationReconcileTabLocalData, updateExpenseAutomationAccountReconciliationSelectedTab, updateExpenseAutomationAccountReconciliationSelectedAccountId, ExpenseAutomationReconciliationViewSelector, getExpenseAutomationReconciliationView, AccountReconciliationBySection, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, UploadStatementDocumentAIResponse, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, AccountReconciliationByAccount, AccountReconciliationEntity, getAccountReconByAccountIdAndSelectedPeriod, ExpenseAutomationReconciliationViewTab, toReconciliationTabsType, isAccountReconReport, ReconReviewSortKey, AccountReconSectionID, ReconciliationReviewTabLocalData, TransactionsToReview, RecommendedActionCodeType, ReconciliationStatusCodeType, BalanceDataStatusCodeType, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, BankStatusCodeType, ReconciliationAccountSourceType, toReconciliationAccountSource, StatementStatusCodeType, AccountReconciliationLocalData, StatementDataStatusCodeType, deleteAccountStatement, uploadAccountStatement, UploadStatementDocumentAIPayload, updateStatementUploadChosen, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, };
|
|
627
627
|
export { JEScheduleLocalData };
|
|
628
628
|
export { ExpenseAutomationJESchedulesViewSelector, JEAccountSettingsView, JEScheduledTransactionWithFailedEntries, };
|
|
629
629
|
export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, TransactionsSortKey, toTransactionsSortKey, TransactionsTab, TransactionCategorizationLineItemData, TransactionReviewLocalData, SupportedTransactionCategorization, ExpenseAutomationTransactionsViewState, ExpenseAutomationTransactionsViewUIState, ExpenseAutomationTransactionViewSelector, TransactionReviewLocalDataSelectorView, };
|