@zeniai/client-epic-state 4.19.84-betaVR15 → 4.19.84-betaVR2

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.
Files changed (32) hide show
  1. package/lib/epic.js +1 -1
  2. package/lib/esm/epic.js +2 -2
  3. package/lib/esm/index.js +3 -7
  4. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +5 -10
  5. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +1 -1
  6. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +1 -1
  7. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +4 -14
  8. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +3 -43
  9. package/lib/esm/view/expenseAutomationView/payload/missingReceiptsPayload.js +9 -38
  10. package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +22 -54
  11. package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +35 -57
  12. package/lib/esm/view/expenseAutomationView/types/missingReceiptsViewState.js +0 -39
  13. package/lib/index.d.ts +3 -4
  14. package/lib/index.js +33 -48
  15. package/lib/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.d.ts +0 -3
  16. package/lib/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +3 -8
  17. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +1 -1
  18. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +1 -1
  19. package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +3 -13
  20. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +2 -14
  21. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +3 -44
  22. package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.d.ts +1 -12
  23. package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.js +9 -39
  24. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +5 -11
  25. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +22 -54
  26. package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +35 -57
  27. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +9 -27
  28. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.js +1 -49
  29. package/package.json +1 -1
  30. package/lib/esm/view/expenseAutomationView/bulkUploadTiming.js +0 -10
  31. package/lib/view/expenseAutomationView/bulkUploadTiming.d.ts +0 -10
  32. package/lib/view/expenseAutomationView/bulkUploadTiming.js +0 -13
@@ -1,12 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pollBulkUploadBatchStatusEpic = exports.bulkUploadAutomatchingTimeoutEpic = exports.pusherBatchStatusCompletionEpic = void 0;
3
+ exports.pollBulkUploadBatchStatusEpic = exports.pusherBatchStatusCompletionEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
- const snackbarReducer_1 = require("../../../../entity/snackbar/snackbarReducer");
7
6
  const transactionReducer_1 = require("../../../../entity/transaction/transactionReducer");
8
7
  const responsePayload_1 = require("../../../../responsePayload");
9
- const bulkUploadTiming_1 = require("../../bulkUploadTiming");
10
8
  const missingReceiptsPayload_1 = require("../../payload/missingReceiptsPayload");
11
9
  const missingReceiptsViewReducer_1 = require("../../reducers/missingReceiptsViewReducer");
12
10
  /** First poll after upload; then interval while batch not resolved via Pusher or API. */
@@ -24,38 +22,9 @@ const pusherBatchStatusCompletionEpic = (actions$) => actions$.pipe((0, operator
24
22
  (0, missingReceiptsViewReducer_1.requestMissingReceiptsTabNavigation)({ tab: 'unmatched' }),
25
23
  ])));
26
24
  exports.pusherBatchStatusCompletionEpic = pusherBatchStatusCompletionEpic;
27
- /**
28
- * If Pusher and batch-details are delayed beyond {@link BULK_UPLOAD_AUTOMATCHING_TIMEOUT_MS},
29
- * force `phase` to `completed` (dismiss automatching banner) and refresh the batch list.
30
- * Cancels when the batch completes normally, bulk state is cleared, or another upload supersedes.
31
- */
32
- const bulkUploadAutomatchingTimeoutEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess.match), (0, operators_1.mergeMap)((action) => {
33
- const { batchId } = action.payload;
34
- return (0, rxjs_1.timer)(bulkUploadTiming_1.BULK_UPLOAD_AUTOMATCHING_TIMEOUT_MS).pipe((0, operators_1.mergeMap)(() => {
35
- const bulk = state$.value.expenseAutomationMissingReceiptsViewState.bulkUpload;
36
- if (bulk.phase !== 'matching' ||
37
- bulk.currentBatchId !== batchId) {
38
- return rxjs_1.EMPTY;
39
- }
40
- // eslint-disable-next-line no-console
41
- console.warn('[bulk-upload] Automatching wait exceeded timeout; releasing UI', { batchId });
42
- return (0, rxjs_1.from)([
43
- (0, missingReceiptsViewReducer_1.bulkUploadAutomatchingTimedOut)(batchId),
44
- (0, missingReceiptsViewReducer_1.fetchBulkUploadBatches)({ cacheOverride: true }),
45
- ]);
46
- }), (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)((a) => a.payload.batchId === batchId &&
47
- a.payload.status === 'completed')), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchBulkUploadBatchDetailsSuccess.match), (0, operators_1.filter)((a) => a.payload.batchId === batchId)))));
48
- }));
49
- exports.bulkUploadAutomatchingTimeoutEpic = bulkUploadAutomatchingTimeoutEpic;
50
- /**
51
- * Fallback polling when Pusher is slow or unavailable. Network errors on a poll tick show one
52
- * error snackbar per upload session (first failure only) so the user is not spammed every
53
- * interval; Pusher or a later successful poll still completes the flow.
54
- */
55
25
  const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess.match), (0, operators_1.mergeMap)((action) => {
56
26
  const { batchId } = action.payload;
57
- let pollErrorNotified = false;
58
- 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
27
+ 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)((a) => a.payload.batchId === batchId)), actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.fetchBulkUploadBatchDetailsSuccess.match), (0, operators_1.filter)((a) => a.payload.batchId === batchId)))), (0, operators_1.switchMap)(() => zeniAPI
59
28
  .getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/${batchId}`)
60
29
  .pipe((0, operators_1.mergeMap)((response) => {
61
30
  /** Same batch-details URL; polls until `status` is completed (Pusher may win first). */
@@ -73,16 +42,6 @@ const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.p
73
42
  }
74
43
  }
75
44
  return rxjs_1.EMPTY;
76
- }), (0, operators_1.catchError)(() => {
77
- if (!pollErrorNotified) {
78
- pollErrorNotified = true;
79
- return (0, rxjs_1.of)((0, snackbarReducer_1.openSnackbar)({
80
- messageSection: 'receipts_upload',
81
- messageText: 'failed',
82
- type: 'error',
83
- }));
84
- }
85
- return rxjs_1.EMPTY;
86
- }))));
45
+ }), (0, operators_1.catchError)(() => (0, rxjs_1.of)()))));
87
46
  }));
88
47
  exports.pollBulkUploadBatchStatusEpic = pollBulkUploadBatchStatusEpic;
@@ -3,7 +3,7 @@ import { TransactionPayload } from '../../../entity/transaction/payloadTypes/tra
3
3
  import { SupportedTransactionPayload } from '../../../entity/transaction/transactionState';
4
4
  import { ZeniAPIResponse } from '../../../responsePayload';
5
5
  import type { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
6
- import { type BatchDetails, type BatchFile, type BatchFileStatus, type BatchListItem, type BatchStatus, type BatchSummary, type ManualSearchResult } from '../types/missingReceiptsViewState';
6
+ import type { BatchDetails, BatchFile, BatchListItem, BatchStatus, BatchSummary, ManualSearchResult } from '../types/missingReceiptsViewState';
7
7
  export interface MissingReceiptsQueryPayload {
8
8
  end_date: string;
9
9
  is_attachment_missing_only: boolean;
@@ -54,11 +54,6 @@ export interface MatchedTransactionPayload {
54
54
  export interface MatchCandidatePayload extends MatchedTransactionPayload {
55
55
  match_score: number;
56
56
  }
57
- /**
58
- * Wire payload for a batch file row. `status` may use legacy aliases (`matched`, `un_matched`,
59
- * `possible_match`, `possible_matches`, etc.) until the backend is fully migrated; canonical
60
- * values are applied in {@link parseBatchFileStatus} via {@link toBatchFile}.
61
- */
62
57
  export interface BatchFilePayload {
63
58
  attachment_id: string;
64
59
  file_id: string;
@@ -83,12 +78,6 @@ export interface BatchDetailsResponsePayload {
83
78
  };
84
79
  }
85
80
  export type BatchDetailsResponse = ZeniAPIResponse<BatchDetailsResponsePayload>;
86
- /**
87
- * Maps batch-details API `files[].status` strings to canonical {@link BatchFileStatus}.
88
- * Legacy aliases are supported during rollout; unknown strings map to `failed` so Redux never
89
- * holds untyped status values.
90
- */
91
- export declare function parseBatchFileStatus(raw: string): BatchFileStatus;
92
81
  export declare function toBatchFile(payload: BatchFilePayload, filesEndPoint?: string): BatchFile;
93
82
  export declare function extractTransactionPayloadsFromBatchFiles(files: BatchFilePayload[]): SupportedTransactionPayload[];
94
83
  export declare function toBatchSummary(payload: BatchDetailsResponsePayload['summary']): BatchSummary;
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseBatchFileStatus = parseBatchFileStatus;
4
3
  exports.toBatchFile = toBatchFile;
5
4
  exports.extractTransactionPayloadsFromBatchFiles = extractTransactionPayloadsFromBatchFiles;
6
5
  exports.toBatchSummary = toBatchSummary;
@@ -14,40 +13,13 @@ exports.toBatchListItem = toBatchListItem;
14
13
  exports.supportedTransactionPayloadToManualSearchResult = supportedTransactionPayloadToManualSearchResult;
15
14
  const urlPayload_1 = require("../../../commonPayloadTypes/urlPayload");
16
15
  const transactionPayload_1 = require("../../../entity/transaction/payloadTypes/transactionPayload");
17
- const missingReceiptsViewState_1 = require("../types/missingReceiptsViewState");
18
16
  // -- Converter functions --
19
- /**
20
- * Maps batch-details API `files[].status` strings to canonical {@link BatchFileStatus}.
21
- * Legacy aliases are supported during rollout; unknown strings map to `failed` so Redux never
22
- * holds untyped status values.
23
- */
24
- function parseBatchFileStatus(raw) {
25
- const normalizedStatus = raw.trim().toLowerCase().replace(/-/g, '_');
26
- switch (normalizedStatus) {
27
- case 'exact_match':
28
- case 'matched':
29
- return 'exact_match';
30
- case 'possible_matches':
31
- case 'possible_match':
32
- case 'possiblematch':
33
- case 'un_matched':
34
- case 'unmatched':
35
- return 'possible_matches';
36
- case 'no_match':
37
- case 'nomatch':
38
- return 'no_match';
39
- case 'failed':
40
- return 'failed';
41
- default:
42
- return 'failed';
43
- }
44
- }
45
17
  function toBatchFile(payload, filesEndPoint) {
46
18
  return {
47
19
  attachmentId: payload.attachment_id,
48
- candidates: payload.candidates?.map((candidate) => ({
49
- transactionId: candidate.transaction_id,
50
- matchScore: candidate.match_score,
20
+ candidates: payload.candidates?.map((c) => ({
21
+ transactionId: c.transaction_id,
22
+ matchScore: c.match_score,
51
23
  })),
52
24
  fileDownloadUrl: payload.file_id != null && filesEndPoint != null
53
25
  ? `${filesEndPoint}/1.0/files/${payload.file_id}?query=${encodeURIComponent(JSON.stringify({ download_file: true }))}`
@@ -55,11 +27,9 @@ function toBatchFile(payload, filesEndPoint) {
55
27
  fileId: payload.file_id,
56
28
  filePreviewUrl: payload.file_preview_url,
57
29
  filename: payload.filename,
58
- matchSource: payload.match_source != null
59
- ? (0, missingReceiptsViewState_1.toMatchSource)(payload.match_source)
60
- : undefined,
30
+ matchSource: payload.match_source,
61
31
  matchedTransactionId: payload.matched_transaction?.transaction_id,
62
- status: (0, missingReceiptsViewState_1.toBatchFileStatus)(payload.status),
32
+ status: payload.status,
63
33
  };
64
34
  }
65
35
  function extractTransactionPayloadsFromBatchFiles(files) {
@@ -109,8 +79,8 @@ function toBatchDetails(payload, filesEndPoint) {
109
79
  return {
110
80
  batchId: payload.batch_id,
111
81
  createdAt: payload.created_at,
112
- files: payload.files.map((file) => toBatchFile(file, filesEndPoint)),
113
- status: (0, missingReceiptsViewState_1.toBatchStatusValue)(payload.status),
82
+ files: payload.files.map((f) => toBatchFile(f, filesEndPoint)),
83
+ status: payload.status,
114
84
  summary: toBatchSummary(payload.summary),
115
85
  };
116
86
  }
@@ -124,7 +94,7 @@ function isBatchListStatusCompleted(status) {
124
94
  * statuses for UI; only `completed` rows should trigger batch-details requests.
125
95
  */
126
96
  function filterBatchListItemsForBatchDetailsFetch(batches) {
127
- return batches.filter((batch) => isBatchListStatusCompleted(batch.status));
97
+ return batches.filter((b) => isBatchListStatusCompleted(b.status));
128
98
  }
129
99
  /**
130
100
  * Batch details API response `status` field — only completed payloads should be stored from
@@ -135,7 +105,7 @@ function isBatchDetailsApiStatusCompleted(status) {
135
105
  }
136
106
  function findBatchListItemForBatchId(batchListByPeriod, batchId) {
137
107
  for (const list of Object.values(batchListByPeriod)) {
138
- const found = list.find((batch) => batch.batchId === batchId);
108
+ const found = list.find((b) => b.batchId === batchId);
139
109
  if (found != null) {
140
110
  return found;
141
111
  }
@@ -5,13 +5,11 @@ import { MonthYearPeriod, TimePeriod } from '../../../commonStateTypes/timePerio
5
5
  import { TransactionPayload } from '../../../entity/transaction/payloadTypes/transactionPayload';
6
6
  import { SupportedTransactionPayload } from '../../../entity/transaction/transactionState';
7
7
  import { ZeniAPIStatus } from '../../../responsePayload';
8
- import { type BatchDetails, type BatchListItem, type BatchStatus, type BulkUploadResultsTab, type BulkUploadSortKey, type BulkUploadState, type CompletedSubTab, type ManualSearchResult, type MissingReceiptsViewState, type MissingReceiptsViewUIState } from '../types/missingReceiptsViewState';
8
+ import type { BatchDetails, BatchListItem, BatchStatus, BulkUploadResultsTab, BulkUploadSortKey, BulkUploadState, CompletedSubTab, ManualSearchResult, MissingReceiptsViewState, MissingReceiptsViewUIState } from '../types/missingReceiptsViewState';
9
9
  import type { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
10
10
  export declare const getCompletedTransactionsCacheKey: (periodId: MonthYearPeriodId, sortKey: BulkUploadSortKey, sortOrder: SortOrder, subTab: CompletedSubTab) => string;
11
11
  export declare const initialBulkUploadState: BulkUploadState;
12
12
  export declare const initialState: MissingReceiptsViewState;
13
- /** Epic trigger only; batch-details fetch is handled in epics. */
14
- export declare const fetchBulkUploadBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails">;
15
13
  export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[period: TimePeriod, minimumTransactionAmount: Amount, cacheOverride?: any, refreshViewInBackground?: any], {
16
14
  period: TimePeriod;
17
15
  minimumTransactionAmount: Amount;
@@ -38,15 +36,11 @@ export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCrea
38
36
  batchId: ID;
39
37
  }, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsSuccess">, bulkUploadReceiptsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
40
38
  error: ZeniAPIStatus;
41
- }, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure">, bulkUploadAutomatchingTimedOut: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[batchId: string], {
42
- batchId: string;
43
- }, "expenseAutomationMissingReceiptsView/bulkUploadAutomatchingTimedOut", never, never>, pusherBatchStatusUpdate: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchStatus, "expenseAutomationMissingReceiptsView/pusherBatchStatusUpdate">, requestMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
39
+ }, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure">, pusherBatchStatusUpdate: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchStatus, "expenseAutomationMissingReceiptsView/pusherBatchStatusUpdate">, requestMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
44
40
  tab: BulkUploadResultsTab;
45
- }, "expenseAutomationMissingReceiptsView/requestMissingReceiptsTabNavigation">, clearMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearMissingReceiptsTabNavigation">, fetchBulkUploadBatchDetailsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsSuccess">, fetchBulkUploadBatchDetailsFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
46
- error: ZeniAPIStatus;
47
- }], {
41
+ }, "expenseAutomationMissingReceiptsView/requestMissingReceiptsTabNavigation">, clearMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearMissingReceiptsTabNavigation">, fetchBulkUploadBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails">, fetchBulkUploadBatchDetailsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsSuccess">, fetchBulkUploadBatchDetailsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
48
42
  error: ZeniAPIStatus;
49
- }, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsFailure", never, never>, storeBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/storeBatchDetails">, batchDetailFetchFailed: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
43
+ }, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsFailure">, storeBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/storeBatchDetails">, batchDetailFetchFailed: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
50
44
  batchId: ID;
51
45
  }, "expenseAutomationMissingReceiptsView/batchDetailFetchFailed">, setInitialBatchDetailsLoading: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/setInitialBatchDetailsLoading">, fetchMoreBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchMoreBatchDetails">, fetchMoreBatchDetailsComplete: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchMoreBatchDetailsComplete">, fetchMoreBatchDetailsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
52
46
  error: ZeniAPIStatus;
@@ -74,7 +68,7 @@ export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCrea
74
68
  transactionId: ID;
75
69
  }, "expenseAutomationMissingReceiptsView/confirmBulkUploadMatchSuccess">, confirmBulkUploadMatchFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
76
70
  error: ZeniAPIStatus;
77
- }, "expenseAutomationMissingReceiptsView/confirmBulkUploadMatchFailure">, setBulkUploadResultsTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<"completed" | "unmatched", "expenseAutomationMissingReceiptsView/setBulkUploadResultsTab">, setBulkUploadCompletedSubTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<"all" | "manual" | "ai_accountant", "expenseAutomationMissingReceiptsView/setBulkUploadCompletedSubTab">, setBulkUploadSortConfig: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
71
+ }, "expenseAutomationMissingReceiptsView/confirmBulkUploadMatchFailure">, setBulkUploadResultsTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<BulkUploadResultsTab, "expenseAutomationMissingReceiptsView/setBulkUploadResultsTab">, setBulkUploadCompletedSubTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<CompletedSubTab, "expenseAutomationMissingReceiptsView/setBulkUploadCompletedSubTab">, setBulkUploadSortConfig: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
78
72
  sortKey: BulkUploadSortKey;
79
73
  sortOrder: SortOrder;
80
74
  }, "expenseAutomationMissingReceiptsView/setBulkUploadSortConfig">, clearBulkUpload: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearBulkUpload">, searchTransactionsForManualMatch: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[query: string, pageToken?: string | null | undefined], {
@@ -1,10 +1,9 @@
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.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;
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.fetchBulkUploadBatchDetails = exports.clearMissingReceiptsTabNavigation = exports.requestMissingReceiptsTabNavigation = exports.pusherBatchStatusUpdate = 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.initialState = exports.initialBulkUploadState = exports.getCompletedTransactionsCacheKey = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
7
- const missingReceiptsViewState_1 = require("../types/missingReceiptsViewState");
8
7
  const getCompletedTransactionsCacheKey = (periodId, sortKey, sortOrder, subTab) => `completed-${subTab}-${sortKey}-${sortOrder === 'ascending' ? 'asc' : 'desc'}-${periodId}`;
9
8
  exports.getCompletedTransactionsCacheKey = getCompletedTransactionsCacheKey;
10
9
  exports.initialBulkUploadState = {
@@ -56,8 +55,6 @@ exports.initialState = {
56
55
  return this.fetchState == 'Completed';
57
56
  },
58
57
  };
59
- /** Epic trigger only; batch-details fetch is handled in epics. */
60
- exports.fetchBulkUploadBatchDetails = (0, toolkit_1.createAction)('expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails');
61
58
  const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
62
59
  name: 'expenseAutomationMissingReceiptsView',
63
60
  initialState: exports.initialState,
@@ -161,7 +158,8 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
161
158
  },
162
159
  // -- Bulk Upload Actions --
163
160
  bulkUploadReceipts: {
164
- reducer(draft) {
161
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
162
+ reducer(draft, _action) {
165
163
  draft.bulkUpload.phase = 'uploading';
166
164
  draft.bulkUpload.uploadProgress = 0;
167
165
  draft.bulkUpload.uploadStatus = {
@@ -178,7 +176,6 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
178
176
  },
179
177
  bulkUploadReceiptsSuccess(draft, action) {
180
178
  draft.bulkUpload.currentBatchId = action.payload.batchId;
181
- draft.bulkUpload.uploadProgress = 100;
182
179
  draft.bulkUpload.uploadStatus = {
183
180
  fetchState: 'Completed',
184
181
  error: undefined,
@@ -192,18 +189,6 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
192
189
  };
193
190
  draft.bulkUpload.phase = 'idle';
194
191
  },
195
- bulkUploadAutomatchingTimedOut: {
196
- reducer(draft, action) {
197
- if (draft.bulkUpload.phase !== 'matching' ||
198
- draft.bulkUpload.currentBatchId !== action.payload.batchId) {
199
- return;
200
- }
201
- draft.bulkUpload.phase = 'completed';
202
- },
203
- prepare(batchId) {
204
- return { payload: { batchId } };
205
- },
206
- },
207
192
  pusherBatchStatusUpdate(draft, action) {
208
193
  const batchStatus = action.payload;
209
194
  draft.bulkUpload.batchStatusById[batchStatus.batchId] = batchStatus;
@@ -224,18 +209,18 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
224
209
  clearMissingReceiptsTabNavigation(draft) {
225
210
  draft.pendingMissingReceiptsTabNavigation = null;
226
211
  },
212
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
213
+ fetchBulkUploadBatchDetails(_draft) {
214
+ // trigger epic, no state change needed
215
+ },
227
216
  fetchBulkUploadBatchDetailsSuccess(draft, action) {
228
217
  const details = action.payload;
229
218
  draft.bulkUpload.batchDetailsById[details.batchId] = details;
230
219
  draft.bulkUpload.phase = 'completed';
231
220
  },
232
- fetchBulkUploadBatchDetailsFailure: {
233
- reducer(draft) {
234
- draft.bulkUpload.phase = 'completed';
235
- },
236
- prepare(payload) {
237
- return { payload };
238
- },
221
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
222
+ fetchBulkUploadBatchDetailsFailure(draft, _action) {
223
+ draft.bulkUpload.phase = 'completed';
239
224
  },
240
225
  storeBatchDetails(draft, action) {
241
226
  const details = action.payload;
@@ -266,8 +251,8 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
266
251
  error: undefined,
267
252
  };
268
253
  },
269
- fetchMoreBatchDetails(draft) {
270
- draft.bulkUpload.batchDetailsPaginationState = {
254
+ fetchMoreBatchDetails(_draft) {
255
+ _draft.bulkUpload.batchDetailsPaginationState = {
271
256
  fetchState: 'In-Progress',
272
257
  error: undefined,
273
258
  };
@@ -305,11 +290,11 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
305
290
  };
306
291
  },
307
292
  prepare(input) {
308
- const fetchOptions = input ?? {};
293
+ const o = input ?? {};
309
294
  return {
310
295
  payload: {
311
- cacheOverride: fetchOptions.cacheOverride === true,
312
- invalidateBatchDetailsCache: fetchOptions.invalidateBatchDetailsCache === true,
296
+ cacheOverride: o.cacheOverride === true,
297
+ invalidateBatchDetailsCache: o.invalidateBatchDetailsCache === true,
313
298
  },
314
299
  };
315
300
  },
@@ -343,7 +328,8 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
343
328
  };
344
329
  },
345
330
  confirmBulkUploadMatch: {
346
- reducer(draft) {
331
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
332
+ reducer(draft, _action) {
347
333
  draft.bulkUpload.confirmMatchStatus = {
348
334
  fetchState: 'In-Progress',
349
335
  error: undefined,
@@ -361,17 +347,17 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
361
347
  };
362
348
  const details = draft.bulkUpload.batchDetailsById[batchId];
363
349
  if (details != null) {
364
- const file = details.files.find((batchFile) => batchFile.attachmentId === attachmentId);
350
+ const file = details.files.find((f) => f.attachmentId === attachmentId);
365
351
  if (file != null) {
366
352
  const originalStatus = file.status;
367
- file.status = 'exact_match';
353
+ file.status = 'matched';
368
354
  file.matchedTransactionId = transactionId;
369
355
  file.candidates = undefined;
370
356
  details.summary.matched += 1;
371
357
  if (originalStatus === 'no_match') {
372
358
  details.summary.noMatch = Math.max(0, details.summary.noMatch - 1);
373
359
  }
374
- else if (originalStatus === 'possible_matches') {
360
+ else {
375
361
  details.summary.possibleMatches = Math.max(0, details.summary.possibleMatches - 1);
376
362
  }
377
363
  }
@@ -403,24 +389,6 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
403
389
  reducer(draft, action) {
404
390
  const { query, pageToken } = action.payload;
405
391
  const isLoadMore = pageToken != null;
406
- const trimmed = query.trim();
407
- /**
408
- * Cleared or too-short query: no API (see epic). Reset fully (no In-Progress).
409
- * Only bump `manualSearchUiResetKey` when clearing a real search — not when the UI
410
- * dispatches `""` on every keystroke while length is below MIN (web-components always sends
411
- * `onSearch("")` in that case), or ReceiptCard remounts and the input loses focus.
412
- */
413
- if (!isLoadMore &&
414
- trimmed.length < missingReceiptsViewState_1.MIN_MANUAL_TRANSACTION_SEARCH_LENGTH) {
415
- const hadActiveSearch = draft.bulkUpload.manualSearch.searchQuery.trim().length >=
416
- missingReceiptsViewState_1.MIN_MANUAL_TRANSACTION_SEARCH_LENGTH ||
417
- draft.bulkUpload.manualSearch.results.length > 0;
418
- draft.bulkUpload.manualSearch = exports.initialBulkUploadState.manualSearch;
419
- if (hadActiveSearch) {
420
- draft.bulkUpload.manualSearchUiResetKey += 1;
421
- }
422
- return;
423
- }
424
392
  draft.bulkUpload.manualSearch.searchQuery = query;
425
393
  if (isLoadMore) {
426
394
  draft.bulkUpload.manualSearch.isLoadingMore = true;
@@ -444,7 +412,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
444
412
  const { append, nextPageToken, results, totalCount } = action.payload;
445
413
  if (append) {
446
414
  const merged = [...draft.bulkUpload.manualSearch.results, ...results];
447
- const byId = new Map(merged.map((result) => [result.transactionId, result]));
415
+ const byId = new Map(merged.map((r) => [r.transactionId, r]));
448
416
  draft.bulkUpload.manualSearch.results = Array.from(byId.values());
449
417
  }
450
418
  else {
@@ -549,7 +517,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
549
517
  });
550
518
  _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,
551
519
  // Bulk Upload
552
- 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,
520
+ exports.bulkUploadReceipts = _a.bulkUploadReceipts, exports.updateBulkUploadProgress = _a.updateBulkUploadProgress, exports.bulkUploadReceiptsSuccess = _a.bulkUploadReceiptsSuccess, exports.bulkUploadReceiptsFailure = _a.bulkUploadReceiptsFailure, exports.pusherBatchStatusUpdate = _a.pusherBatchStatusUpdate, exports.requestMissingReceiptsTabNavigation = _a.requestMissingReceiptsTabNavigation, exports.clearMissingReceiptsTabNavigation = _a.clearMissingReceiptsTabNavigation, exports.fetchBulkUploadBatchDetails = _a.fetchBulkUploadBatchDetails, 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,
553
521
  // Completed Transactions
554
522
  exports.fetchCompletedTransactions = _a.fetchCompletedTransactions, exports.fetchCompletedTransactionsSuccess = _a.fetchCompletedTransactionsSuccess, exports.fetchCompletedTransactionsFailure = _a.fetchCompletedTransactionsFailure;
555
523
  exports.default = expenseAutomationMissingReceiptsView.reducer;
@@ -11,7 +11,6 @@ const transactionSelector_1 = require("../../../entity/transaction/transactionSe
11
11
  const expenseAutomationViewSelectorTypes_1 = require("../selectorTypes/expenseAutomationViewSelectorTypes");
12
12
  const missingReceiptsPayload_1 = require("../payload/missingReceiptsPayload");
13
13
  const missingReceiptsViewReducer_1 = require("../reducers/missingReceiptsViewReducer");
14
- const missingReceiptsViewState_1 = require("../types/missingReceiptsViewState");
15
14
  function getExpenseAutomationMissingReceiptsView(state) {
16
15
  const { expenseAutomationMissingReceiptsViewState, expenseAutomationViewState, transactionState, monthEndCloseChecksState, } = state;
17
16
  const currentTenant = (0, tenantSelector_1.getCurrentTenant)(state);
@@ -65,71 +64,50 @@ function getExpenseAutomationMissingReceiptsView(state) {
65
64
  : [];
66
65
  /**
67
66
  * Primary "Unmatched" batch = first completed batch in platform list order, preferring the
68
- * first batch that still has possible_matches/no_match work when any completed batch has such work.
67
+ * first batch that still has un_matched/no_match work when any completed batch has such work.
69
68
  * Batches without details yet: wait if the list row still reports unmatched work; otherwise skip
70
69
  * so we do not block the whole tab while other rows are not fetched yet.
71
70
  */
72
71
  const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(batchList, bulkUpload.batchDetailsById, bulkUpload.failedBatchDetailIds);
73
- /**
74
- * During upload/matching, prefer `currentBatchId` only when its batch details are loaded,
75
- * completed, and still have unmatched-tab work. Otherwise keep `primaryBatchIdFromDetailsOrder`.
76
- *
77
- * If we pinned to `currentBatchId` as soon as it was absent from the batch list (in-flight
78
- * upload), details are often not loaded yet — `unmatchedFiles` would empty while older batches
79
- * moved to "past", so the primary "Unmatched Receipts" section vanished during auto-matching.
80
- */
81
- const unmatchedSectionBatchId = (() => {
82
- const phase = bulkUpload.phase;
83
- if (phase !== 'matching' && phase !== 'uploading') {
84
- return primaryBatchIdFromDetailsOrder;
85
- }
86
- const currentId = bulkUpload.currentBatchId;
87
- if (currentId == null) {
88
- return primaryBatchIdFromDetailsOrder;
89
- }
90
- const currentDetails = bulkUpload.batchDetailsById[currentId];
91
- if (currentDetails != null &&
92
- currentDetails.status === 'completed' &&
93
- batchDetailsHasUnmatchedWork(currentDetails)) {
94
- return currentId;
95
- }
96
- return primaryBatchIdFromDetailsOrder;
97
- })();
98
- const completedBatchesInApiOrder = batchList.filter((batchListItem) => (0, missingReceiptsPayload_1.isBatchListStatusCompleted)(batchListItem.status));
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));
99
77
  const currentBatchDetails = unmatchedSectionBatchId != null
100
78
  ? bulkUpload.batchDetailsById[unmatchedSectionBatchId]
101
79
  : undefined;
102
80
  const resolvedFiles = currentBatchDetails?.files.map((file) => resolveBatchFile(file, currentBatchDetails.batchId, transactionState));
103
81
  const failedIds = new Set(bulkUpload.failedBatchDetailIds);
104
- const hasMoreBatchDetails = completedBatchesInApiOrder.some((batchListItem) => bulkUpload.batchDetailsById[batchListItem.batchId] == null &&
105
- !failedIds.has(batchListItem.batchId));
82
+ const hasMoreBatchDetails = completedBatchesInApiOrder.some((b) => bulkUpload.batchDetailsById[b.batchId] == null &&
83
+ !failedIds.has(b.batchId));
106
84
  const getSortValue = (file) => {
107
- const matchedTransaction = file.matchedTransaction;
108
- if (matchedTransaction == null) {
85
+ const t = file.matchedTransaction;
86
+ if (t == null) {
109
87
  return null;
110
88
  }
111
89
  switch (bulkUpload.sortKey) {
112
90
  case 'vendor':
113
- return (matchedTransaction.vendorName ?? matchedTransaction.description)?.toLowerCase() ?? null;
91
+ return (t.vendorName ?? t.description)?.toLowerCase() ?? null;
114
92
  case 'category': {
115
- const line = matchedTransaction.lines?.[0];
93
+ const line = t.lines?.[0];
116
94
  return line?.account?.accountName?.toLowerCase() ?? null;
117
95
  }
118
96
  case 'class': {
119
- const line = matchedTransaction.lines?.[0];
97
+ const line = t.lines?.[0];
120
98
  return line?.class?.className?.toLowerCase() ?? null;
121
99
  }
122
100
  case 'date':
123
- return matchedTransaction.date.valueOf();
101
+ return t.date.valueOf();
124
102
  case 'amount':
125
- return matchedTransaction.amount.amount;
103
+ return t.amount.amount;
126
104
  default:
127
105
  return null;
128
106
  }
129
107
  };
130
108
  const bulkUploadSortDirection = bulkUpload.sortOrder === 'ascending' ? 'asc' : 'desc';
131
- const matchedFiles = (0, orderBy_1.default)(resolvedFiles?.filter((resolvedFile) => resolvedFile.status === 'exact_match') ?? [], getSortValue, bulkUploadSortDirection);
132
- const unmatchedFiles = (0, orderBy_1.default)(resolvedFiles?.filter((resolvedFile) => (0, missingReceiptsViewState_1.isUnmatchedTabFileStatus)(resolvedFile.status)) ?? [], getSortValue, bulkUploadSortDirection);
109
+ const matchedFiles = (0, orderBy_1.default)(resolvedFiles?.filter((f) => f.status === 'matched') ?? [], getSortValue, bulkUploadSortDirection);
110
+ const unmatchedFiles = (0, orderBy_1.default)(resolvedFiles?.filter((f) => f.status === 'un_matched' || f.status === 'no_match') ?? [], getSortValue, bulkUploadSortDirection);
133
111
  const progress = currentBatchStatus != null
134
112
  ? {
135
113
  ...currentBatchStatus.progress,
@@ -146,16 +124,16 @@ function getExpenseAutomationMissingReceiptsView(state) {
146
124
  * that has details loaded (otherwise past is empty and receipts vanish from the UI).
147
125
  */
148
126
  const pastBatches = unmatchedSectionBatchId != null
149
- ? batchList.filter((batchListItem) => batchListItem.batchId !== unmatchedSectionBatchId)
127
+ ? batchList.filter((b) => b.batchId !== unmatchedSectionBatchId)
150
128
  : batchList;
151
- const pastUnmatchedFiles = pastBatches.flatMap((pastBatch) => {
152
- const details = bulkUpload.batchDetailsById[pastBatch.batchId];
129
+ const pastUnmatchedFiles = pastBatches.flatMap((b) => {
130
+ const details = bulkUpload.batchDetailsById[b.batchId];
153
131
  if (details == null) {
154
132
  return [];
155
133
  }
156
134
  return details.files
157
- .filter((batchFile) => (0, missingReceiptsViewState_1.isUnmatchedTabFileStatus)(batchFile.status))
158
- .map((batchFile) => resolveBatchFile(batchFile, pastBatch.batchId, transactionState));
135
+ .filter((f) => f.status === 'un_matched' || f.status === 'no_match')
136
+ .map((f) => resolveBatchFile(f, b.batchId, transactionState));
159
137
  });
160
138
  const completedTransactionsCacheKey = monthYearPeriodId != null
161
139
  ? (0, missingReceiptsViewReducer_1.getCompletedTransactionsCacheKey)(monthYearPeriodId, bulkUpload.sortKey, bulkUpload.sortOrder, bulkUpload.completedSubTab)
@@ -174,11 +152,11 @@ function getExpenseAutomationMissingReceiptsView(state) {
174
152
  summary: currentBatchDetails.summary,
175
153
  }
176
154
  : undefined;
177
- const manualSearchResults = bulkUpload.manualSearch.results.map((result) => {
178
- const transaction = (0, transactionSelector_1.getSupportedTransactionById)(transactionState, result.transactionId);
155
+ const manualSearchResults = bulkUpload.manualSearch.results.map((r) => {
156
+ const t = (0, transactionSelector_1.getSupportedTransactionById)(transactionState, r.transactionId);
179
157
  return {
180
- ...result,
181
- vendorLogo: result.vendorLogo ?? transaction?.logo?.href,
158
+ ...r,
159
+ vendorLogo: r.vendorLogo ?? t?.logo?.href,
182
160
  };
183
161
  });
184
162
  return {
@@ -228,7 +206,7 @@ function getExpenseAutomationMissingReceiptsView(state) {
228
206
  };
229
207
  }
230
208
  function batchDetailsHasUnmatchedWork(details) {
231
- return details.files.some((file) => (0, missingReceiptsViewState_1.isUnmatchedTabFileStatus)(file.status));
209
+ return details.files.some((f) => f.status === 'un_matched' || f.status === 'no_match');
232
210
  }
233
211
  /** List row summary before batch details load — aligns with unmatched / possible-match work. */
234
212
  function batchListItemHasUnmatchedWork(batch) {
@@ -245,17 +223,17 @@ function batchListItemHasUnmatchedWork(batch) {
245
223
  */
246
224
  function getPrimaryBatchIdFromBatchListOrder(batchListInPlatformOrder, batchDetailsById, failedBatchDetailIds) {
247
225
  const failedIds = new Set(failedBatchDetailIds);
248
- const anyCompletedBatchHasUnmatchedWork = batchListInPlatformOrder.some((batch) => {
249
- if (failedIds.has(batch.batchId)) {
226
+ const anyCompletedBatchHasUnmatchedWork = batchListInPlatformOrder.some((b) => {
227
+ if (failedIds.has(b.batchId)) {
250
228
  return false;
251
229
  }
252
- const details = batchDetailsById[batch.batchId];
253
- if (details != null &&
254
- details.status === 'completed' &&
255
- batchDetailsHasUnmatchedWork(details)) {
230
+ const d = batchDetailsById[b.batchId];
231
+ if (d != null &&
232
+ d.status === 'completed' &&
233
+ batchDetailsHasUnmatchedWork(d)) {
256
234
  return true;
257
235
  }
258
- return details == null && batchListItemHasUnmatchedWork(batch);
236
+ return d == null && batchListItemHasUnmatchedWork(b);
259
237
  });
260
238
  for (const batch of batchListInPlatformOrder) {
261
239
  if (failedIds.has(batch.batchId)) {
@@ -292,7 +270,7 @@ function resolveBatchFile(file, batchId, transactionState) {
292
270
  ? { transaction, matchScore: ref.matchScore }
293
271
  : undefined;
294
272
  })
295
- .filter((candidate) => candidate != null);
273
+ .filter((c) => c != null);
296
274
  return {
297
275
  attachmentId: file.attachmentId,
298
276
  batchId,