@zeniai/client-epic-state 4.19.37-betaVR27 → 4.19.37-betaVR4
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/epic.d.ts +1 -2
- package/lib/epic.js +1 -2
- package/lib/esm/epic.js +1 -2
- package/lib/esm/index.js +2 -2
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/confirmBulkUploadMatchEpic.js +2 -2
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +13 -22
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +1 -7
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +3 -7
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +23 -45
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +24 -65
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +32 -33
- package/lib/esm/view/expenseAutomationView/payload/missingReceiptsPayload.js +16 -63
- package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +26 -163
- package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +13 -109
- package/lib/index.d.ts +2 -2
- package/lib/index.js +32 -37
- package/lib/tsconfig.typecheck.tsbuildinfo +1 -0
- package/lib/view/expenseAutomationView/epics/missingReceipts/confirmBulkUploadMatchEpic.js +1 -1
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +11 -20
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +1 -7
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +2 -6
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.d.ts +2 -3
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +20 -43
- package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.d.ts +3 -11
- package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +22 -63
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +7 -5
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +28 -29
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.d.ts +31 -30
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.js +18 -69
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +6 -25
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +27 -165
- package/lib/view/expenseAutomationView/selectorTypes/missingReceiptsSelectorTypes.d.ts +0 -8
- package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +13 -109
- package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +1 -21
- package/package.json +2 -2
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +0 -34
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.d.ts +0 -8
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +0 -38
|
@@ -9,8 +9,6 @@ const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
|
|
|
9
9
|
const tenantSelector_1 = require("../../../entity/tenant/tenantSelector");
|
|
10
10
|
const transactionSelector_1 = require("../../../entity/transaction/transactionSelector");
|
|
11
11
|
const expenseAutomationViewSelectorTypes_1 = require("../selectorTypes/expenseAutomationViewSelectorTypes");
|
|
12
|
-
const missingReceiptsPayload_1 = require("../payload/missingReceiptsPayload");
|
|
13
|
-
const missingReceiptsViewReducer_1 = require("../reducers/missingReceiptsViewReducer");
|
|
14
12
|
function getExpenseAutomationMissingReceiptsView(state) {
|
|
15
13
|
const { expenseAutomationMissingReceiptsViewState, expenseAutomationViewState, transactionState, monthEndCloseChecksState, } = state;
|
|
16
14
|
const currentTenant = (0, tenantSelector_1.getCurrentTenant)(state);
|
|
@@ -55,32 +53,14 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
55
53
|
const completionStatus = missingReceiptsCompletionStatus != null
|
|
56
54
|
? missingReceiptsCompletionStatus
|
|
57
55
|
: 'incomplete';
|
|
58
|
-
const { bulkUpload
|
|
56
|
+
const { bulkUpload } = expenseAutomationMissingReceiptsViewState;
|
|
59
57
|
const currentBatchStatus = bulkUpload.currentBatchId != null
|
|
60
58
|
? bulkUpload.batchStatusById[bulkUpload.currentBatchId]
|
|
61
59
|
: undefined;
|
|
62
|
-
const
|
|
63
|
-
? bulkUpload.
|
|
64
|
-
: [];
|
|
65
|
-
/**
|
|
66
|
-
* Primary "Unmatched" batch = first completed batch in platform list order, preferring the
|
|
67
|
-
* first batch that still has un_matched/no_match work when any completed batch has such work.
|
|
68
|
-
* Batches without details yet: wait if the list row still reports unmatched work; otherwise skip
|
|
69
|
-
* so we do not block the whole tab while other rows are not fetched yet.
|
|
70
|
-
*/
|
|
71
|
-
const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(batchList, bulkUpload.batchDetailsById, bulkUpload.failedBatchDetailIds);
|
|
72
|
-
/** During upload/matching, the in-flight batch may not appear in batchList yet — prefer currentBatchId. */
|
|
73
|
-
const unmatchedSectionBatchId = bulkUpload.phase === 'matching' || bulkUpload.phase === 'uploading'
|
|
74
|
-
? bulkUpload.currentBatchId ?? primaryBatchIdFromDetailsOrder
|
|
75
|
-
: primaryBatchIdFromDetailsOrder;
|
|
76
|
-
const completedBatchesInApiOrder = batchList.filter((b) => (0, missingReceiptsPayload_1.isBatchListStatusCompleted)(b.status));
|
|
77
|
-
const currentBatchDetails = unmatchedSectionBatchId != null
|
|
78
|
-
? bulkUpload.batchDetailsById[unmatchedSectionBatchId]
|
|
60
|
+
const currentBatchDetails = bulkUpload.currentBatchId != null
|
|
61
|
+
? bulkUpload.batchDetailsById[bulkUpload.currentBatchId]
|
|
79
62
|
: undefined;
|
|
80
|
-
const resolvedFiles = currentBatchDetails?.files.map((file) => resolveBatchFile(file,
|
|
81
|
-
const failedIds = new Set(bulkUpload.failedBatchDetailIds);
|
|
82
|
-
const hasMoreBatchDetails = completedBatchesInApiOrder.some((b) => bulkUpload.batchDetailsById[b.batchId] == null &&
|
|
83
|
-
!failedIds.has(b.batchId));
|
|
63
|
+
const resolvedFiles = currentBatchDetails?.files.map((file) => resolveBatchFile(file, transactionState));
|
|
84
64
|
const getSortValue = (file) => {
|
|
85
65
|
const t = file.matchedTransaction;
|
|
86
66
|
if (t == null) {
|
|
@@ -118,14 +98,11 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
118
98
|
: 0,
|
|
119
99
|
}
|
|
120
100
|
: { total: 0, processed: 0, percentage: 0 };
|
|
101
|
+
const batchList = monthYearPeriodId != null
|
|
102
|
+
? bulkUpload.batchListByPeriod[monthYearPeriodId] ?? []
|
|
103
|
+
: [];
|
|
121
104
|
const batchListFetchState = bulkUpload.batchListFetchState;
|
|
122
|
-
|
|
123
|
-
* When primary batch is not resolved yet, still aggregate unmatched files from every batch
|
|
124
|
-
* that has details loaded (otherwise past is empty and receipts vanish from the UI).
|
|
125
|
-
*/
|
|
126
|
-
const pastBatches = unmatchedSectionBatchId != null
|
|
127
|
-
? batchList.filter((b) => b.batchId !== unmatchedSectionBatchId)
|
|
128
|
-
: batchList;
|
|
105
|
+
const pastBatches = batchList.filter((b) => b.batchId !== bulkUpload.currentBatchId);
|
|
129
106
|
const pastUnmatchedFiles = pastBatches.flatMap((b) => {
|
|
130
107
|
const details = bulkUpload.batchDetailsById[b.batchId];
|
|
131
108
|
if (details == null) {
|
|
@@ -133,13 +110,10 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
133
110
|
}
|
|
134
111
|
return details.files
|
|
135
112
|
.filter((f) => f.status === 'un_matched' || f.status === 'no_match')
|
|
136
|
-
.map((f) => resolveBatchFile(f,
|
|
113
|
+
.map((f) => resolveBatchFile(f, transactionState));
|
|
137
114
|
});
|
|
138
|
-
const
|
|
139
|
-
?
|
|
140
|
-
: undefined;
|
|
141
|
-
const completedTransactionsForPeriod = completedTransactionsCacheKey != null
|
|
142
|
-
? bulkUpload.completedTransactionsByPeriod[completedTransactionsCacheKey]
|
|
115
|
+
const completedTransactionsForPeriod = monthYearPeriodId != null
|
|
116
|
+
? bulkUpload.completedTransactionsByPeriod[monthYearPeriodId]
|
|
143
117
|
: undefined;
|
|
144
118
|
const completedTransactionIds = completedTransactionsForPeriod?.transactionIds ?? [];
|
|
145
119
|
const resolvedCompletedTransactions = (0, transactionSelector_1.getSupportedTransactionsByIds)(transactionState, completedTransactionIds);
|
|
@@ -152,13 +126,6 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
152
126
|
summary: currentBatchDetails.summary,
|
|
153
127
|
}
|
|
154
128
|
: undefined;
|
|
155
|
-
const manualSearchResults = bulkUpload.manualSearch.results.map((r) => {
|
|
156
|
-
const t = (0, transactionSelector_1.getSupportedTransactionById)(transactionState, r.transactionId);
|
|
157
|
-
return {
|
|
158
|
-
...r,
|
|
159
|
-
vendorLogo: r.vendorLogo ?? t?.logo?.href,
|
|
160
|
-
};
|
|
161
|
-
});
|
|
162
129
|
return {
|
|
163
130
|
fetchState,
|
|
164
131
|
error,
|
|
@@ -167,7 +134,6 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
167
134
|
refreshStatus,
|
|
168
135
|
transactions: sortedTransactions,
|
|
169
136
|
completionStatus,
|
|
170
|
-
pendingMissingReceiptsTabNavigation: pendingMissingReceiptsTabNavigation ?? null,
|
|
171
137
|
bulkUpload: {
|
|
172
138
|
phase: bulkUpload.phase,
|
|
173
139
|
uploadStatus: bulkUpload.uploadStatus,
|
|
@@ -194,72 +160,12 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
194
160
|
pastBatches,
|
|
195
161
|
pastUnmatchedFiles,
|
|
196
162
|
confirmMatchStatus: bulkUpload.confirmMatchStatus,
|
|
197
|
-
|
|
198
|
-
hasMoreBatchDetails,
|
|
199
|
-
batchDetailsPaginationState: bulkUpload.batchDetailsPaginationState,
|
|
200
|
-
manualSearch: {
|
|
201
|
-
...bulkUpload.manualSearch,
|
|
202
|
-
results: manualSearchResults,
|
|
203
|
-
},
|
|
163
|
+
manualSearch: bulkUpload.manualSearch,
|
|
204
164
|
uploadProgress: bulkUpload.uploadProgress,
|
|
205
165
|
},
|
|
206
166
|
};
|
|
207
167
|
}
|
|
208
|
-
function
|
|
209
|
-
return details.files.some((f) => f.status === 'un_matched' || f.status === 'no_match');
|
|
210
|
-
}
|
|
211
|
-
/** List row summary before batch details load — aligns with unmatched / possible-match work. */
|
|
212
|
-
function batchListItemHasUnmatchedWork(batch) {
|
|
213
|
-
return batch.noMatchCount > 0 || batch.possibleMatchesCount > 0;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* `batchList` must match platform order (same sequence as the bulk-upload batches API). Picks the
|
|
217
|
-
* primary batch for the top "Unmatched" section. Skips failed detail fetches.
|
|
218
|
-
*
|
|
219
|
-
* If details are not loaded for an earlier list row but that row reports no unmatched work, we
|
|
220
|
-
* skip it so later rows with loaded details can be primary (avoids an empty tab when the first
|
|
221
|
-
* fetch page only loaded later batches). If the list reports unmatched work but details are still
|
|
222
|
-
* loading, we wait (undefined) so primary order stays correct once details arrive.
|
|
223
|
-
*/
|
|
224
|
-
function getPrimaryBatchIdFromBatchListOrder(batchListInPlatformOrder, batchDetailsById, failedBatchDetailIds) {
|
|
225
|
-
const failedIds = new Set(failedBatchDetailIds);
|
|
226
|
-
const anyCompletedBatchHasUnmatchedWork = batchListInPlatformOrder.some((b) => {
|
|
227
|
-
if (failedIds.has(b.batchId)) {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
const d = batchDetailsById[b.batchId];
|
|
231
|
-
if (d != null &&
|
|
232
|
-
d.status === 'completed' &&
|
|
233
|
-
batchDetailsHasUnmatchedWork(d)) {
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
236
|
-
return d == null && batchListItemHasUnmatchedWork(b);
|
|
237
|
-
});
|
|
238
|
-
for (const batch of batchListInPlatformOrder) {
|
|
239
|
-
if (failedIds.has(batch.batchId)) {
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
const details = batchDetailsById[batch.batchId];
|
|
243
|
-
if (details == null) {
|
|
244
|
-
if (batchListItemHasUnmatchedWork(batch)) {
|
|
245
|
-
return undefined;
|
|
246
|
-
}
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
if (details.status !== 'completed') {
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
if (anyCompletedBatchHasUnmatchedWork) {
|
|
253
|
-
if (batchDetailsHasUnmatchedWork(details)) {
|
|
254
|
-
return batch.batchId;
|
|
255
|
-
}
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
return batch.batchId;
|
|
259
|
-
}
|
|
260
|
-
return undefined;
|
|
261
|
-
}
|
|
262
|
-
function resolveBatchFile(file, batchId, transactionState) {
|
|
168
|
+
function resolveBatchFile(file, transactionState) {
|
|
263
169
|
const matchedTransaction = file.matchedTransactionId != null
|
|
264
170
|
? (0, transactionSelector_1.getSupportedTransactionById)(transactionState, file.matchedTransactionId)
|
|
265
171
|
: undefined;
|
|
@@ -273,8 +179,6 @@ function resolveBatchFile(file, batchId, transactionState) {
|
|
|
273
179
|
.filter((c) => c != null);
|
|
274
180
|
return {
|
|
275
181
|
attachmentId: file.attachmentId,
|
|
276
|
-
batchId,
|
|
277
|
-
fileDownloadUrl: file.fileDownloadUrl,
|
|
278
182
|
fileId: file.fileId,
|
|
279
183
|
filename: file.filename,
|
|
280
184
|
filePreviewUrl: file.filePreviewUrl,
|
|
@@ -36,7 +36,6 @@ export interface MatchCandidate {
|
|
|
36
36
|
}
|
|
37
37
|
export interface BatchFile {
|
|
38
38
|
attachmentId: ID;
|
|
39
|
-
fileDownloadUrl: string | null;
|
|
40
39
|
fileId: ID;
|
|
41
40
|
filename: string;
|
|
42
41
|
filePreviewUrl: string | null;
|
|
@@ -86,18 +85,11 @@ export interface ManualSearchResult {
|
|
|
86
85
|
transactionId: ID;
|
|
87
86
|
transactionType: string;
|
|
88
87
|
vendorName: string;
|
|
89
|
-
/** Present when API/merged transaction state supplies a logo URL. */
|
|
90
|
-
vendorLogo?: string;
|
|
91
88
|
}
|
|
92
89
|
export interface ManualSearchState {
|
|
93
90
|
fetchState: FetchStateAndError;
|
|
94
|
-
/** True while appending the next page (initial search uses fetchState only). */
|
|
95
|
-
isLoadingMore: boolean;
|
|
96
|
-
nextPageToken: string | null;
|
|
97
|
-
pageSize: number;
|
|
98
91
|
results: ManualSearchResult[];
|
|
99
92
|
searchQuery: string;
|
|
100
|
-
totalCount: number;
|
|
101
93
|
}
|
|
102
94
|
export type CompletedTransactionsMatchType = 'all' | 'ai_accountant' | 'manual';
|
|
103
95
|
export interface CompletedTransactionsState {
|
|
@@ -108,21 +100,14 @@ export interface CompletedTransactionsState {
|
|
|
108
100
|
}
|
|
109
101
|
export interface BulkUploadState {
|
|
110
102
|
batchDetailsById: Record<ID, BatchDetails>;
|
|
111
|
-
batchDetailsPaginationState: FetchStateAndError;
|
|
112
103
|
batchListByPeriod: Record<MonthYearPeriodId, BatchListItem[]>;
|
|
113
104
|
batchListFetchState: FetchStateAndError;
|
|
114
105
|
batchStatusById: Record<ID, BatchStatus>;
|
|
115
106
|
completedSubTab: CompletedSubTab;
|
|
116
|
-
completedTransactionsByPeriod: Record<
|
|
107
|
+
completedTransactionsByPeriod: Record<MonthYearPeriodId, CompletedTransactionsState>;
|
|
117
108
|
confirmMatchStatus: FetchStateAndError;
|
|
118
109
|
currentResultsTab: BulkUploadResultsTab;
|
|
119
|
-
failedBatchDetailIds: ID[];
|
|
120
|
-
/**
|
|
121
|
-
* Incremented when manual search Redux state is cleared so Unmatched `ManualSearchInput`
|
|
122
|
-
* instances remount and drop local query text.
|
|
123
|
-
*/
|
|
124
110
|
manualSearch: ManualSearchState;
|
|
125
|
-
manualSearchUiResetKey: number;
|
|
126
111
|
phase: BulkUploadPhase;
|
|
127
112
|
sortKey: BulkUploadSortKey;
|
|
128
113
|
sortOrder: SortOrder;
|
|
@@ -132,11 +117,6 @@ export interface BulkUploadState {
|
|
|
132
117
|
}
|
|
133
118
|
export interface MissingReceiptsViewState extends FetchedState {
|
|
134
119
|
bulkUpload: BulkUploadState;
|
|
135
|
-
/**
|
|
136
|
-
* When set, the app shell should switch the Missing Receipts sub-tab (e.g. to Unmatched)
|
|
137
|
-
* once, then clear via `clearMissingReceiptsTabNavigation`.
|
|
138
|
-
*/
|
|
139
|
-
pendingMissingReceiptsTabNavigation: BulkUploadResultsTab | null;
|
|
140
120
|
refreshStatus: FetchStateAndError;
|
|
141
121
|
transactionIdsBySelectedPeriod: Record<MonthYearPeriodId, ID[]>;
|
|
142
122
|
uiState: MissingReceiptsViewUIState;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "4.19.37-
|
|
3
|
+
"version": "4.19.37-betaVR4",
|
|
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
|
"format": "prettier --write --ignore-unknown \"src/**/*\" && pnpm lint",
|
|
117
117
|
"format-watch": "(git diff --name-only --diff-filter=ACM && git ls-files --others --exclude-standard) | grep -E '\\.(ts|tsx)$' | xargs prettier --write",
|
package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { concat, of } from 'rxjs';
|
|
2
|
-
import { catchError, exhaustMap, filter } from 'rxjs/operators';
|
|
3
|
-
import { toMonthYearPeriodId } from '../../../../commonStateTypes/timePeriod';
|
|
4
|
-
import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
|
|
5
|
-
import { createZeniAPIStatus } from '../../../../responsePayload';
|
|
6
|
-
import { filterBatchListItemsForBatchDetailsFetch } from '../../payload/missingReceiptsPayload';
|
|
7
|
-
import { fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, } from '../../reducers/missingReceiptsViewReducer';
|
|
8
|
-
import { fetchBatchDetailsByIds } from './fetchMultipleBatchDetailsEpic';
|
|
9
|
-
const MORE_BATCH_PAGE_SIZE = 1;
|
|
10
|
-
export const fetchMoreBatchDetailsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchMoreBatchDetails.match),
|
|
11
|
-
/** One page at a time — avoids duplicate loads if IO + scroll fallback both fire. */
|
|
12
|
-
exhaustMap(() => {
|
|
13
|
-
const state = state$.value;
|
|
14
|
-
const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationMissingReceiptsViewState: { bulkUpload }, } = state;
|
|
15
|
-
const currentTenant = getCurrentTenant(state);
|
|
16
|
-
const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
|
|
17
|
-
if (selectedPeriod == null) {
|
|
18
|
-
return of(fetchMoreBatchDetailsComplete());
|
|
19
|
-
}
|
|
20
|
-
const periodId = toMonthYearPeriodId(selectedPeriod);
|
|
21
|
-
const batchList = bulkUpload.batchListByPeriod[periodId] ?? [];
|
|
22
|
-
const failedIds = new Set(bulkUpload.failedBatchDetailIds);
|
|
23
|
-
const unfetchedBatches = filterBatchListItemsForBatchDetailsFetch(batchList).filter((batch) => bulkUpload.batchDetailsById[batch.batchId] == null &&
|
|
24
|
-
!failedIds.has(batch.batchId));
|
|
25
|
-
const unfetchedBatchIds = unfetchedBatches.map((batch) => batch.batchId);
|
|
26
|
-
if (unfetchedBatchIds.length === 0) {
|
|
27
|
-
return of(fetchMoreBatchDetailsComplete());
|
|
28
|
-
}
|
|
29
|
-
const nextPage = unfetchedBatchIds.slice(0, MORE_BATCH_PAGE_SIZE);
|
|
30
|
-
return concat(fetchBatchDetailsByIds(nextPage, zeniAPI), of(fetchMoreBatchDetailsComplete())).pipe(catchError((error) => of(fetchMoreBatchDetailsFailure({
|
|
31
|
-
error: createZeniAPIStatus('Unexpected Error', 'Fetch more batch details errored out: ' +
|
|
32
|
-
JSON.stringify(error)),
|
|
33
|
-
}))));
|
|
34
|
-
}));
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
|
|
4
|
-
import { RootState } from '../../../../reducer';
|
|
5
|
-
import { ZeniAPI } from '../../../../zeniAPI';
|
|
6
|
-
import { batchDetailFetchFailed, fetchBulkUploadBatchDetails, fetchBulkUploadBatchesSuccess, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, setInitialBatchDetailsLoading, storeBatchDetails } from '../../reducers/missingReceiptsViewReducer';
|
|
7
|
-
export type ActionType = ReturnType<typeof fetchBulkUploadBatchDetails> | ReturnType<typeof fetchBulkUploadBatchesSuccess> | ReturnType<typeof fetchMoreBatchDetails> | ReturnType<typeof fetchMoreBatchDetailsComplete> | ReturnType<typeof fetchMoreBatchDetailsFailure> | ReturnType<typeof batchDetailFetchFailed> | ReturnType<typeof setInitialBatchDetailsLoading> | ReturnType<typeof storeBatchDetails> | ReturnType<typeof updateTransactions>;
|
|
8
|
-
export declare const fetchMoreBatchDetailsEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchMoreBatchDetailsEpic = void 0;
|
|
4
|
-
const rxjs_1 = require("rxjs");
|
|
5
|
-
const operators_1 = require("rxjs/operators");
|
|
6
|
-
const timePeriod_1 = require("../../../../commonStateTypes/timePeriod");
|
|
7
|
-
const tenantSelector_1 = require("../../../../entity/tenant/tenantSelector");
|
|
8
|
-
const responsePayload_1 = require("../../../../responsePayload");
|
|
9
|
-
const missingReceiptsPayload_1 = require("../../payload/missingReceiptsPayload");
|
|
10
|
-
const missingReceiptsViewReducer_1 = require("../../reducers/missingReceiptsViewReducer");
|
|
11
|
-
const fetchMultipleBatchDetailsEpic_1 = require("./fetchMultipleBatchDetailsEpic");
|
|
12
|
-
const MORE_BATCH_PAGE_SIZE = 1;
|
|
13
|
-
const fetchMoreBatchDetailsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchMoreBatchDetails.match),
|
|
14
|
-
/** One page at a time — avoids duplicate loads if IO + scroll fallback both fire. */
|
|
15
|
-
(0, operators_1.exhaustMap)(() => {
|
|
16
|
-
const state = state$.value;
|
|
17
|
-
const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationMissingReceiptsViewState: { bulkUpload }, } = state;
|
|
18
|
-
const currentTenant = (0, tenantSelector_1.getCurrentTenant)(state);
|
|
19
|
-
const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
|
|
20
|
-
if (selectedPeriod == null) {
|
|
21
|
-
return (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.fetchMoreBatchDetailsComplete)());
|
|
22
|
-
}
|
|
23
|
-
const periodId = (0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod);
|
|
24
|
-
const batchList = bulkUpload.batchListByPeriod[periodId] ?? [];
|
|
25
|
-
const failedIds = new Set(bulkUpload.failedBatchDetailIds);
|
|
26
|
-
const unfetchedBatches = (0, missingReceiptsPayload_1.filterBatchListItemsForBatchDetailsFetch)(batchList).filter((batch) => bulkUpload.batchDetailsById[batch.batchId] == null &&
|
|
27
|
-
!failedIds.has(batch.batchId));
|
|
28
|
-
const unfetchedBatchIds = unfetchedBatches.map((batch) => batch.batchId);
|
|
29
|
-
if (unfetchedBatchIds.length === 0) {
|
|
30
|
-
return (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.fetchMoreBatchDetailsComplete)());
|
|
31
|
-
}
|
|
32
|
-
const nextPage = unfetchedBatchIds.slice(0, MORE_BATCH_PAGE_SIZE);
|
|
33
|
-
return (0, rxjs_1.concat)((0, fetchMultipleBatchDetailsEpic_1.fetchBatchDetailsByIds)(nextPage, zeniAPI), (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.fetchMoreBatchDetailsComplete)())).pipe((0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.fetchMoreBatchDetailsFailure)({
|
|
34
|
-
error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch more batch details errored out: ' +
|
|
35
|
-
JSON.stringify(error)),
|
|
36
|
-
}))));
|
|
37
|
-
}));
|
|
38
|
-
exports.fetchMoreBatchDetailsEpic = fetchMoreBatchDetailsEpic;
|