@zeniai/client-epic-state 4.19.84-betaVR7 → 4.19.84-betaVR9
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/bulkUploadReceiptsEpic.js +7 -3
- package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +18 -1
- package/lib/esm/view/expenseAutomationView/payload/missingReceiptsPayload.js +31 -1
- package/lib/tsconfig.typecheck.tsbuildinfo +1 -1
- package/lib/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +7 -3
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +7 -1
- package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +18 -1
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.d.ts +11 -0
- package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.js +32 -1
- package/package.json +1 -1
|
@@ -12,9 +12,13 @@ export const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.p
|
|
|
12
12
|
.postFormData(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/receipts/bulk-upload`, formData)
|
|
13
13
|
.pipe(mergeMap((response) => {
|
|
14
14
|
if (isSuccessResponse(response) && response.data != null) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const batchId = String(response.data.batch_id ?? '').trim();
|
|
16
|
+
if (batchId === '') {
|
|
17
|
+
return of(bulkUploadReceiptsFailure({
|
|
18
|
+
error: createZeniAPIStatus('Unexpected Error', 'Bulk upload succeeded but batch_id was missing or empty.'),
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
return of(bulkUploadReceiptsSuccess({ batchId }));
|
|
18
22
|
}
|
|
19
23
|
return of(bulkUploadReceiptsFailure({ error: response.status }));
|
|
20
24
|
}), catchError((error) => of(bulkUploadReceiptsFailure({
|
package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EMPTY, from, merge, of, timer } from 'rxjs';
|
|
2
2
|
import { catchError, debounceTime, filter, mergeMap, switchMap, takeUntil, } from 'rxjs/operators';
|
|
3
|
+
import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
|
|
3
4
|
import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
|
|
4
5
|
import { isSuccessResponse } from '../../../../responsePayload';
|
|
5
6
|
import { extractTransactionPayloadsFromBatchFiles, isBatchDetailsApiStatusCompleted, toBatchDetails, } from '../../payload/missingReceiptsPayload';
|
|
@@ -18,8 +19,14 @@ export const pusherBatchStatusCompletionEpic = (actions$) => actions$.pipe(filte
|
|
|
18
19
|
}),
|
|
19
20
|
requestMissingReceiptsTabNavigation({ tab: 'unmatched' }),
|
|
20
21
|
])));
|
|
22
|
+
/**
|
|
23
|
+
* Fallback polling when Pusher is slow or unavailable. Network errors on a poll tick show one
|
|
24
|
+
* error snackbar per upload session (first failure only) so the user is not spammed every
|
|
25
|
+
* interval; Pusher or a later successful poll still completes the flow.
|
|
26
|
+
*/
|
|
21
27
|
export const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceiptsSuccess.match), mergeMap((action) => {
|
|
22
28
|
const { batchId } = action.payload;
|
|
29
|
+
let pollErrorNotified = false;
|
|
23
30
|
return timer(FALLBACK_FIRST_DELAY_MS, FALLBACK_POLL_INTERVAL_MS).pipe(takeUntil(merge(actions$.pipe(filter(clearBulkUpload.match)), actions$.pipe(filter(pusherBatchStatusUpdate.match), filter((a) => a.payload.batchId === batchId)), actions$.pipe(filter(fetchBulkUploadBatchDetailsSuccess.match), filter((a) => a.payload.batchId === batchId)))), switchMap(() => zeniAPI
|
|
24
31
|
.getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/${batchId}`)
|
|
25
32
|
.pipe(mergeMap((response) => {
|
|
@@ -38,5 +45,15 @@ export const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => act
|
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
return EMPTY;
|
|
41
|
-
}), catchError(() =>
|
|
48
|
+
}), catchError(() => {
|
|
49
|
+
if (!pollErrorNotified) {
|
|
50
|
+
pollErrorNotified = true;
|
|
51
|
+
return of(openSnackbar({
|
|
52
|
+
messageSection: 'receipts_upload',
|
|
53
|
+
messageText: 'failed',
|
|
54
|
+
type: 'error',
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
return EMPTY;
|
|
58
|
+
}))));
|
|
42
59
|
}));
|
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
import { toURL } from '../../../commonPayloadTypes/urlPayload';
|
|
2
2
|
import { getTransactionPayloadAmount, } from '../../../entity/transaction/payloadTypes/transactionPayload';
|
|
3
3
|
// -- Converter functions --
|
|
4
|
+
/**
|
|
5
|
+
* Maps batch-details API `files[].status` strings to canonical {@link BatchFile} statuses.
|
|
6
|
+
* The service may send aliases (`unmatched`, `possible_match`) or different separators; the UI
|
|
7
|
+
* only treats `un_matched` / `no_match` as work for the Unmatched tab.
|
|
8
|
+
*
|
|
9
|
+
* **Unknown values:** Any string not matched below is returned as-is (typed as
|
|
10
|
+
* {@link BatchFile} status). Callers should not assume exhaustiveness—treat unknown statuses in
|
|
11
|
+
* UI as “other” (e.g. show a generic label or fall back to a safe bucket) until the API contract
|
|
12
|
+
* adds an explicit mapping.
|
|
13
|
+
*/
|
|
14
|
+
export function normalizeBatchFileStatus(raw) {
|
|
15
|
+
const s = raw.trim().toLowerCase().replace(/-/g, '_');
|
|
16
|
+
switch (s) {
|
|
17
|
+
case 'un_matched':
|
|
18
|
+
case 'unmatched':
|
|
19
|
+
return 'un_matched';
|
|
20
|
+
case 'no_match':
|
|
21
|
+
case 'nomatch':
|
|
22
|
+
return 'no_match';
|
|
23
|
+
case 'matched':
|
|
24
|
+
return 'matched';
|
|
25
|
+
case 'failed':
|
|
26
|
+
return 'failed';
|
|
27
|
+
case 'possible_match':
|
|
28
|
+
case 'possiblematch':
|
|
29
|
+
return 'un_matched';
|
|
30
|
+
default:
|
|
31
|
+
return raw;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
4
34
|
export function toBatchFile(payload, filesEndPoint) {
|
|
5
35
|
return {
|
|
6
36
|
attachmentId: payload.attachment_id,
|
|
@@ -16,7 +46,7 @@ export function toBatchFile(payload, filesEndPoint) {
|
|
|
16
46
|
filename: payload.filename,
|
|
17
47
|
matchSource: payload.match_source,
|
|
18
48
|
matchedTransactionId: payload.matched_transaction?.transaction_id,
|
|
19
|
-
status: payload.status,
|
|
49
|
+
status: normalizeBatchFileStatus(payload.status),
|
|
20
50
|
};
|
|
21
51
|
}
|
|
22
52
|
export function extractTransactionPayloadsFromBatchFiles(files) {
|