@zeniai/client-epic-state 4.20.3-betaVR5 → 4.20.4
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/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.js +0 -1
- package/lib/epic.d.ts +1 -3
- package/lib/epic.js +1 -3
- package/lib/esm/entity/snackbar/snackbarTypes.js +0 -1
- package/lib/esm/epic.js +2 -4
- package/lib/esm/index.js +2 -2
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +4 -7
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +13 -7
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +5 -40
- package/lib/esm/view/expenseAutomationView/payload/missingReceiptsPayload.js +0 -9
- package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +3 -26
- package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +0 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +32 -35
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +3 -6
- package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +13 -7
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +2 -9
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +4 -40
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.d.ts +0 -5
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.js +0 -10
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +2 -12
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +4 -27
- package/lib/view/expenseAutomationView/selectorTypes/missingReceiptsSelectorTypes.d.ts +0 -1
- package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +0 -1
- package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +0 -4
- package/package.json +2 -2
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/refetchCompletedTransactionsOnBulkUploadSortEpic.js +0 -12
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/restoreBulkUploadAutomatchingOnMountEpic.js +0 -99
- package/lib/esm/view/expenseAutomationView/helpers/rollingCalendarDateRangeInclusive.js +0 -13
- package/lib/view/expenseAutomationView/epics/missingReceipts/refetchCompletedTransactionsOnBulkUploadSortEpic.d.ts +0 -10
- package/lib/view/expenseAutomationView/epics/missingReceipts/refetchCompletedTransactionsOnBulkUploadSortEpic.js +0 -16
- package/lib/view/expenseAutomationView/epics/missingReceipts/restoreBulkUploadAutomatchingOnMountEpic.d.ts +0 -18
- package/lib/view/expenseAutomationView/epics/missingReceipts/restoreBulkUploadAutomatchingOnMountEpic.js +0 -103
- package/lib/view/expenseAutomationView/helpers/rollingCalendarDateRangeInclusive.d.ts +0 -7
- package/lib/view/expenseAutomationView/helpers/rollingCalendarDateRangeInclusive.js +0 -16
|
@@ -8,9 +8,6 @@ const tenantSelector_1 = require("../../../../entity/tenant/tenantSelector");
|
|
|
8
8
|
const responsePayload_1 = require("../../../../responsePayload");
|
|
9
9
|
const missingReceiptsPayload_1 = require("../../payload/missingReceiptsPayload");
|
|
10
10
|
const missingReceiptsViewReducer_1 = require("../../reducers/missingReceiptsViewReducer");
|
|
11
|
-
const rollingCalendarDateRangeInclusive_1 = require("../../helpers/rollingCalendarDateRangeInclusive");
|
|
12
|
-
/** Batch list API window (rolling; ignores accounting month for date filter). */
|
|
13
|
-
const BULK_UPLOAD_BATCH_LIST_DATE_RANGE_DAYS = 30;
|
|
14
11
|
const fetchBulkUploadBatchesEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchBulkUploadBatches.match), (0, operators_1.switchMap)((action) => {
|
|
15
12
|
const { cacheOverride } = action.payload;
|
|
16
13
|
const state = state$.value;
|
|
@@ -25,10 +22,10 @@ const fetchBulkUploadBatchesEpic = (actions$, state$, zeniAPI) => actions$.pipe(
|
|
|
25
22
|
selectedPeriod,
|
|
26
23
|
}));
|
|
27
24
|
}
|
|
28
|
-
const
|
|
25
|
+
const period = (0, timePeriod_1.convertToPeriod)(selectedPeriod);
|
|
29
26
|
const queryParam = {
|
|
30
|
-
start_date: start,
|
|
31
|
-
end_date: end,
|
|
27
|
+
start_date: period.start,
|
|
28
|
+
end_date: period.end,
|
|
32
29
|
sort_order: 'desc',
|
|
33
30
|
};
|
|
34
31
|
return zeniAPI
|
package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js
CHANGED
|
@@ -3,20 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.searchTransactionsForManualMatchEpic = exports.MANUAL_TRANSACTION_SEARCH_AUTO_CATEGORIZED = void 0;
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
|
+
const timePeriod_1 = require("../../../../commonStateTypes/timePeriod");
|
|
7
|
+
const tenantSelector_1 = require("../../../../entity/tenant/tenantSelector");
|
|
6
8
|
const transactionReducer_1 = require("../../../../entity/transaction/transactionReducer");
|
|
7
9
|
const responsePayload_1 = require("../../../../responsePayload");
|
|
8
10
|
const missingReceiptsPayload_1 = require("../../payload/missingReceiptsPayload");
|
|
9
11
|
const missingReceiptsViewReducer_1 = require("../../reducers/missingReceiptsViewReducer");
|
|
10
12
|
const transactionsViewState_1 = require("../../types/transactionsViewState");
|
|
11
|
-
const rollingCalendarDateRangeInclusive_1 = require("../../helpers/rollingCalendarDateRangeInclusive");
|
|
12
13
|
/**
|
|
13
14
|
* `auto_categorized` for manual transaction search (Unmatched).
|
|
14
15
|
* Backend contract TBD — align with `fetchTransactionCategorizationEpic` (`selectedTab === 'autoCategorized'`)
|
|
15
16
|
* when the expense-automation API documents the intended filter for this flow.
|
|
16
17
|
*/
|
|
17
18
|
exports.MANUAL_TRANSACTION_SEARCH_AUTO_CATEGORIZED = false;
|
|
18
|
-
/** Inclusive rolling window for manual match search (ignores accounting period picker). */
|
|
19
|
-
const MANUAL_SEARCH_TRANSACTION_DATE_RANGE_DAYS = 90;
|
|
20
19
|
const searchTransactionsForManualMatchEpic = (actions$, state$, zeniAPI) => {
|
|
21
20
|
const searchActions$ = actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.searchTransactionsForManualMatch.match));
|
|
22
21
|
const pagination$ = searchActions$.pipe((0, operators_1.filter)((action) => action.payload.pageToken != null));
|
|
@@ -33,11 +32,18 @@ const searchTransactionsForManualMatchEpic = (actions$, state$, zeniAPI) => {
|
|
|
33
32
|
return rxjs_1.EMPTY;
|
|
34
33
|
}
|
|
35
34
|
const state = state$.value;
|
|
36
|
-
const { expenseAutomationMissingReceiptsViewState: { bulkUpload: { manualSearch, sortKey, sortOrder }, }, } = state;
|
|
37
|
-
const
|
|
35
|
+
const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationMissingReceiptsViewState: { bulkUpload: { manualSearch, sortKey, sortOrder }, }, } = state;
|
|
36
|
+
const currentTenant = (0, tenantSelector_1.getCurrentTenant)(state);
|
|
37
|
+
const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
|
|
38
|
+
if (selectedPeriod == null) {
|
|
39
|
+
return (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.searchTransactionsForManualMatchFailure)({
|
|
40
|
+
error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Manual search requires a selected accounting period.'),
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
const period = (0, timePeriod_1.convertToPeriod)(selectedPeriod);
|
|
38
44
|
const queryParam = {
|
|
39
|
-
start_date: start,
|
|
40
|
-
end_date: end,
|
|
45
|
+
start_date: period.start,
|
|
46
|
+
end_date: period.end,
|
|
41
47
|
auto_categorized: exports.MANUAL_TRANSACTION_SEARCH_AUTO_CATEGORIZED,
|
|
42
48
|
sort_by: (0, transactionsViewState_1.toTransactionsSortKey)(sortKey),
|
|
43
49
|
sort_order: sortOrder === 'ascending' ? 'asc' : 'desc',
|
package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
|
|
|
4
4
|
import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
|
|
5
5
|
import { RootState } from '../../../../reducer';
|
|
6
6
|
import { ZeniAPI } from '../../../../zeniAPI';
|
|
7
|
-
import { bulkUploadAutomatchingTimedOut, bulkUploadReceiptsSuccess, clearBulkUpload, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation
|
|
8
|
-
export type ActionType = ReturnType<typeof bulkUploadReceiptsSuccess> | ReturnType<typeof
|
|
7
|
+
import { bulkUploadAutomatchingTimedOut, bulkUploadReceiptsSuccess, clearBulkUpload, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation } from '../../reducers/missingReceiptsViewReducer';
|
|
8
|
+
export type ActionType = ReturnType<typeof bulkUploadReceiptsSuccess> | ReturnType<typeof pusherBatchStatusUpdate> | ReturnType<typeof fetchBulkUploadBatchDetailsSuccess> | ReturnType<typeof fetchBulkUploadBatches> | ReturnType<typeof requestMissingReceiptsTabNavigation> | ReturnType<typeof updateTransactions> | ReturnType<typeof clearBulkUpload> | ReturnType<typeof openSnackbar> | ReturnType<typeof bulkUploadAutomatchingTimedOut>;
|
|
9
9
|
/**
|
|
10
10
|
* On Pusher batch completion: refresh batch list (then fetchMultipleBatchDetailsEpic runs),
|
|
11
11
|
* and request switching to the Unmatched tab. Debounced to reduce duplicate refreshes.
|
|
@@ -17,13 +17,6 @@ export declare const pusherBatchStatusCompletionEpic: (actions$: ActionsObservab
|
|
|
17
17
|
* Cancels when the batch completes normally, bulk state is cleared, or another upload supersedes.
|
|
18
18
|
*/
|
|
19
19
|
export declare const bulkUploadAutomatchingTimeoutEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => Observable<ActionType>;
|
|
20
|
-
/**
|
|
21
|
-
* Show a success toast when batch details arrive for the current upload batch,
|
|
22
|
-
* e.g. "17 out of 20 Receipts Matched". Scoped per upload session so it fires
|
|
23
|
-
* only once: starts on `bulkUploadReceiptsSuccess`, waits for the first
|
|
24
|
-
* batch details action for that batch, emits the toast, then stops.
|
|
25
|
-
*/
|
|
26
|
-
export declare const bulkUploadMatchResultToastEpic: (actions$: ActionsObservable<ActionType>) => Observable<ActionType>;
|
|
27
20
|
/**
|
|
28
21
|
* Fallback polling when Pusher is slow or unavailable. Network errors on a poll tick show one
|
|
29
22
|
* error snackbar per upload session (first failure only) so the user is not spammed every
|
package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pollBulkUploadBatchStatusEpic = exports.
|
|
3
|
+
exports.pollBulkUploadBatchStatusEpic = exports.bulkUploadAutomatchingTimeoutEpic = exports.pusherBatchStatusCompletionEpic = void 0;
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
6
|
const snackbarReducer_1 = require("../../../../entity/snackbar/snackbarReducer");
|
|
@@ -11,8 +11,6 @@ const missingReceiptsPayload_1 = require("../../payload/missingReceiptsPayload")
|
|
|
11
11
|
const missingReceiptsViewReducer_1 = require("../../reducers/missingReceiptsViewReducer");
|
|
12
12
|
/** First poll after upload; then interval while batch not resolved via Pusher or API. */
|
|
13
13
|
const FALLBACK_FIRST_DELAY_MS = 30000;
|
|
14
|
-
/** Shorter first poll for restored sessions — batch may already be near completion. */
|
|
15
|
-
const RESTORE_FIRST_DELAY_MS = 5000;
|
|
16
14
|
const FALLBACK_POLL_INTERVAL_MS = 10000;
|
|
17
15
|
/**
|
|
18
16
|
* On Pusher batch completion: refresh batch list (then fetchMultipleBatchDetailsEpic runs),
|
|
@@ -31,8 +29,7 @@ exports.pusherBatchStatusCompletionEpic = pusherBatchStatusCompletionEpic;
|
|
|
31
29
|
* force `phase` to `completed` (dismiss automatching banner) and refresh the batch list.
|
|
32
30
|
* Cancels when the batch completes normally, bulk state is cleared, or another upload supersedes.
|
|
33
31
|
*/
|
|
34
|
-
const bulkUploadAutomatchingTimeoutEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(
|
|
35
|
-
missingReceiptsViewReducer_1.restoreBulkUploadMatchingState.match(action)), (0, operators_1.mergeMap)((action) => {
|
|
32
|
+
const bulkUploadAutomatchingTimeoutEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess.match), (0, operators_1.mergeMap)((action) => {
|
|
36
33
|
const { batchId } = action.payload;
|
|
37
34
|
return (0, rxjs_1.timer)(bulkUploadTiming_1.BULK_UPLOAD_AUTOMATCHING_TIMEOUT_MS).pipe((0, operators_1.mergeMap)(() => {
|
|
38
35
|
const bulk = state$.value.expenseAutomationMissingReceiptsViewState.bulkUpload;
|
|
@@ -47,48 +44,15 @@ const bulkUploadAutomatchingTimeoutEpic = (actions$, state$) => actions$.pipe((0
|
|
|
47
44
|
a.payload.status === 'completed')), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchBulkUploadBatchDetailsSuccess.match), (0, operators_1.filter)((a) => a.payload.batchId === batchId)))));
|
|
48
45
|
}));
|
|
49
46
|
exports.bulkUploadAutomatchingTimeoutEpic = bulkUploadAutomatchingTimeoutEpic;
|
|
50
|
-
/**
|
|
51
|
-
* Show a success toast when batch details arrive for the current upload batch,
|
|
52
|
-
* e.g. "17 out of 20 Receipts Matched". Scoped per upload session so it fires
|
|
53
|
-
* only once: starts on `bulkUploadReceiptsSuccess`, waits for the first
|
|
54
|
-
* batch details action for that batch, emits the toast, then stops.
|
|
55
|
-
*/
|
|
56
|
-
const bulkUploadMatchResultToastEpic = (actions$) => actions$.pipe((0, operators_1.filter)((action) => missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess.match(action) ||
|
|
57
|
-
missingReceiptsViewReducer_1.restoreBulkUploadMatchingState.match(action)), (0, operators_1.switchMap)((uploadAction) => {
|
|
58
|
-
const { batchId } = uploadAction.payload;
|
|
59
|
-
return (0, rxjs_1.merge)(actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchBulkUploadBatchDetailsSuccess.match)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.storeBatchDetails.match))).pipe((0, operators_1.filter)((a) => a.payload.batchId === batchId), (0, operators_1.take)(1), (0, operators_1.mergeMap)((action) => {
|
|
60
|
-
const { summary } = action.payload;
|
|
61
|
-
return (0, rxjs_1.of)((0, snackbarReducer_1.openSnackbar)({
|
|
62
|
-
messageSection: 'receipts_bulk_match',
|
|
63
|
-
messageText: 'success',
|
|
64
|
-
type: 'success',
|
|
65
|
-
variables: [
|
|
66
|
-
{
|
|
67
|
-
variableName: '_matched_',
|
|
68
|
-
variableValue: String(summary.matched),
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
variableName: '_total_',
|
|
72
|
-
variableValue: String(summary.total),
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
}));
|
|
76
|
-
}), (0, operators_1.takeUntil)((0, rxjs_1.merge)(actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.clearBulkUpload.match)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess.match)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.restoreBulkUploadMatchingState.match)))));
|
|
77
|
-
}));
|
|
78
|
-
exports.bulkUploadMatchResultToastEpic = bulkUploadMatchResultToastEpic;
|
|
79
47
|
/**
|
|
80
48
|
* Fallback polling when Pusher is slow or unavailable. Network errors on a poll tick show one
|
|
81
49
|
* error snackbar per upload session (first failure only) so the user is not spammed every
|
|
82
50
|
* interval; Pusher or a later successful poll still completes the flow.
|
|
83
51
|
*/
|
|
84
|
-
const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(
|
|
85
|
-
missingReceiptsViewReducer_1.restoreBulkUploadMatchingState.match(action)), (0, operators_1.mergeMap)((action) => {
|
|
52
|
+
const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess.match), (0, operators_1.mergeMap)((action) => {
|
|
86
53
|
const { batchId } = action.payload;
|
|
87
54
|
let pollErrorNotified = false;
|
|
88
|
-
|
|
89
|
-
? RESTORE_FIRST_DELAY_MS
|
|
90
|
-
: FALLBACK_FIRST_DELAY_MS;
|
|
91
|
-
return (0, rxjs_1.timer)(firstDelay, FALLBACK_POLL_INTERVAL_MS).pipe((0, operators_1.takeUntil)((0, rxjs_1.merge)(actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.clearBulkUpload.match)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.pusherBatchStatusUpdate.match), (0, operators_1.filter)((action) => action.payload.batchId === batchId)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchBulkUploadBatchDetailsSuccess.match), (0, operators_1.filter)((action) => action.payload.batchId === batchId)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadAutomatchingTimedOut.match), (0, operators_1.filter)((action) => action.payload.batchId === batchId)))), (0, operators_1.switchMap)(() => zeniAPI
|
|
55
|
+
return (0, rxjs_1.timer)(FALLBACK_FIRST_DELAY_MS, FALLBACK_POLL_INTERVAL_MS).pipe((0, operators_1.takeUntil)((0, rxjs_1.merge)(actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.clearBulkUpload.match)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.pusherBatchStatusUpdate.match), (0, operators_1.filter)((action) => action.payload.batchId === batchId)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchBulkUploadBatchDetailsSuccess.match), (0, operators_1.filter)((action) => action.payload.batchId === batchId)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadAutomatchingTimedOut.match), (0, operators_1.filter)((action) => action.payload.batchId === batchId)))), (0, operators_1.switchMap)(() => zeniAPI
|
|
92
56
|
.getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/${batchId}`)
|
|
93
57
|
.pipe((0, operators_1.mergeMap)((response) => {
|
|
94
58
|
/** Same batch-details URL; polls until `status` is completed (Pusher may win first). */
|
package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare const getLineItemsByTransactionsIdsFromResponse: (transactions: S
|
|
|
37
37
|
export declare const getLineItemsByTransactionIdsFromLocalData: (transactionLocalData: TransactionReviewLocalDataSelectorView[], selectedTab: TransactionsTab) => Record<ID, string[]>;
|
|
38
38
|
export declare const mergeTabSpecificLineItems: (currentTabSpecificLineItems: TabSpecificLineItems, selectedTab: TransactionsTab, newLineItems: TabSpecificLineItems) => TabSpecificLineItems;
|
|
39
39
|
export declare const getSnackbarMessageForTransactionReview: (updatedCount: number, failedCount: number, categorizedCount: number) => {
|
|
40
|
-
messageSection: "common" | "transactionDetails_updatingPastTransactions" | "transactionDetails_transactionUpdated" | "cockpit_month_end_email_sent" | "cockpit_month_end_email_save" | "cockpit_month_end_email_attachment_upload" | "je_bill_link" | "je_posted" | "audit_score_updated" | "people_invite_people" | "people_invite_multiple_people" | "people_delete_person" | "people_update_person" | "reimbursement_updated" | "reimbursement_deleted" | "reimbursement_cancelled_deleted" | "reimbursement_cancelled" | "reimbursement_approved" | "reimbursement_rejected" | "reimbursement_sent_for_approval" | "account_added" | "business_verification_save" | "business_verification_submit" | "business_verification_from_bills_submit" | "plaid_connection" | "unlink_deposit_account" | "reimbursement_setup" | "reimbursement_approval_create" | "reimbursement_duplicate_approval_create" | "reimbursement_approval_update" | "reimbursement_duplicate_approval_update" | "reimbursement_approval_delete" | "reimbursement_create_mileage" | "reimbursement_update_mileage" | "reimbursement_accept_term" | "reimbursement_accept_employee_term" | "reimbursement_bulk_submit" | "reimbursement_bulk_processed" | "bill_pay_setup" | "zeni_accounts_setup" | "bill_pay_approval_create" | "bill_pay_duplicate_approval_create" | "bill_pay_approval_update" | "bill_pay_duplicate_approval_update" | "bill_pay_approval_delete" | "bill_pay_updated" | "bill_pay_deleted" | "bill_pay_cancelled_deleted" | "bill_pay_cancelled" | "bill_pay_approved" | "real_time_approver_added" | "bill_pay_rejected" | "bill_pay_sent_for_approval" | "bill_pay_accept_term" | "bill_pay_bulk_submit" | "bill_pay_bulk_processed" | "bill_pay_refund" | "bill_pay_retry" | "bill_pay_marked_as_paid" | "zeni_account_accept_term" | "update_vendor" | "data_refresh_update" | "delete_bank_account" | "create_bank_account" | "create_bank_account_ach" | "create_bank_account_wire" | "create_bank_account_international" | "transfer_money" | "update_zeni_account_nickname" | "create_checking_account" | "deposit_check" | "create_vendor" | "onboarding_customer_view" | "onboarding_customer_view_complete" | "onboarding_customer_identity_verification_save" | "onboarding_customer_identity_verification_submit" | "onboarding_customer_business_verification_save" | "onboarding_customer_business_verification_submit" | "retry_bank_account_connection" | "dashboard_invite_sent" | "onboarding_info_saved" | "approve_original_merchant" | "approve_global_merchant" | "reject_global_merchant" | "create_global_merchant" | "fetch_global_merchant_no_recommendation" | "save_vendor_renamed" | "save_vendor_sent_for_review" | "save_vendor_marked_as_employee" | "save_vendor_marked_as_local_contractor" | "charge_card_setup" | "charge_card_accept_term" | "charge_card_receipt_upload" | "charge_card_resend_invite" | "charge_card_revoke_invite" | "charge_card_update_limit" | "charge_cards_update_limit" | "close_charge_card" | "lock_charge_card" | "lock_charge_card_card_user" | "lock_charge_cards" | "unlock_charge_card" | "unlock_charge_card_card_user" | "unlock_charge_cards" | "close_charge_cards" | "revoke_invite_charge_cards" | "charge_card_express_interest" | "create_schedule" | "save_schedule" | "delete_schedule" | "ignore_schedule" | "save_task_detail" | "fetch_task_detail" | "delete_task" | "archive_task" | "create_tag" | "delete_tag" | "update_charge_card" | "update_charge_card_name" | "update_charge_card_name_card_user" | "issue_charge_card" | "issue_charge_cards" | "notification_settings_saved" | "referral_invite_sent" | "notification_mark_as_read" | "mark_as_complete_schedule" | "cancel_journal_entry" | "settings_accounting_accounts_updated" | "create_card_setup" | "confirm_card_setup" | "add_card_payment_source" | "fetch_payment_sources" | "task_assigned_toast_notification" | "task_due_tomorrow_toast_notification" | "task_deleted_toast_notification" | "task_archived_toast_notification" | "task_overdue_toast_notification" | "task_overdue_toast_notification_creator" | "task_notification_count" | "task_activities_toast_notification" | "task_created_toast_notification" | "task_group_creation_success" | "task_group_deletion_success" | "task_group_update_success" | "primary_funding_account_updated" | "task_time_spent_validation" | "missing_receipts_attachment" | "flux_analysis_unreviewed" | "flux_analysis_reviewed" | "receipt_match" | "receipts_upload" | "
|
|
40
|
+
messageSection: "common" | "transactionDetails_updatingPastTransactions" | "transactionDetails_transactionUpdated" | "cockpit_month_end_email_sent" | "cockpit_month_end_email_save" | "cockpit_month_end_email_attachment_upload" | "je_bill_link" | "je_posted" | "audit_score_updated" | "people_invite_people" | "people_invite_multiple_people" | "people_delete_person" | "people_update_person" | "reimbursement_updated" | "reimbursement_deleted" | "reimbursement_cancelled_deleted" | "reimbursement_cancelled" | "reimbursement_approved" | "reimbursement_rejected" | "reimbursement_sent_for_approval" | "account_added" | "business_verification_save" | "business_verification_submit" | "business_verification_from_bills_submit" | "plaid_connection" | "unlink_deposit_account" | "reimbursement_setup" | "reimbursement_approval_create" | "reimbursement_duplicate_approval_create" | "reimbursement_approval_update" | "reimbursement_duplicate_approval_update" | "reimbursement_approval_delete" | "reimbursement_create_mileage" | "reimbursement_update_mileage" | "reimbursement_accept_term" | "reimbursement_accept_employee_term" | "reimbursement_bulk_submit" | "reimbursement_bulk_processed" | "bill_pay_setup" | "zeni_accounts_setup" | "bill_pay_approval_create" | "bill_pay_duplicate_approval_create" | "bill_pay_approval_update" | "bill_pay_duplicate_approval_update" | "bill_pay_approval_delete" | "bill_pay_updated" | "bill_pay_deleted" | "bill_pay_cancelled_deleted" | "bill_pay_cancelled" | "bill_pay_approved" | "real_time_approver_added" | "bill_pay_rejected" | "bill_pay_sent_for_approval" | "bill_pay_accept_term" | "bill_pay_bulk_submit" | "bill_pay_bulk_processed" | "bill_pay_refund" | "bill_pay_retry" | "bill_pay_marked_as_paid" | "zeni_account_accept_term" | "update_vendor" | "data_refresh_update" | "delete_bank_account" | "create_bank_account" | "create_bank_account_ach" | "create_bank_account_wire" | "create_bank_account_international" | "transfer_money" | "update_zeni_account_nickname" | "create_checking_account" | "deposit_check" | "create_vendor" | "onboarding_customer_view" | "onboarding_customer_view_complete" | "onboarding_customer_identity_verification_save" | "onboarding_customer_identity_verification_submit" | "onboarding_customer_business_verification_save" | "onboarding_customer_business_verification_submit" | "retry_bank_account_connection" | "dashboard_invite_sent" | "onboarding_info_saved" | "approve_original_merchant" | "approve_global_merchant" | "reject_global_merchant" | "create_global_merchant" | "fetch_global_merchant_no_recommendation" | "save_vendor_renamed" | "save_vendor_sent_for_review" | "save_vendor_marked_as_employee" | "save_vendor_marked_as_local_contractor" | "charge_card_setup" | "charge_card_accept_term" | "charge_card_receipt_upload" | "charge_card_resend_invite" | "charge_card_revoke_invite" | "charge_card_update_limit" | "charge_cards_update_limit" | "close_charge_card" | "lock_charge_card" | "lock_charge_card_card_user" | "lock_charge_cards" | "unlock_charge_card" | "unlock_charge_card_card_user" | "unlock_charge_cards" | "close_charge_cards" | "revoke_invite_charge_cards" | "charge_card_express_interest" | "create_schedule" | "save_schedule" | "delete_schedule" | "ignore_schedule" | "save_task_detail" | "fetch_task_detail" | "delete_task" | "archive_task" | "create_tag" | "delete_tag" | "update_charge_card" | "update_charge_card_name" | "update_charge_card_name_card_user" | "issue_charge_card" | "issue_charge_cards" | "notification_settings_saved" | "referral_invite_sent" | "notification_mark_as_read" | "mark_as_complete_schedule" | "cancel_journal_entry" | "settings_accounting_accounts_updated" | "create_card_setup" | "confirm_card_setup" | "add_card_payment_source" | "fetch_payment_sources" | "task_assigned_toast_notification" | "task_due_tomorrow_toast_notification" | "task_deleted_toast_notification" | "task_archived_toast_notification" | "task_overdue_toast_notification" | "task_overdue_toast_notification_creator" | "task_notification_count" | "task_activities_toast_notification" | "task_created_toast_notification" | "task_group_creation_success" | "task_group_deletion_success" | "task_group_update_success" | "primary_funding_account_updated" | "task_time_spent_validation" | "missing_receipts_attachment" | "flux_analysis_unreviewed" | "flux_analysis_reviewed" | "receipt_match" | "receipts_upload" | "billing_address_view" | "express_pay_submit" | "exclude_transaction" | "reconcile" | "save_reconcile_for_later" | "recon_transaction_categorize" | "recon_transaction_match" | "update_debit_card_pin_attempt" | "set_debit_card_pin" | "ai_cfo_create_session_and_submit" | "ai_cfo_chat_session_deleted" | "charge_card_auto_pay_enable" | "charge_card_auto_pay_disable" | "treasury_setup" | "treasury_accept_term" | "treasury_transfer_money" | "treasury_transfer_money_failed" | "treasury_update_portfolio_allocation" | "send_email_magic_link_to_user" | "complete_profile_done" | "reports_resync" | "invalid_phone_number" | "transactions_categorized_updated_failed" | "transaction_categorized_updated_failed" | "transactionsCategorized_transactionsUpdated" | "transactionsCategorized_transactionUpdated" | "transactionCategorized_transactionsUpdated" | "transactionCategorized_transactionUpdated" | "transactionsCategorized_transactionsFailed" | "transactionsCategorized_transactionFailed" | "transactionCategorized_transactionsFailed" | "transactionCategorized_transactionFailed" | "transactionsUpdated_transactionsFailed" | "transactionsUpdated_transactionFailed" | "transactionUpdated_transactionsFailed" | "transactionUpdated_transactionFailed" | "transactionsCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionsUpdated_transactionFailed" | "transactionsCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionUpdated_transactionFailed" | "transactionCategorized_transactionsUpdated_transactionFailed" | "transactionCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionUpdated_transactionFailed";
|
|
41
41
|
messageText: "notification" | "success" | "failed";
|
|
42
42
|
type: "error" | "success" | "info";
|
|
43
43
|
variables: {
|
|
@@ -40,7 +40,6 @@ export interface BatchListItemPayload {
|
|
|
40
40
|
possible_matches_count: number;
|
|
41
41
|
status: string;
|
|
42
42
|
total_files: number;
|
|
43
|
-
user_id: string;
|
|
44
43
|
}
|
|
45
44
|
export type BatchListResponse = ZeniAPIResponse<BatchListResponsePayload>;
|
|
46
45
|
export interface MatchedTransactionPayload {
|
|
@@ -82,8 +81,6 @@ export interface BatchDetailsResponsePayload {
|
|
|
82
81
|
possible_matches: number;
|
|
83
82
|
total: number;
|
|
84
83
|
};
|
|
85
|
-
/** Uploader — used to scope automatching UI to the user who submitted the batch. */
|
|
86
|
-
user_id?: string;
|
|
87
84
|
}
|
|
88
85
|
export type BatchDetailsResponse = ZeniAPIResponse<BatchDetailsResponsePayload>;
|
|
89
86
|
/**
|
|
@@ -96,8 +93,6 @@ export declare function toBatchFile(payload: BatchFilePayload, filesEndPoint?: s
|
|
|
96
93
|
export declare function extractTransactionPayloadsFromBatchFiles(files: BatchFilePayload[]): SupportedTransactionPayload[];
|
|
97
94
|
export declare function toBatchSummary(payload: BatchDetailsResponsePayload['summary']): BatchSummary;
|
|
98
95
|
export declare function toBatchDetails(payload: BatchDetailsResponsePayload, filesEndPoint?: string): BatchDetails;
|
|
99
|
-
/** Batch is still in-flight for automatching (GET /batches/:id while not completed). */
|
|
100
|
-
export declare function isBatchDetailsStatusPendingOrProcessing(status: string): boolean;
|
|
101
96
|
/** Batch list `status` is a string from the API — compare case-insensitively. */
|
|
102
97
|
export declare function isBatchListStatusCompleted(status: string): boolean;
|
|
103
98
|
/**
|
|
@@ -5,7 +5,6 @@ exports.toBatchFile = toBatchFile;
|
|
|
5
5
|
exports.extractTransactionPayloadsFromBatchFiles = extractTransactionPayloadsFromBatchFiles;
|
|
6
6
|
exports.toBatchSummary = toBatchSummary;
|
|
7
7
|
exports.toBatchDetails = toBatchDetails;
|
|
8
|
-
exports.isBatchDetailsStatusPendingOrProcessing = isBatchDetailsStatusPendingOrProcessing;
|
|
9
8
|
exports.isBatchListStatusCompleted = isBatchListStatusCompleted;
|
|
10
9
|
exports.filterBatchListItemsForBatchDetailsFetch = filterBatchListItemsForBatchDetailsFetch;
|
|
11
10
|
exports.isBatchDetailsApiStatusCompleted = isBatchDetailsApiStatusCompleted;
|
|
@@ -114,16 +113,8 @@ function toBatchDetails(payload, filesEndPoint) {
|
|
|
114
113
|
files: payload.files.map((file) => toBatchFile(file, filesEndPoint)),
|
|
115
114
|
status: (0, missingReceiptsViewState_1.toBatchStatusValue)(payload.status),
|
|
116
115
|
summary: toBatchSummary(payload.summary),
|
|
117
|
-
...(payload.user_id != null && payload.user_id !== ''
|
|
118
|
-
? { userId: payload.user_id }
|
|
119
|
-
: {}),
|
|
120
116
|
};
|
|
121
117
|
}
|
|
122
|
-
/** Batch is still in-flight for automatching (GET /batches/:id while not completed). */
|
|
123
|
-
function isBatchDetailsStatusPendingOrProcessing(status) {
|
|
124
|
-
const s = status.toLowerCase();
|
|
125
|
-
return s === 'processing' || s === 'pending';
|
|
126
|
-
}
|
|
127
118
|
/** Batch list `status` is a string from the API — compare case-insensitively. */
|
|
128
119
|
function isBatchListStatusCompleted(status) {
|
|
129
120
|
return status.toLowerCase() === 'completed';
|
|
@@ -181,7 +172,6 @@ function toBatchListItem(payload) {
|
|
|
181
172
|
possibleMatchesCount: payload.possible_matches_count,
|
|
182
173
|
status: payload.status,
|
|
183
174
|
totalFiles: payload.total_files,
|
|
184
|
-
userId: payload.user_id,
|
|
185
175
|
};
|
|
186
176
|
}
|
|
187
177
|
/**
|
|
@@ -12,12 +12,6 @@ export declare const initialBulkUploadState: BulkUploadState;
|
|
|
12
12
|
export declare const initialState: MissingReceiptsViewState;
|
|
13
13
|
/** Epic trigger only; batch-details fetch is handled in epics. */
|
|
14
14
|
export declare const fetchBulkUploadBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails">;
|
|
15
|
-
/**
|
|
16
|
-
* Epic trigger only. Dispatched from the screen on missing-receipts entry / period switch so the
|
|
17
|
-
* automatching banner is restored for the logged-in user even when they sit on the Missing tab
|
|
18
|
-
* after a hard refresh. The epic owns the list + details API calls end-to-end.
|
|
19
|
-
*/
|
|
20
|
-
export declare const restoreBulkUploadAutomatchingOnMount: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/restoreBulkUploadAutomatchingOnMount">;
|
|
21
15
|
export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[period: TimePeriod, minimumTransactionAmount: Amount, cacheOverride?: any, refreshViewInBackground?: any], {
|
|
22
16
|
period: TimePeriod;
|
|
23
17
|
minimumTransactionAmount: Amount;
|
|
@@ -40,15 +34,11 @@ export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCrea
|
|
|
40
34
|
selectedPeriod: MonthYearPeriod;
|
|
41
35
|
}, "expenseAutomationMissingReceiptsView/markMissingReceiptAsDone", never, never>, clearExpenseAutomationMissingReceiptsView: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearExpenseAutomationMissingReceiptsView">, bulkUploadReceipts: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[files: File[]], {
|
|
42
36
|
files: File[];
|
|
43
|
-
|
|
44
|
-
}, "expenseAutomationMissingReceiptsView/bulkUploadReceipts", never, never>, updateBulkUploadProgress: import("@reduxjs/toolkit").ActionCreatorWithPayload<number, "expenseAutomationMissingReceiptsView/updateBulkUploadProgress">, setBulkUploadUploadedFileCount: import("@reduxjs/toolkit").ActionCreatorWithPayload<number, "expenseAutomationMissingReceiptsView/setBulkUploadUploadedFileCount">, bulkUploadReceiptsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
37
|
+
}, "expenseAutomationMissingReceiptsView/bulkUploadReceipts", never, never>, updateBulkUploadProgress: import("@reduxjs/toolkit").ActionCreatorWithPayload<number, "expenseAutomationMissingReceiptsView/updateBulkUploadProgress">, bulkUploadReceiptsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
45
38
|
batchId: ID;
|
|
46
39
|
}, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsSuccess">, bulkUploadReceiptsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
47
40
|
error: ZeniAPIStatus;
|
|
48
|
-
}, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure">,
|
|
49
|
-
batchId: ID;
|
|
50
|
-
totalFiles: number;
|
|
51
|
-
}, "expenseAutomationMissingReceiptsView/restoreBulkUploadMatchingState">, bulkUploadAutomatchingTimedOut: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[batchId: string], {
|
|
41
|
+
}, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure">, bulkUploadAutomatchingTimedOut: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[batchId: string], {
|
|
52
42
|
batchId: string;
|
|
53
43
|
}, "expenseAutomationMissingReceiptsView/bulkUploadAutomatchingTimedOut", never, never>, pusherBatchStatusUpdate: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchStatus, "expenseAutomationMissingReceiptsView/pusherBatchStatusUpdate">, requestMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
54
44
|
tab: BulkUploadResultsTab;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.fetchCompletedTransactionsFailure = exports.fetchCompletedTransactionsSuccess = exports.fetchCompletedTransactions = exports.acknowledgeBulkUploadConfirmMatchComplete = exports.clearManualSearchResults = exports.searchTransactionsForManualMatchFailure = exports.searchTransactionsForManualMatchSuccess = exports.searchTransactionsForManualMatch = exports.clearBulkUpload = exports.setBulkUploadSortConfig = exports.setBulkUploadCompletedSubTab = exports.setBulkUploadResultsTab = exports.confirmBulkUploadMatchFailure = exports.confirmBulkUploadMatchSuccess = exports.confirmBulkUploadMatch = exports.fetchBulkUploadBatchesFailure = exports.fetchBulkUploadBatchesSuccess = exports.fetchBulkUploadBatches = exports.fetchMoreBatchDetailsFailure = exports.fetchMoreBatchDetailsComplete = exports.fetchMoreBatchDetails = exports.setInitialBatchDetailsLoading = exports.batchDetailFetchFailed = exports.storeBatchDetails = exports.fetchBulkUploadBatchDetailsFailure = exports.fetchBulkUploadBatchDetailsSuccess = exports.clearMissingReceiptsTabNavigation = exports.requestMissingReceiptsTabNavigation = exports.pusherBatchStatusUpdate = exports.bulkUploadAutomatchingTimedOut = exports.
|
|
4
|
+
exports.fetchCompletedTransactionsFailure = exports.fetchCompletedTransactionsSuccess = exports.fetchCompletedTransactions = exports.acknowledgeBulkUploadConfirmMatchComplete = exports.clearManualSearchResults = exports.searchTransactionsForManualMatchFailure = exports.searchTransactionsForManualMatchSuccess = exports.searchTransactionsForManualMatch = exports.clearBulkUpload = exports.setBulkUploadSortConfig = exports.setBulkUploadCompletedSubTab = exports.setBulkUploadResultsTab = exports.confirmBulkUploadMatchFailure = exports.confirmBulkUploadMatchSuccess = exports.confirmBulkUploadMatch = exports.fetchBulkUploadBatchesFailure = exports.fetchBulkUploadBatchesSuccess = exports.fetchBulkUploadBatches = exports.fetchMoreBatchDetailsFailure = exports.fetchMoreBatchDetailsComplete = exports.fetchMoreBatchDetails = exports.setInitialBatchDetailsLoading = exports.batchDetailFetchFailed = exports.storeBatchDetails = exports.fetchBulkUploadBatchDetailsFailure = exports.fetchBulkUploadBatchDetailsSuccess = exports.clearMissingReceiptsTabNavigation = exports.requestMissingReceiptsTabNavigation = exports.pusherBatchStatusUpdate = exports.bulkUploadAutomatchingTimedOut = exports.bulkUploadReceiptsFailure = exports.bulkUploadReceiptsSuccess = exports.updateBulkUploadProgress = exports.bulkUploadReceipts = exports.clearExpenseAutomationMissingReceiptsView = exports.markMissingReceiptAsDone = exports.updateMissingReceiptsUIState = exports.updateMissingReceiptUploadState = exports.uploadMissingReceiptSuccess = exports.fetchMissingReceiptsFailure = exports.fetchMissingReceiptsSuccess = exports.fetchMissingReceipts = exports.fetchBulkUploadBatchDetails = exports.initialState = exports.initialBulkUploadState = exports.getCompletedTransactionsCacheKey = void 0;
|
|
5
5
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
6
6
|
const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
|
|
7
7
|
const missingReceiptsViewState_1 = require("../types/missingReceiptsViewState");
|
|
@@ -32,7 +32,6 @@ exports.initialBulkUploadState = {
|
|
|
32
32
|
phase: 'idle',
|
|
33
33
|
sortKey: 'date',
|
|
34
34
|
sortOrder: 'descending',
|
|
35
|
-
uploadedFileCount: 0,
|
|
36
35
|
uploadProgress: 0,
|
|
37
36
|
uploadStatus: { fetchState: 'Not-Started', error: undefined },
|
|
38
37
|
};
|
|
@@ -59,12 +58,6 @@ exports.initialState = {
|
|
|
59
58
|
};
|
|
60
59
|
/** Epic trigger only; batch-details fetch is handled in epics. */
|
|
61
60
|
exports.fetchBulkUploadBatchDetails = (0, toolkit_1.createAction)('expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails');
|
|
62
|
-
/**
|
|
63
|
-
* Epic trigger only. Dispatched from the screen on missing-receipts entry / period switch so the
|
|
64
|
-
* automatching banner is restored for the logged-in user even when they sit on the Missing tab
|
|
65
|
-
* after a hard refresh. The epic owns the list + details API calls end-to-end.
|
|
66
|
-
*/
|
|
67
|
-
exports.restoreBulkUploadAutomatchingOnMount = (0, toolkit_1.createAction)('expenseAutomationMissingReceiptsView/restoreBulkUploadAutomatchingOnMount');
|
|
68
61
|
const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
|
|
69
62
|
name: 'expenseAutomationMissingReceiptsView',
|
|
70
63
|
initialState: exports.initialState,
|
|
@@ -168,29 +161,21 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
|
|
|
168
161
|
},
|
|
169
162
|
// -- Bulk Upload Actions --
|
|
170
163
|
bulkUploadReceipts: {
|
|
171
|
-
reducer(draft
|
|
164
|
+
reducer(draft) {
|
|
172
165
|
draft.bulkUpload.phase = 'uploading';
|
|
173
166
|
draft.bulkUpload.uploadProgress = 0;
|
|
174
|
-
draft.bulkUpload.uploadedFileCount = action.payload.fileCount;
|
|
175
167
|
draft.bulkUpload.uploadStatus = {
|
|
176
168
|
fetchState: 'In-Progress',
|
|
177
169
|
error: undefined,
|
|
178
170
|
};
|
|
179
171
|
},
|
|
180
172
|
prepare(files) {
|
|
181
|
-
return { payload: { files
|
|
173
|
+
return { payload: { files } };
|
|
182
174
|
},
|
|
183
175
|
},
|
|
184
176
|
updateBulkUploadProgress(draft, action) {
|
|
185
177
|
draft.bulkUpload.uploadProgress = action.payload;
|
|
186
178
|
},
|
|
187
|
-
/**
|
|
188
|
-
* Sync file count when bulk upload uses direct HTTP (`bulkUploadReceipts` Redux action is not
|
|
189
|
-
* dispatched, so `bulkUploadReceipts` reducer never runs).
|
|
190
|
-
*/
|
|
191
|
-
setBulkUploadUploadedFileCount(draft, action) {
|
|
192
|
-
draft.bulkUpload.uploadedFileCount = action.payload;
|
|
193
|
-
},
|
|
194
179
|
bulkUploadReceiptsSuccess(draft, action) {
|
|
195
180
|
draft.bulkUpload.currentBatchId = action.payload.batchId;
|
|
196
181
|
draft.bulkUpload.uploadProgress = 100;
|
|
@@ -207,14 +192,6 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
|
|
|
207
192
|
};
|
|
208
193
|
draft.bulkUpload.phase = 'idle';
|
|
209
194
|
},
|
|
210
|
-
restoreBulkUploadMatchingState(draft, action) {
|
|
211
|
-
if (draft.bulkUpload.phase !== 'idle') {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
draft.bulkUpload.currentBatchId = action.payload.batchId;
|
|
215
|
-
draft.bulkUpload.uploadedFileCount = action.payload.totalFiles;
|
|
216
|
-
draft.bulkUpload.phase = 'matching';
|
|
217
|
-
},
|
|
218
195
|
bulkUploadAutomatchingTimedOut: {
|
|
219
196
|
reducer(draft, action) {
|
|
220
197
|
if (draft.bulkUpload.phase !== 'matching' ||
|
|
@@ -579,7 +556,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
|
|
|
579
556
|
});
|
|
580
557
|
_a = expenseAutomationMissingReceiptsView.actions, exports.fetchMissingReceipts = _a.fetchMissingReceipts, exports.fetchMissingReceiptsSuccess = _a.fetchMissingReceiptsSuccess, exports.fetchMissingReceiptsFailure = _a.fetchMissingReceiptsFailure, exports.uploadMissingReceiptSuccess = _a.uploadMissingReceiptSuccess, exports.updateMissingReceiptUploadState = _a.updateMissingReceiptUploadState, exports.updateMissingReceiptsUIState = _a.updateMissingReceiptsUIState, exports.markMissingReceiptAsDone = _a.markMissingReceiptAsDone, exports.clearExpenseAutomationMissingReceiptsView = _a.clearExpenseAutomationMissingReceiptsView,
|
|
581
558
|
// Bulk Upload
|
|
582
|
-
exports.bulkUploadReceipts = _a.bulkUploadReceipts, exports.updateBulkUploadProgress = _a.updateBulkUploadProgress, exports.
|
|
559
|
+
exports.bulkUploadReceipts = _a.bulkUploadReceipts, exports.updateBulkUploadProgress = _a.updateBulkUploadProgress, exports.bulkUploadReceiptsSuccess = _a.bulkUploadReceiptsSuccess, exports.bulkUploadReceiptsFailure = _a.bulkUploadReceiptsFailure, exports.bulkUploadAutomatchingTimedOut = _a.bulkUploadAutomatchingTimedOut, exports.pusherBatchStatusUpdate = _a.pusherBatchStatusUpdate, exports.requestMissingReceiptsTabNavigation = _a.requestMissingReceiptsTabNavigation, exports.clearMissingReceiptsTabNavigation = _a.clearMissingReceiptsTabNavigation, exports.fetchBulkUploadBatchDetailsSuccess = _a.fetchBulkUploadBatchDetailsSuccess, exports.fetchBulkUploadBatchDetailsFailure = _a.fetchBulkUploadBatchDetailsFailure, exports.storeBatchDetails = _a.storeBatchDetails, exports.batchDetailFetchFailed = _a.batchDetailFetchFailed, exports.setInitialBatchDetailsLoading = _a.setInitialBatchDetailsLoading, exports.fetchMoreBatchDetails = _a.fetchMoreBatchDetails, exports.fetchMoreBatchDetailsComplete = _a.fetchMoreBatchDetailsComplete, exports.fetchMoreBatchDetailsFailure = _a.fetchMoreBatchDetailsFailure, exports.fetchBulkUploadBatches = _a.fetchBulkUploadBatches, exports.fetchBulkUploadBatchesSuccess = _a.fetchBulkUploadBatchesSuccess, exports.fetchBulkUploadBatchesFailure = _a.fetchBulkUploadBatchesFailure, exports.confirmBulkUploadMatch = _a.confirmBulkUploadMatch, exports.confirmBulkUploadMatchSuccess = _a.confirmBulkUploadMatchSuccess, exports.confirmBulkUploadMatchFailure = _a.confirmBulkUploadMatchFailure, exports.setBulkUploadResultsTab = _a.setBulkUploadResultsTab, exports.setBulkUploadCompletedSubTab = _a.setBulkUploadCompletedSubTab, exports.setBulkUploadSortConfig = _a.setBulkUploadSortConfig, exports.clearBulkUpload = _a.clearBulkUpload, exports.searchTransactionsForManualMatch = _a.searchTransactionsForManualMatch, exports.searchTransactionsForManualMatchSuccess = _a.searchTransactionsForManualMatchSuccess, exports.searchTransactionsForManualMatchFailure = _a.searchTransactionsForManualMatchFailure, exports.clearManualSearchResults = _a.clearManualSearchResults, exports.acknowledgeBulkUploadConfirmMatchComplete = _a.acknowledgeBulkUploadConfirmMatchComplete,
|
|
583
560
|
// Completed Transactions
|
|
584
561
|
exports.fetchCompletedTransactions = _a.fetchCompletedTransactions, exports.fetchCompletedTransactionsSuccess = _a.fetchCompletedTransactionsSuccess, exports.fetchCompletedTransactionsFailure = _a.fetchCompletedTransactionsFailure;
|
|
585
562
|
exports.default = expenseAutomationMissingReceiptsView.reducer;
|
|
@@ -83,8 +83,6 @@ export interface BatchDetails {
|
|
|
83
83
|
files: BatchFile[];
|
|
84
84
|
status: BatchStatusValue;
|
|
85
85
|
summary: BatchSummary;
|
|
86
|
-
/** Present when batch-details API includes `user_id` (uploader). */
|
|
87
|
-
userId?: string;
|
|
88
86
|
}
|
|
89
87
|
export interface BatchListItem {
|
|
90
88
|
batchId: ID;
|
|
@@ -95,7 +93,6 @@ export interface BatchListItem {
|
|
|
95
93
|
possibleMatchesCount: number;
|
|
96
94
|
status: string;
|
|
97
95
|
totalFiles: number;
|
|
98
|
-
userId: string;
|
|
99
96
|
}
|
|
100
97
|
export interface ManualSearchResult {
|
|
101
98
|
amount: number;
|
|
@@ -147,7 +144,6 @@ export interface BulkUploadState {
|
|
|
147
144
|
phase: BulkUploadPhase;
|
|
148
145
|
sortKey: BulkUploadSortKey;
|
|
149
146
|
sortOrder: SortOrder;
|
|
150
|
-
uploadedFileCount: number;
|
|
151
147
|
uploadProgress: number;
|
|
152
148
|
uploadStatus: FetchStateAndError;
|
|
153
149
|
currentBatchId?: ID;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "4.20.
|
|
3
|
+
"version": "4.20.4",
|
|
4
4
|
"description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"find-dead-code": "ts-prune | grep -v '(used in module)'",
|
|
112
112
|
"find-unused-exports": "ts-unused-exports ./tsconfig.json",
|
|
113
113
|
"circular-dependency": "npx madge --circular --extensions ts ./src",
|
|
114
|
-
"build": "concurrently --kill-others-on-fail --handle-input \"echo 'Running ESLint...' && eslint . --ext .js,.jsx,.ts,.tsx\" \"echo 'TypeScript build in progress...' && time tsc && echo 'ESM build...' && tsc -p tsconfig.esm.json\"",
|
|
114
|
+
"build": "concurrently --kill-others-on-fail --handle-input \"echo 'Running ESLint...' && eslint . --ext .js,.jsx,.ts,.tsx\" \"echo 'TypeScript build in progress...' && time tsc && echo 'ESM build...' && tsc -p tsconfig.esm.json\" \"echo 'Running tests and typecheck...' && pnpm test\" && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
|
|
115
115
|
"only-build": "eslint . --ext .js,.jsx,.ts,.tsx && time tsc && tsc -p tsconfig.esm.json && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
|
|
116
116
|
"only-build-dev": "eslint . --ext .js,.jsx,.ts,.tsx && time tsc -p tsconfig.dev.json && tsc -p tsconfig.esm.dev.json && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
|
|
117
117
|
"format": "prettier --write --ignore-unknown \"src/**/*\" && pnpm lint",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { filter, mergeMap } from 'rxjs/operators';
|
|
3
|
-
import { fetchCompletedTransactions, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, } from '../../reducers/missingReceiptsViewReducer';
|
|
4
|
-
/**
|
|
5
|
-
* Completed transactions are cached per sort key/order/sub-tab. After a sort or sub-tab
|
|
6
|
-
* change, the fetch epic would otherwise skip the network when that cache entry already
|
|
7
|
-
* exists — dispatch a cache-bypassing initial fetch whenever either changes from the UI.
|
|
8
|
-
*/
|
|
9
|
-
export const refetchCompletedTransactionsOnBulkUploadSortEpic = (actions$) => {
|
|
10
|
-
return actions$.pipe(filter((action) => setBulkUploadSortConfig.match(action) ||
|
|
11
|
-
setBulkUploadCompletedSubTab.match(action)), mergeMap(() => of(fetchCompletedTransactions(undefined, true))));
|
|
12
|
-
};
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { EMPTY, concat, from, of } from 'rxjs';
|
|
2
|
-
import { catchError, concatMap, filter, mergeMap, take } from 'rxjs/operators';
|
|
3
|
-
import { isSuccessResponse } from '../../../../responsePayload';
|
|
4
|
-
import { isBatchDetailsStatusPendingOrProcessing, toBatchListItem, } from '../../payload/missingReceiptsPayload';
|
|
5
|
-
import { fetchBulkUploadBatchesSuccess, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, } from '../../reducers/missingReceiptsViewReducer';
|
|
6
|
-
import { rollingCalendarDateRangeInclusive } from '../../helpers/rollingCalendarDateRangeInclusive';
|
|
7
|
-
import { toMonthYearPeriodId } from '../../../../commonStateTypes/timePeriod';
|
|
8
|
-
import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
|
|
9
|
-
/** Mirrors `BULK_UPLOAD_BATCH_LIST_DATE_RANGE_DAYS` in `fetchBulkUploadBatchesEpic` — rolling, period-agnostic. */
|
|
10
|
-
const BULK_UPLOAD_BATCH_LIST_DATE_RANGE_DAYS = 30;
|
|
11
|
-
/**
|
|
12
|
-
* On missing-receipts entry / period switch, hydrate the automatching banner for the logged-in
|
|
13
|
-
* user without relying on UI-driven list fetches (the Missing tab does not fetch the batch list
|
|
14
|
-
* while `phase === 'idle'`). Flow:
|
|
15
|
-
* 1. Call `GET /1.0/batches` (rolling 30-day window).
|
|
16
|
-
* 2. Emit `fetchBulkUploadBatchesSuccess` so `batchListByPeriod` is populated for the selected
|
|
17
|
-
* period (prevents a duplicate list fetch when the user switches to the Unmatched tab).
|
|
18
|
-
* 3. For each `processing|pending` row, call `GET /1.0/batches/:id` in order; for the first row
|
|
19
|
-
* whose details `user_id` matches the logged-in user and whose status is still
|
|
20
|
-
* pending/processing, dispatch `restoreBulkUploadMatchingState` and stop.
|
|
21
|
-
*/
|
|
22
|
-
export const restoreBulkUploadAutomatchingOnMountEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(restoreBulkUploadAutomatchingOnMount.match), mergeMap(() => {
|
|
23
|
-
const state = state$.value;
|
|
24
|
-
const { expenseAutomationMissingReceiptsViewState: { bulkUpload }, expenseAutomationViewState: { selectedPeriodByTenantId }, } = state;
|
|
25
|
-
if (bulkUpload.phase !== 'idle') {
|
|
26
|
-
return EMPTY;
|
|
27
|
-
}
|
|
28
|
-
if (bulkUpload.batchListFetchState.fetchState === 'In-Progress') {
|
|
29
|
-
return EMPTY;
|
|
30
|
-
}
|
|
31
|
-
const loggedInUserId = state.tenantState.loggedInUser?.userId;
|
|
32
|
-
if (loggedInUserId == null) {
|
|
33
|
-
return EMPTY;
|
|
34
|
-
}
|
|
35
|
-
const currentTenant = getCurrentTenant(state);
|
|
36
|
-
const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
|
|
37
|
-
if (selectedPeriod == null) {
|
|
38
|
-
return EMPTY;
|
|
39
|
-
}
|
|
40
|
-
const { end, start } = rollingCalendarDateRangeInclusive(BULK_UPLOAD_BATCH_LIST_DATE_RANGE_DAYS);
|
|
41
|
-
const queryParam = {
|
|
42
|
-
start_date: start,
|
|
43
|
-
end_date: end,
|
|
44
|
-
sort_order: 'desc',
|
|
45
|
-
};
|
|
46
|
-
const listUrl = `${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches?query=${encodeURIComponent(JSON.stringify(queryParam))}`;
|
|
47
|
-
const detailsBaseUrl = `${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/`;
|
|
48
|
-
const periodId = toMonthYearPeriodId(selectedPeriod);
|
|
49
|
-
const alreadyCached = (bulkUpload.batchListByPeriod[periodId] ?? []).length > 0 &&
|
|
50
|
-
bulkUpload.batchListFetchState.fetchState === 'Completed';
|
|
51
|
-
const listSource = alreadyCached
|
|
52
|
-
? of(null)
|
|
53
|
-
: zeniAPI.getJSON(listUrl).pipe(catchError(() => of(null)));
|
|
54
|
-
return listSource.pipe(mergeMap((listResponse) => {
|
|
55
|
-
const batchList = alreadyCached
|
|
56
|
-
? bulkUpload.batchListByPeriod[periodId] ?? []
|
|
57
|
-
: listResponse != null &&
|
|
58
|
-
isSuccessResponse(listResponse) &&
|
|
59
|
-
listResponse.data != null
|
|
60
|
-
? listResponse.data.batches.map(toBatchListItem)
|
|
61
|
-
: null;
|
|
62
|
-
if (batchList == null) {
|
|
63
|
-
return EMPTY;
|
|
64
|
-
}
|
|
65
|
-
const successAction = alreadyCached
|
|
66
|
-
? null
|
|
67
|
-
: fetchBulkUploadBatchesSuccess({
|
|
68
|
-
batchList,
|
|
69
|
-
selectedPeriod,
|
|
70
|
-
});
|
|
71
|
-
const processingBatches = batchList.filter((b) => {
|
|
72
|
-
const status = b.status.toLowerCase();
|
|
73
|
-
return status === 'processing' || status === 'pending';
|
|
74
|
-
});
|
|
75
|
-
const restoreStream = from(processingBatches).pipe(concatMap((batch) => zeniAPI
|
|
76
|
-
.getJSON(`${detailsBaseUrl}${batch.batchId}`)
|
|
77
|
-
.pipe(mergeMap((response) => {
|
|
78
|
-
if (!isSuccessResponse(response) || response.data == null) {
|
|
79
|
-
return EMPTY;
|
|
80
|
-
}
|
|
81
|
-
const data = response.data;
|
|
82
|
-
const detailsUserId = data.user_id;
|
|
83
|
-
if (detailsUserId == null ||
|
|
84
|
-
detailsUserId !== loggedInUserId) {
|
|
85
|
-
return EMPTY;
|
|
86
|
-
}
|
|
87
|
-
if (!isBatchDetailsStatusPendingOrProcessing(data.status)) {
|
|
88
|
-
return EMPTY;
|
|
89
|
-
}
|
|
90
|
-
return of(restoreBulkUploadMatchingState({
|
|
91
|
-
batchId: batch.batchId,
|
|
92
|
-
totalFiles: batch.totalFiles,
|
|
93
|
-
}));
|
|
94
|
-
}), catchError(() => EMPTY))), take(1));
|
|
95
|
-
return successAction != null
|
|
96
|
-
? concat(of(successAction), restoreStream)
|
|
97
|
-
: restoreStream;
|
|
98
|
-
}));
|
|
99
|
-
}));
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_DATE_FORMAT } from '../../../commonStateTypes/fiscalYearHelpers/formatZeniDateFY';
|
|
2
|
-
import { dateNow } from '../../../zeniDayJS';
|
|
3
|
-
/**
|
|
4
|
-
* Local calendar dates from (end − (days − 1)) through end, inclusive.
|
|
5
|
-
*/
|
|
6
|
-
export function rollingCalendarDateRangeInclusive(days) {
|
|
7
|
-
const end = dateNow().startOf('day');
|
|
8
|
-
const start = end.subtract(days - 1, 'day');
|
|
9
|
-
return {
|
|
10
|
-
end: end.format(DEFAULT_DATE_FORMAT),
|
|
11
|
-
start: start.format(DEFAULT_DATE_FORMAT),
|
|
12
|
-
};
|
|
13
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ActionsObservable } from 'redux-observable';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
import { fetchCompletedTransactions, setBulkUploadCompletedSubTab, setBulkUploadSortConfig } from '../../reducers/missingReceiptsViewReducer';
|
|
4
|
-
export type ActionType = ReturnType<typeof setBulkUploadSortConfig> | ReturnType<typeof setBulkUploadCompletedSubTab> | ReturnType<typeof fetchCompletedTransactions>;
|
|
5
|
-
/**
|
|
6
|
-
* Completed transactions are cached per sort key/order/sub-tab. After a sort or sub-tab
|
|
7
|
-
* change, the fetch epic would otherwise skip the network when that cache entry already
|
|
8
|
-
* exists — dispatch a cache-bypassing initial fetch whenever either changes from the UI.
|
|
9
|
-
*/
|
|
10
|
-
export declare const refetchCompletedTransactionsOnBulkUploadSortEpic: (actions$: ActionsObservable<ActionType>) => Observable<ActionType>;
|