@zeniai/client-epic-state 4.19.37-betaVR16 → 4.19.37-betaVR17
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/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +1 -0
- package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +33 -11
- package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +1 -0
- package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +33 -11
- package/package.json +1 -1
package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js
CHANGED
|
@@ -9,6 +9,7 @@ export function fetchBatchDetailsByIds(batchIds, zeniAPI) {
|
|
|
9
9
|
if (batchIds.length === 0) {
|
|
10
10
|
return EMPTY;
|
|
11
11
|
}
|
|
12
|
+
console.log('fetchBatchDetailsByIds', batchIds);
|
|
12
13
|
return from(batchIds).pipe(mergeMap((batchId) => zeniAPI
|
|
13
14
|
.getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/${batchId}`)
|
|
14
15
|
.pipe(mergeMap((response) => {
|
|
@@ -56,12 +56,15 @@ export function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
56
56
|
const batchList = monthYearPeriodId != null
|
|
57
57
|
? bulkUpload.batchListByPeriod[monthYearPeriodId] ?? []
|
|
58
58
|
: [];
|
|
59
|
+
/** API returns newest-first (`sort_order: desc`); primary batch uses oldest-first order. */
|
|
60
|
+
const batchListChronological = orderBy(batchList, (b) => new Date(b.createdAt).valueOf(), 'asc');
|
|
59
61
|
/**
|
|
60
|
-
* Primary "Unmatched" batch = first batch in
|
|
61
|
-
*
|
|
62
|
-
*
|
|
62
|
+
* Primary "Unmatched" batch = first completed batch in chronological order, preferring the
|
|
63
|
+
* first batch that still has un_matched/no_match work when any completed batch has such work
|
|
64
|
+
* (so a newer fully-matched batch does not hide older unmatched receipts). If an earlier batch
|
|
65
|
+
* in that order has no details yet (still loading), we return undefined until it resolves.
|
|
63
66
|
*/
|
|
64
|
-
const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(
|
|
67
|
+
const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(batchListChronological, bulkUpload.batchDetailsById, bulkUpload.failedBatchDetailIds);
|
|
65
68
|
/** During upload/matching, the in-flight batch may not appear in batchList yet — prefer currentBatchId. */
|
|
66
69
|
const unmatchedSectionBatchId = bulkUpload.phase === 'matching' || bulkUpload.phase === 'uploading'
|
|
67
70
|
? bulkUpload.currentBatchId ?? primaryBatchIdFromDetailsOrder
|
|
@@ -183,14 +186,26 @@ export function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
183
186
|
},
|
|
184
187
|
};
|
|
185
188
|
}
|
|
189
|
+
function batchDetailsHasUnmatchedWork(details) {
|
|
190
|
+
return details.files.some((f) => f.status === 'un_matched' || f.status === 'no_match');
|
|
191
|
+
}
|
|
186
192
|
/**
|
|
187
|
-
*
|
|
188
|
-
* Skips failed detail fetches. Stops at the first batch with no details
|
|
189
|
-
* so
|
|
193
|
+
* `batchList` must be in chronological order (oldest first). Picks the primary batch for the
|
|
194
|
+
* top "Unmatched" section. Skips failed detail fetches. Stops at the first batch with no details
|
|
195
|
+
* yet (still loading) so we do not choose a later batch until earlier chronological rows resolve.
|
|
190
196
|
*/
|
|
191
|
-
function getPrimaryBatchIdFromBatchListOrder(
|
|
197
|
+
function getPrimaryBatchIdFromBatchListOrder(batchListChronological, batchDetailsById, failedBatchDetailIds) {
|
|
192
198
|
const failedIds = new Set(failedBatchDetailIds);
|
|
193
|
-
|
|
199
|
+
const anyCompletedBatchHasUnmatchedWork = batchListChronological.some((b) => {
|
|
200
|
+
if (failedIds.has(b.batchId)) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
const d = batchDetailsById[b.batchId];
|
|
204
|
+
return (d != null &&
|
|
205
|
+
d.status === 'completed' &&
|
|
206
|
+
batchDetailsHasUnmatchedWork(d));
|
|
207
|
+
});
|
|
208
|
+
for (const batch of batchListChronological) {
|
|
194
209
|
if (failedIds.has(batch.batchId)) {
|
|
195
210
|
continue;
|
|
196
211
|
}
|
|
@@ -198,9 +213,16 @@ function getPrimaryBatchIdFromBatchListOrder(batchList, batchDetailsById, failed
|
|
|
198
213
|
if (details == null) {
|
|
199
214
|
return undefined;
|
|
200
215
|
}
|
|
201
|
-
if (details.status
|
|
202
|
-
|
|
216
|
+
if (details.status !== 'completed') {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (anyCompletedBatchHasUnmatchedWork) {
|
|
220
|
+
if (batchDetailsHasUnmatchedWork(details)) {
|
|
221
|
+
return batch.batchId;
|
|
222
|
+
}
|
|
223
|
+
continue;
|
|
203
224
|
}
|
|
225
|
+
return batch.batchId;
|
|
204
226
|
}
|
|
205
227
|
return undefined;
|
|
206
228
|
}
|
package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js
CHANGED
|
@@ -13,6 +13,7 @@ function fetchBatchDetailsByIds(batchIds, zeniAPI) {
|
|
|
13
13
|
if (batchIds.length === 0) {
|
|
14
14
|
return rxjs_1.EMPTY;
|
|
15
15
|
}
|
|
16
|
+
console.log('fetchBatchDetailsByIds', batchIds);
|
|
16
17
|
return (0, rxjs_1.from)(batchIds).pipe((0, operators_1.mergeMap)((batchId) => zeniAPI
|
|
17
18
|
.getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/${batchId}`)
|
|
18
19
|
.pipe((0, operators_1.mergeMap)((response) => {
|
|
@@ -62,12 +62,15 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
62
62
|
const batchList = monthYearPeriodId != null
|
|
63
63
|
? bulkUpload.batchListByPeriod[monthYearPeriodId] ?? []
|
|
64
64
|
: [];
|
|
65
|
+
/** API returns newest-first (`sort_order: desc`); primary batch uses oldest-first order. */
|
|
66
|
+
const batchListChronological = (0, orderBy_1.default)(batchList, (b) => new Date(b.createdAt).valueOf(), 'asc');
|
|
65
67
|
/**
|
|
66
|
-
* Primary "Unmatched" batch = first batch in
|
|
67
|
-
*
|
|
68
|
-
*
|
|
68
|
+
* Primary "Unmatched" batch = first completed batch in chronological order, preferring the
|
|
69
|
+
* first batch that still has un_matched/no_match work when any completed batch has such work
|
|
70
|
+
* (so a newer fully-matched batch does not hide older unmatched receipts). If an earlier batch
|
|
71
|
+
* in that order has no details yet (still loading), we return undefined until it resolves.
|
|
69
72
|
*/
|
|
70
|
-
const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(
|
|
73
|
+
const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(batchListChronological, bulkUpload.batchDetailsById, bulkUpload.failedBatchDetailIds);
|
|
71
74
|
/** During upload/matching, the in-flight batch may not appear in batchList yet — prefer currentBatchId. */
|
|
72
75
|
const unmatchedSectionBatchId = bulkUpload.phase === 'matching' || bulkUpload.phase === 'uploading'
|
|
73
76
|
? bulkUpload.currentBatchId ?? primaryBatchIdFromDetailsOrder
|
|
@@ -189,14 +192,26 @@ function getExpenseAutomationMissingReceiptsView(state) {
|
|
|
189
192
|
},
|
|
190
193
|
};
|
|
191
194
|
}
|
|
195
|
+
function batchDetailsHasUnmatchedWork(details) {
|
|
196
|
+
return details.files.some((f) => f.status === 'un_matched' || f.status === 'no_match');
|
|
197
|
+
}
|
|
192
198
|
/**
|
|
193
|
-
*
|
|
194
|
-
* Skips failed detail fetches. Stops at the first batch with no details
|
|
195
|
-
* so
|
|
199
|
+
* `batchList` must be in chronological order (oldest first). Picks the primary batch for the
|
|
200
|
+
* top "Unmatched" section. Skips failed detail fetches. Stops at the first batch with no details
|
|
201
|
+
* yet (still loading) so we do not choose a later batch until earlier chronological rows resolve.
|
|
196
202
|
*/
|
|
197
|
-
function getPrimaryBatchIdFromBatchListOrder(
|
|
203
|
+
function getPrimaryBatchIdFromBatchListOrder(batchListChronological, batchDetailsById, failedBatchDetailIds) {
|
|
198
204
|
const failedIds = new Set(failedBatchDetailIds);
|
|
199
|
-
|
|
205
|
+
const anyCompletedBatchHasUnmatchedWork = batchListChronological.some((b) => {
|
|
206
|
+
if (failedIds.has(b.batchId)) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
const d = batchDetailsById[b.batchId];
|
|
210
|
+
return (d != null &&
|
|
211
|
+
d.status === 'completed' &&
|
|
212
|
+
batchDetailsHasUnmatchedWork(d));
|
|
213
|
+
});
|
|
214
|
+
for (const batch of batchListChronological) {
|
|
200
215
|
if (failedIds.has(batch.batchId)) {
|
|
201
216
|
continue;
|
|
202
217
|
}
|
|
@@ -204,9 +219,16 @@ function getPrimaryBatchIdFromBatchListOrder(batchList, batchDetailsById, failed
|
|
|
204
219
|
if (details == null) {
|
|
205
220
|
return undefined;
|
|
206
221
|
}
|
|
207
|
-
if (details.status
|
|
208
|
-
|
|
222
|
+
if (details.status !== 'completed') {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (anyCompletedBatchHasUnmatchedWork) {
|
|
226
|
+
if (batchDetailsHasUnmatchedWork(details)) {
|
|
227
|
+
return batch.batchId;
|
|
228
|
+
}
|
|
229
|
+
continue;
|
|
209
230
|
}
|
|
231
|
+
return batch.batchId;
|
|
210
232
|
}
|
|
211
233
|
return undefined;
|
|
212
234
|
}
|
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-betaVR17",
|
|
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",
|