@zeniai/client-epic-state 5.0.64-betaAR2 → 5.0.64-betaSS1

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 (45) hide show
  1. package/lib/entity/account/accountSelector.d.ts +1 -20
  2. package/lib/entity/account/accountSelector.js +1 -35
  3. package/lib/entity/account/accountState.d.ts +0 -5
  4. package/lib/entity/account/accountState.js +4 -11
  5. package/lib/entity/class/classSelector.d.ts +0 -5
  6. package/lib/entity/class/classSelector.js +0 -8
  7. package/lib/esm/entity/account/accountSelector.js +1 -33
  8. package/lib/esm/entity/account/accountState.js +1 -7
  9. package/lib/esm/entity/class/classSelector.js +0 -7
  10. package/lib/esm/index.js +7 -12
  11. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +2 -1
  12. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +6 -0
  13. package/lib/esm/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +11 -1
  14. package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +2 -1
  15. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +114 -11
  16. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +28 -59
  17. package/lib/esm/view/expenseAutomationView/types/completedSubTab.js +17 -0
  18. package/lib/esm/view/expenseAutomationView/types/missingReceiptsViewState.js +0 -2
  19. package/lib/esm/view/spendManagement/spendManagementFilterHelpers.js +0 -2
  20. package/lib/index.d.ts +8 -9
  21. package/lib/index.js +39 -44
  22. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +2 -1
  23. package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +6 -0
  24. package/lib/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.d.ts +2 -2
  25. package/lib/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +10 -0
  26. package/lib/view/expenseAutomationView/payload/transactionCategorizationPayload.d.ts +21 -0
  27. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +2 -1
  28. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +2 -1
  29. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +9 -7
  30. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +115 -12
  31. package/lib/view/expenseAutomationView/selectorTypes/missingReceiptsSelectorTypes.d.ts +2 -1
  32. package/lib/view/expenseAutomationView/selectorTypes/transactionsViewSelectorTypes.d.ts +14 -0
  33. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.d.ts +1 -4
  34. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +28 -61
  35. package/lib/view/expenseAutomationView/types/completedSubTab.d.ts +10 -0
  36. package/lib/view/expenseAutomationView/types/completedSubTab.js +21 -0
  37. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +1 -2
  38. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.js +1 -4
  39. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +35 -3
  40. package/lib/view/spendManagement/spendManagementFilterHelpers.js +0 -2
  41. package/package.json +1 -1
  42. package/lib/esm/view/expenseAutomationView/transactionFilterHelpers.js +0 -186
  43. package/lib/tsconfig.typecheck.tsbuildinfo +0 -1
  44. package/lib/view/expenseAutomationView/transactionFilterHelpers.d.ts +0 -65
  45. package/lib/view/expenseAutomationView/transactionFilterHelpers.js +0 -190
@@ -1,9 +1,9 @@
1
1
  import { AccountsViewParentID } from '../../commonStateTypes/accountView/nestedAccountID';
2
2
  import { ClassesViewParentID } from '../../commonStateTypes/classesView/nestedClassID';
3
+ import { ProjectsViewParentID } from '../../commonStateTypes/projectView/projectViewParentID';
3
4
  import { AdditionalBalancesOptions } from '../../commonStateTypes/coaBalance/additionalBalances/getAdditionalBalances';
4
5
  import { COABalancesFilter } from '../../commonStateTypes/coaBalance/coaBalancesFilter';
5
6
  import { ID } from '../../commonStateTypes/common';
6
- import { ProjectsViewParentID } from '../../commonStateTypes/projectView/projectViewParentID';
7
7
  import { EntityOrder } from '../../commonStateTypes/selectorTypes/selectorTypes';
8
8
  import { ReportIDPlusForecastID } from '../../commonStateTypes/viewAndReport/viewAndReport';
9
9
  import { Account, AccountBase, AccountState, AccountType } from './accountState';
@@ -123,22 +123,3 @@ export declare const getAccountsOrdered: (filter: COABalancesFilter, accountStat
123
123
  export declare const getAccountsByType: (accountState: AccountState, accountTypes: AccountType[]) => Partial<Record<AccountType, Account[]>>;
124
124
  export declare const getAccountIdsForTypes: (accountState: AccountState, accountTypes: AccountType[]) => ID[];
125
125
  export declare const getAccountIdsForLabels: (accountState: AccountState, labels: string[]) => ID[];
126
- /**
127
- * Returns all accounts currently in state (single pass over accountsByKey).
128
- * Use for dropdowns that need account names and types; map to
129
- * { accountId, accountName, accountType } as needed.
130
- */
131
- export declare const getAllAccounts: (accountState: AccountState) => Account[];
132
- export interface AccountFilterOption {
133
- accountId: ID;
134
- accountName: string;
135
- accountType: AccountType;
136
- }
137
- /**
138
- * Partitions accounts for transaction filter dropdowns: bank/credit_card → paymentAccountNames,
139
- * all other account types → categoryOptions. Use for payment_account_name and category filter options.
140
- */
141
- export declare const getTransactionFilterAccountOptions: (accountState: AccountState) => {
142
- categoryOptions: AccountFilterOption[];
143
- paymentAccountNames: AccountFilterOption[];
144
- };
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getTransactionFilterAccountOptions = exports.getAllAccounts = exports.getAccountIdsForLabels = exports.getAccountIdsForTypes = exports.getAccountsByType = exports.getAccountsOrdered = exports.getAccountBase = void 0;
6
+ exports.getAccountIdsForLabels = exports.getAccountIdsForTypes = exports.getAccountsByType = exports.getAccountsOrdered = exports.getAccountBase = void 0;
7
7
  exports.getAccount = getAccount;
8
8
  exports.getAccountWithBalance = getAccountWithBalance;
9
9
  const flatMap_1 = __importDefault(require("lodash/flatMap"));
@@ -192,37 +192,3 @@ const getAccountIdsForLabels = (accountState, labels) => {
192
192
  return allAccountIdsForLabels;
193
193
  };
194
194
  exports.getAccountIdsForLabels = getAccountIdsForLabels;
195
- /**
196
- * Returns all accounts currently in state (single pass over accountsByKey).
197
- * Use for dropdowns that need account names and types; map to
198
- * { accountId, accountName, accountType } as needed.
199
- */
200
- const getAllAccounts = (accountState) => Object.values(accountState.accountsByKey);
201
- exports.getAllAccounts = getAllAccounts;
202
- /**
203
- * Partitions accounts for transaction filter dropdowns: bank/credit_card → paymentAccountNames,
204
- * all other account types → categoryOptions. Use for payment_account_name and category filter options.
205
- */
206
- const getTransactionFilterAccountOptions = (accountState) => {
207
- const accounts = (0, exports.getAllAccounts)(accountState);
208
- const paymentAccountNames = [];
209
- const categoryOptions = [];
210
- for (const account of accounts) {
211
- if (account.accountType == null) {
212
- continue;
213
- }
214
- const option = {
215
- accountId: account.accountId,
216
- accountName: account.accountName,
217
- accountType: account.accountType,
218
- };
219
- if ((0, accountState_1.isPaymentAccountType)(account.accountType)) {
220
- paymentAccountNames.push(option);
221
- }
222
- else {
223
- categoryOptions.push(option);
224
- }
225
- }
226
- return { categoryOptions, paymentAccountNames };
227
- };
228
- exports.getTransactionFilterAccountOptions = getTransactionFilterAccountOptions;
@@ -8,14 +8,9 @@ import { RecommendationBase } from '../../commonStateTypes/recommendationBase';
8
8
  import { Status } from '../../commonStateTypes/status';
9
9
  import { ReportIDPlusForecastID } from '../../commonStateTypes/viewAndReport/viewAndReport';
10
10
  import { ZeniUrl } from '../../zeniUrl';
11
- export declare const ALL_ACCOUNT_TYPES: readonly ["bank", "credit_card", "expenses", "cogs", "income", "cash_in", "cash_out", "cash_position", "other_income", "other_expense", "accounts_receivable", "other_current_assets", "fixed_assets", "other_assets", "accounts_payable", "other_current_liabilities", "long_term_liabilities", "equity", "current_liabilities", "current_assets"];
12
11
  export declare const toAccountType: (v: string) => "cash_position" | "fixed_assets" | "bank" | "credit_card" | "expenses" | "cogs" | "income" | "cash_in" | "cash_out" | "other_income" | "other_expense" | "accounts_receivable" | "other_current_assets" | "other_assets" | "accounts_payable" | "other_current_liabilities" | "long_term_liabilities" | "equity" | "current_liabilities" | "current_assets";
13
12
  export type AccountType = ReturnType<typeof toAccountType>;
14
13
  export declare const toAccountTypeStrict: (v: string | null | undefined) => AccountType | undefined;
15
- /** Account types used for payment-account filters (e.g. transaction filter "payment account name"). */
16
- export declare const PAYMENT_ACCOUNT_TYPES: readonly ["bank", "credit_card"];
17
- export type PaymentAccountType = (typeof PAYMENT_ACCOUNT_TYPES)[number];
18
- export declare function isPaymentAccountType(accountType: AccountType | undefined): accountType is PaymentAccountType;
19
14
  export type UncategorizedAccountTypes = 'expense' | 'income';
20
15
  declare const toAccountLabel: (v: string) => "prepaid_expenses" | "fixed_assets" | "uncategorized_income" | "uncategorized_expense" | "bank_charges_and_fees" | "travel_transportation" | "accrued_expenses";
21
16
  export type AccountLabel = ReturnType<typeof toAccountLabel>;
@@ -1,12 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toReconciliationAccountSourceStrict = exports.toReconciliationAccountSource = exports.toAccountLabelStrict = exports.PAYMENT_ACCOUNT_TYPES = exports.toAccountTypeStrict = exports.toAccountType = exports.ALL_ACCOUNT_TYPES = void 0;
4
- exports.isPaymentAccountType = isPaymentAccountType;
3
+ exports.toReconciliationAccountSourceStrict = exports.toReconciliationAccountSource = exports.toAccountLabelStrict = exports.toAccountTypeStrict = exports.toAccountType = void 0;
5
4
  exports.getAccountKey = getAccountKey;
6
5
  const nestedAccountID_1 = require("../../commonStateTypes/accountView/nestedAccountID");
7
6
  const nestedClassID_1 = require("../../commonStateTypes/classesView/nestedClassID");
8
7
  const stringToUnion_1 = require("../../commonStateTypes/stringToUnion");
9
- exports.ALL_ACCOUNT_TYPES = [
8
+ const ALL_ACCOUNT_TYPES = [
10
9
  'bank',
11
10
  'credit_card',
12
11
  'expenses',
@@ -28,16 +27,10 @@ exports.ALL_ACCOUNT_TYPES = [
28
27
  'current_liabilities',
29
28
  'current_assets',
30
29
  ];
31
- const toAccountType = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.ALL_ACCOUNT_TYPES);
30
+ const toAccountType = (v) => (0, stringToUnion_1.stringToUnion)(v, ALL_ACCOUNT_TYPES);
32
31
  exports.toAccountType = toAccountType;
33
- const toAccountTypeStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v ?? '', exports.ALL_ACCOUNT_TYPES);
32
+ const toAccountTypeStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v ?? '', ALL_ACCOUNT_TYPES);
34
33
  exports.toAccountTypeStrict = toAccountTypeStrict;
35
- /** Account types used for payment-account filters (e.g. transaction filter "payment account name"). */
36
- exports.PAYMENT_ACCOUNT_TYPES = ['bank', 'credit_card'];
37
- function isPaymentAccountType(accountType) {
38
- return (accountType != null &&
39
- exports.PAYMENT_ACCOUNT_TYPES.includes(accountType));
40
- }
41
34
  const ALL_ACCOUNT_LABELS = [
42
35
  'uncategorized_income',
43
36
  'uncategorized_expense',
@@ -20,8 +20,3 @@ export declare function getClassReport(classState: ClassState, accountState: Acc
20
20
  reportId: ReportID;
21
21
  classesViewParentId?: ClassesViewParentID;
22
22
  }, filter: COABalancesFilter): ClassReport | undefined;
23
- /**
24
- * Returns all classes currently in state (single pass over classesByKey).
25
- * Use for dropdowns that need class names; map to { classId, className } as needed.
26
- */
27
- export declare function getAllClasses(classState: ClassState): Class[];
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getClassesByIds = getClassesByIds;
7
7
  exports.getClassById = getClassById;
8
8
  exports.getClassReport = getClassReport;
9
- exports.getAllClasses = getAllClasses;
10
9
  const get_1 = __importDefault(require("lodash/get"));
11
10
  const coaBalance_1 = require("../../commonStateTypes/coaBalance/coaBalance");
12
11
  const accountSelector_1 = require("../account/accountSelector");
@@ -59,10 +58,3 @@ function getClassReport(classState, accountState, id, filter) {
59
58
  accounts: accountReport,
60
59
  };
61
60
  }
62
- /**
63
- * Returns all classes currently in state (single pass over classesByKey).
64
- * Use for dropdowns that need class names; map to { classId, className } as needed.
65
- */
66
- function getAllClasses(classState) {
67
- return Object.values(classState.classesByKey);
68
- }
@@ -1,7 +1,7 @@
1
1
  import flatMap from 'lodash/flatMap';
2
2
  import { getCOABalances } from '../../commonStateTypes/coaBalance/coaBalance';
3
3
  import { sortComparator } from '../../commonStateTypes/coaBalance/sortBalancesByFreeRangeTotal';
4
- import { getAccountKey, isPaymentAccountType, } from './accountState';
4
+ import { getAccountKey, } from './accountState';
5
5
  function getCommonAccountFields(accountState, id) {
6
6
  const key = getAccountKey(id.reportId, id.accountId, id.classesViewParentId, id.accountsViewParentId, id.projectsViewParentId);
7
7
  const account = accountState.accountsByKey[key];
@@ -179,35 +179,3 @@ export const getAccountIdsForLabels = (accountState, labels) => {
179
179
  });
180
180
  return allAccountIdsForLabels;
181
181
  };
182
- /**
183
- * Returns all accounts currently in state (single pass over accountsByKey).
184
- * Use for dropdowns that need account names and types; map to
185
- * { accountId, accountName, accountType } as needed.
186
- */
187
- export const getAllAccounts = (accountState) => Object.values(accountState.accountsByKey);
188
- /**
189
- * Partitions accounts for transaction filter dropdowns: bank/credit_card → paymentAccountNames,
190
- * all other account types → categoryOptions. Use for payment_account_name and category filter options.
191
- */
192
- export const getTransactionFilterAccountOptions = (accountState) => {
193
- const accounts = getAllAccounts(accountState);
194
- const paymentAccountNames = [];
195
- const categoryOptions = [];
196
- for (const account of accounts) {
197
- if (account.accountType == null) {
198
- continue;
199
- }
200
- const option = {
201
- accountId: account.accountId,
202
- accountName: account.accountName,
203
- accountType: account.accountType,
204
- };
205
- if (isPaymentAccountType(account.accountType)) {
206
- paymentAccountNames.push(option);
207
- }
208
- else {
209
- categoryOptions.push(option);
210
- }
211
- }
212
- return { categoryOptions, paymentAccountNames };
213
- };
@@ -1,7 +1,7 @@
1
1
  import { getNestedAccountIDStr, } from '../../commonStateTypes/accountView/nestedAccountID';
2
2
  import { getNestedClassIDStr, } from '../../commonStateTypes/classesView/nestedClassID';
3
3
  import { stringToUnion, stringToUnionStrict, } from '../../commonStateTypes/stringToUnion';
4
- export const ALL_ACCOUNT_TYPES = [
4
+ const ALL_ACCOUNT_TYPES = [
5
5
  'bank',
6
6
  'credit_card',
7
7
  'expenses',
@@ -25,12 +25,6 @@ export const ALL_ACCOUNT_TYPES = [
25
25
  ];
26
26
  export const toAccountType = (v) => stringToUnion(v, ALL_ACCOUNT_TYPES);
27
27
  export const toAccountTypeStrict = (v) => stringToUnionStrict(v ?? '', ALL_ACCOUNT_TYPES);
28
- /** Account types used for payment-account filters (e.g. transaction filter "payment account name"). */
29
- export const PAYMENT_ACCOUNT_TYPES = ['bank', 'credit_card'];
30
- export function isPaymentAccountType(accountType) {
31
- return (accountType != null &&
32
- PAYMENT_ACCOUNT_TYPES.includes(accountType));
33
- }
34
28
  const ALL_ACCOUNT_LABELS = [
35
29
  'uncategorized_income',
36
30
  'uncategorized_expense',
@@ -50,10 +50,3 @@ export function getClassReport(classState, accountState, id, filter) {
50
50
  accounts: accountReport,
51
51
  };
52
52
  }
53
- /**
54
- * Returns all classes currently in state (single pass over classesByKey).
55
- * Use for dropdowns that need class names; map to { classId, className } as needed.
56
- */
57
- export function getAllClasses(classState) {
58
- return Object.values(classState.classesByKey);
59
- }
package/lib/esm/index.js CHANGED
@@ -23,7 +23,6 @@ import { mapTimePeriodtoTimeframeTick, toTimePeriod, toTimeframeTick, } from './
23
23
  import { isAgingReport, isCashFlowOrBalanceSheetReport, isDashboardClassesViewReport, isDashboardReport, isFluxAnalysisOpExReport, isOpExByVendorReport, isPAndLClassesViewReport, isPAndLProjectViewReport, isPAndLReport, } from './commonStateTypes/viewAndReport/reportIDHelper';
24
24
  import { toReportFormatStrict, toReportID, } from './commonStateTypes/viewAndReport/viewAndReport';
25
25
  import { PAYMENT_BUSINESS_DAYS, filterDays, getNextNthWorkingDay, getPreviousNthWorkingDay, getYearsList, holidaysFormatted, isHoliday, isHolidayToday, } from './commonStateTypes/workingDayHelper';
26
- import { getAllAccounts, getTransactionFilterAccountOptions, } from './entity/account/accountSelector';
27
26
  import { toAccountType, toReconciliationAccountSource, } from './entity/account/accountState';
28
27
  import { getAccountGroupKey, toAccountGroupType, } from './entity/accountGroup/accountGroupState';
29
28
  /**
@@ -168,12 +167,13 @@ import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFl
168
167
  import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, retryJeSchedule as retryExpenseAutomationJESchedule, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData, updateJESchedulesUIState as updateExpenseAutomationJESchedulesUIState, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
169
168
  import { acknowledgeBulkUploadConfirmMatchComplete, bulkUploadAutomatchingTimedOut, bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, clearBulkUpload, clearManualSearchResults, clearMissingReceiptsTabNavigation, confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, fetchMissingReceipts as fetchExpenseAutomationMissingReceipts, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, markMissingReceiptAsDone as markExpenseAutomationMissingReceiptAsDone, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, searchTransactionsForManualMatch, searchTransactionsForManualMatchFailure, searchTransactionsForManualMatchSuccess, setBulkUploadCompletedSubTab, setBulkUploadResultsTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, storeBatchDetails, updateBulkUploadProgress, updateMissingReceiptUploadState as updateExpenseAutomationMissingReceiptUploadState, updateMissingReceiptsUIState as updateExpenseAutomationMissingReceiptsUIState, uploadMissingReceiptSuccess as uploadExpenseAutomationMissingReceiptSuccess, } from './view/expenseAutomationView/reducers/missingReceiptsViewReducer';
170
169
  import { deleteAccountStatement, excludeAccountFromReconciliation, fetchReconciliation as fetchReconciliationView, includeAccountInReconciliation, saveReconciliationDetail as saveExpenseAutomationReconciliationDetail, saveReconciliationReview as saveExpenseAutomationReconciliationReview, setConnectionInProgressForAccount as setConnectionInProgressForAccountReconciliation, setStatementParseInProgress, updateAccountReconciliationLocalData as updateExpenseAutomationAccountReconciliationLocalData, updateSelectedAccountId as updateExpenseAutomationAccountReconciliationSelectedAccountId, updateSelectedTab as updateExpenseAutomationAccountReconciliationSelectedTab, updateReconListScrollPosition as updateExpenseAutomationReconListScrollPosition, updateReviewTabSortState as updateExpenseAutomationReconReviewTabListSortState, updateReviewTabLocalData as updateExpenseAutomationReconReviewTabLocalData, updateReconcileTabListScrollState as updateExpenseAutomationReconcileTabListScrollState, updateReconcileTabListSortState as updateExpenseAutomationReconcileTabListSortState, updateReconcileTabLocalData as updateExpenseAutomationReconcileTabLocalData, updateSelectedDrawerAccountId as updateExpenseAutomationSelectedDrawerAccountId, updateNodeCollapseState, updateStatementUploadChosen, uploadAccountStatement, } from './view/expenseAutomationView/reducers/reconciliationViewReducer';
171
- import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markTransactionAsNotMiscategorized, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, updateTransactionFilters, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
170
+ import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markTransactionAsNotMiscategorized, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
172
171
  import { getExpenseAutomationFluxAnalysisView } from './view/expenseAutomationView/selectors/fluxAnalysisViewSelector';
173
172
  import { getExpenseAutomationReconciliationView, isAccountReconReport, } from './view/expenseAutomationView/selectors/reconciliationViewSelector';
174
173
  import { getExpenseAutomationTransactionView } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
175
174
  import { toJEScheduleMainTab as toExpenseAutomationJEScheduleMainTab, toJEScheduleSortKey as toExpenseAutomationJEScheduleSortKey, } from './view/expenseAutomationView/types/jeSchedulesViewState';
176
- import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, } from './view/expenseAutomationView/types/missingReceiptsViewState';
175
+ import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toMatchSource, toMissingReceiptsTab, } from './view/expenseAutomationView/types/missingReceiptsViewState';
176
+ import { DEFAULT_COMPLETED_SUB_TAB, toCompletedSubTab, } from './view/expenseAutomationView/types/completedSubTab';
177
177
  import { toMissingReceiptsSortKey as toExpenseAutomationMissingReceiptsSortKey, } from './view/expenseAutomationView/types/missingReceiptsViewState';
178
178
  import { toReconciliationTabsType, } from './view/expenseAutomationView/types/reconciliationViewState';
179
179
  import { toTransactionsTabKey as toExpenseAutomationTransactionsTabKey, toTransactionsSortKey, } from './view/expenseAutomationView/types/transactionsViewState';
@@ -333,7 +333,6 @@ import { getRemiBusinessVerificationDetails, getRemiSetupViewDetails, } from './
333
333
  import { approveOrRejectRemisBulkAction, autoReviewPendingApprovalRemis, cancelOrDeleteRemisBulkAction, clearAllRemisFromBulkActionList, clearRemiBulkActionView, incrementRemiBulkActionProcessedCount, removeRemiFromBulkActionList, reviewDraftRemisBulkAction, submitDraftRemisBulkAction, updateRemisBulkActionList, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewReducer';
334
334
  import { getRemisBulkOperationProgress, getRemisBulkReviewView, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewSelector';
335
335
  import { hideCreatedByFilter, } from './view/spendManagement/spendManagementFilterHelpers';
336
- import { TRANSACTION_FILTER_CATEGORIES, applyTransactionFilters, } from './view/expenseAutomationView/transactionFilterHelpers';
337
336
  import { acceptTreasuryTerms, clearTreasurySetupView, fetchPortfolioAllocation, fetchTreasuryFunds, fetchTreasurySetupView, updateFundAllocationLocalData, updatePortfolioAllocation, updateTreasuryVideoViewed, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewReducer';
338
337
  import { getTreasuryBusinessVerificationDetails, getTreasurySetupViewDetails, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewSelector';
339
338
  import { getTreasuryFundsMaximumYield, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewState';
@@ -443,18 +442,18 @@ export { stringToUnion, stringToUnionStrict };
443
442
  export { fetchMonthEndCloseChecks, fetchMonthClosePerformanceTrend, getMonthEndCloseChecksViewByTenantId, ALL_MONTH_END_CLOSE_CHECKS_FREQUENCY, };
444
443
  export {
445
444
  // Bulk Upload Types
446
- BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, toExpenseAutomationJEScheduleMainTab, toExpenseAutomationJEScheduleSortKey, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, fetchExpenseAutomationMissingReceipts,
445
+ BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, DEFAULT_COMPLETED_SUB_TAB, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, toExpenseAutomationJEScheduleMainTab, toExpenseAutomationJEScheduleSortKey, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, fetchExpenseAutomationMissingReceipts,
447
446
  // Bulk Upload Actions
448
447
  bulkUploadReceipts, bulkUploadAutomatchingTimedOut, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete, fetchCompletedTransactions, fetchCompletedTransactionsSuccess, fetchCompletedTransactionsFailure, fetchFluxAnalysisView, clearExpenseAutomationFluxAnalysisView, updateOperatingExpensesIdsForReview as updateFluxOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview as updateFluxAnalysisSelectedSectionIdsForReview, reviewFluxAnalysisView, updateExpenseAutomationMissingReceiptUploadState, updateExpenseAutomationMissingReceiptsUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, getExpenseAutomationFluxAnalysisView, updateCurrentSelectedView, updateCurrentSelectedPeriod, getExpenseAutomationTransactionView, updateFluxAnalysisViewUIState, updateFluxAnalysisViewPageMetaData, MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, excludeAccountFromReconciliation, includeAccountInReconciliation, saveExpenseAutomationReconciliationDetail, updateExpenseAutomationReconcileTabListScrollState, updateExpenseAutomationReconReviewTabListSortState, updateExpenseAutomationReconcileTabListSortState, updateExpenseAutomationReconcileTabLocalData, updateExpenseAutomationAccountReconciliationSelectedTab, updateExpenseAutomationAccountReconciliationSelectedAccountId, getExpenseAutomationReconciliationView, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, getAccountReconByAccountIdAndSelectedPeriod, toReconciliationTabsType, isAccountReconReport, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, toReconciliationAccountSource, deleteAccountStatement, uploadAccountStatement, updateNodeCollapseState, updateStatementUploadChosen, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, };
449
- export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateTransactionFilters, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
448
+ export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
450
449
  export { TOP_EX_TIME_PERIODS };
451
450
  export { toTimeframeTick, mapTimePeriodtoTimeframeTick, toTimePeriod, toAbsoluteDay, toMonthYearPeriodId, convertToPeriod, };
452
451
  export { toVendorSpendTrendFilterTabsTypeStrict, } from './entity/vendorExpense/vendorExpenseSelector';
453
452
  export { getNumberOfPeriods };
454
453
  export { SCHEDULE_DAYS_OF_MONTH, toScheduleDaysOfMonth, toMonth, toMonthStrict, toQuarter, toQuarterStrict, };
455
454
  export { getTenantBaseById, getCurrentTenant, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getTenantsByCheckInDateSelector, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, toTenantCoreDetailsView, getTenantBaseViewForTenantView, getTenantBaseViewForTenantId, isZeniDomainTenant, isTenantUsingZeniCOA, fetchActiveTenant, fetchAllTenants, updateCurrentTenant, clearAll, doMagicLinkSignIn, verifyDeviceWithTwoFA, resendVerifyDeviceOTP, sendEmailMagicLinkToUser, doSignIn, updateSignInState, doSignOut, sendSessionHeartbeat, resetSignInState, fetchExcludedResourcesForTenant, fetchExternalConnectionsForTenant, saveExternalConnectionForTenant, deleteConnection, saveAPIKeyConnection, saveConnectorCredentials, saveOAuthConnection, toExternalIntegrationType, toExternalSupportedTool, fetchSubscriptionSummaryForTenant, isTenantBankingOnly, isTenantCardsOnly, isTenantBookkeepingEnabled, isOtherProductsEnabledForTenant, };
456
- export { toAccountType, toAccountGroupType, getAccountGroupKey, getAllAccounts, getTransactionFilterAccountOptions, };
457
- export { getAllClasses, getClassById } from './entity/class/classSelector';
455
+ export { toAccountType, toAccountGroupType, getAccountGroupKey, };
456
+ export { getClassById } from './entity/class/classSelector';
458
457
  export { getForecast };
459
458
  export { getUserName, getUserByUserId, getUsersByUserIds, getAllZeniUsersFromState, } from './entity/user/userSelector';
460
459
  export { toUserRoleType, toUserRoleTypeStrict, isFinOpsUserRoleType, hasAdminLevelAccess, hasFullOrAdminLevelAccess, hasReimbursementUserAccess, hasEmployeeLevelAccess, hasBookKeepingAdminLevelAccess, hasBookKeepingUserLevelAccess, isNonZeniRole, hasInvestorBankerLevelAccess, getUserRoleMap, hasOnlyBillPayAccess, hasZeniRoleOrCompanyOfficerAccess, hasSuperAdminLevelAccess, hasBillPayFallbackAdminLevelAccess, hasRemiFallbackAdminLevelAccess, hasOnlyReimbursementAccess, hasOnlyChargeCardAccess, hasOnlyZeniAccountsAccess, isZeniSignedInUser, getUserRoleByUserId, getUserRoleByUserIds, hasChargeCardAccess, hasZeniAccountsAccess, hasTreasuryAccess, hasTreasuryAdminLevelAccess, hasBillPayAccess, hasReimbursementAccess, hasReimbursementAdminLevelAccess, hasBillPayAdminLevelAccess, hasChargeCardAdminLevelAccess, hasSpendManagementAccess, hasSpendManagementAdminLevelAccess, hasZeniAccountsAdminLevelAccess, hasAnyCompanyRole, hasAnyFinOpRole, hasBillPayAccessible, hasReimbursementAccessible, hasZeniAccountsAccessible, hasChargeCardAccessible, hasTreasuryAccessible, hasAICFOAccess, };
@@ -554,10 +553,6 @@ export { toRemiSubTabType, toRemiSubTabTypeStrict, toRemiTabType, toRemiTabTypeS
554
553
  export { getClassList, fetchClassList, getProjectList, fetchProjectList, };
555
554
  export { fetchBillList, fetchBillListPerTab, updateTab, updateSubTab, updateSelectedBillId, updateBillDetailSaveBillCode, fetchVendorByNameAndParseInvoice, saveBillUpdatesToLocalStore, discardBillUpdatesInLocalStore, saveBillDetail, approveOrRejectBill, updateApprovalStatusOnSuccess, deleteBill, cancelAndDeleteBill, retryOrRefundBill, getBillList, getBillDownloadList, getBillDetailView, checkApproveRejectBtnShowForBill, getBillTransactionDetailKey, fetchBillDetail, fetchEditBillDetailPage, fetchAndUpdateVendorRecommendations, fetchDuplicateBill, clearBillPayReview, getEditBillDetail, getReviewPageBillDetail, fetchBillAndInitializeLocalStore, updateShowAutofill, saveVendorSuccessOrFailure, updateBillListUIState, BILL_PAY_FILTER_CATEGORIES, updateVendorDetailLocalData, resetVendorDetailLocalData, resetVendorSaveStatus, updateContactsInVendorDetailLocalData, updateVendorTabDetailUIState, updateContactsInVendorTabDetailLocalData, updateBillUploadFetchState, updateBillListSearchResult, fetchUserDetails, verifyUser, updateVendorContact, toPaymentToOption, convertAmountToHomeCurrency, fetchVendorAndUpdateBillLocalData, markBillForRetry, updateWithdrawFromAccountId, removeBillFileFromLocalStore, replaceBillFileInLocalStore, updateShouldReplaceBillData, };
556
555
  export { hideCreatedByFilter, };
557
- // Transaction Categorization filter API — lives under Expense Automation,
558
- // not Spend Management. Kept in a separate re-export block to make the
559
- // separation visible at the barrel level.
560
- export { TRANSACTION_FILTER_CATEGORIES, applyTransactionFilters, };
561
556
  export { fetchBillPaySetupView, fetchZeniAccountSetupView, enableSetup, getPaymentAccounts, getPlaidLinkToken, updateSelectedCompanyOfficer, updateSetupViewLocalStoreData, updateBusinessVerificationDetails, updatePaymentAccount, updatePaymentAccountLoginStatus, updatePaymentAccountStatus, establishPlaidConnection, updateMappedCashAccount, updatePrimaryFundingAccount, acceptBillPayTerms, acceptZeniAccountTerms, acceptBillPayUpdatedTerms, saveSetupViewDataInLocalStore, saveCompnayOfficerPhoneInLocalStore, saveCompnayOfficerAdditionalDocumentsInLocalStore, saveTreasuryAdditionalDocumentsInLocalStore, saveIndustryAndIncDateInLocalStore, clearSetupViewDataInLocalStore, clearBillPaySetupView, clearZeniAccountSetupView, sendOtp, resendOtp, verifyOtp, getBillPaySetupViewDetails, getPlaidAccountDetails, getZeniAccountSetupViewDetails, getBusinessVerificationDetails, getBillPayBusinessVerificationDetails, getZeniAccountBusinessVerificationDetails, getTreasuryBusinessVerificationDetails, getCommonSetupViewDetails, getTwoFactorAuthenticationView, getTwoFactorAuthenticationViewForCardUserOnboarding, getTwoFactorAuthenticationViewForChargeCardHolder, };
562
557
  export { getApprovalRuleViewDetails, getBankConnectionsSetupViewDetails, getIntegrationsView, };
563
558
  export { fetchUserFinancialAccount };
@@ -5,6 +5,7 @@ import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
5
5
  import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
6
6
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
7
7
  import { fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, getCompletedTransactionsCacheKey, } from '../../reducers/missingReceiptsViewReducer';
8
+ import { DEFAULT_COMPLETED_SUB_TAB } from '../../types/completedSubTab';
8
9
  export const fetchCompletedTransactionsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchCompletedTransactions.match), switchMap((action) => {
9
10
  const state = state$.value;
10
11
  const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationMissingReceiptsViewState: { bulkUpload }, } = state;
@@ -39,7 +40,7 @@ export const fetchCompletedTransactionsEpic = (actions$, state$, zeniAPI) => act
39
40
  if (sortOrder != null) {
40
41
  queryPayload.sort_order = sortOrder === 'ascending' ? 'asc' : 'desc';
41
42
  }
42
- if (completedSubTab !== 'all') {
43
+ if (completedSubTab !== DEFAULT_COMPLETED_SUB_TAB) {
43
44
  queryPayload.match_type = completedSubTab;
44
45
  }
45
46
  const encodedQuery = encodeURIComponent(JSON.stringify(queryPayload));
@@ -4,6 +4,7 @@ import { updateTransactions } from '../../../../entity/transaction/transactionRe
4
4
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
5
5
  import { supportedTransactionPayloadToManualSearchResult } from '../../payload/missingReceiptsPayload';
6
6
  import { searchTransactionsForManualMatch, searchTransactionsForManualMatchFailure, searchTransactionsForManualMatchSuccess, } from '../../reducers/missingReceiptsViewReducer';
7
+ import { DEFAULT_COMPLETED_SUB_TAB } from '../../types/completedSubTab';
7
8
  import { toTransactionsSortKey } from '../../types/transactionsViewState';
8
9
  import { rollingCalendarDateRangeInclusive } from '../../helpers/rollingCalendarDateRangeInclusive';
9
10
  /**
@@ -46,6 +47,11 @@ export const searchTransactionsForManualMatchEpic = (actions$, state$, zeniAPI)
46
47
  page_token: pageToken ?? null,
47
48
  page_size: manualSearch.pageSize,
48
49
  search_text: query,
50
+ // Manual search ignores the Completed sub-tab axis — always span the
51
+ // default sentinel so the receipt-matching UX returns results
52
+ // regardless of where the transaction would otherwise be bucketed on
53
+ // the Completed tab.
54
+ sub_tab: DEFAULT_COMPLETED_SUB_TAB,
49
55
  };
50
56
  return zeniAPI
51
57
  .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/expense-automation/transactions?query=${encodeURIComponent(JSON.stringify(queryParam))}`)
@@ -5,7 +5,8 @@ import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
5
5
  import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
6
6
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
7
7
  import { getLineItemsByTransactionsIdsFromResponse } from '../../helpers/transactionCategorizationLocalDataHelper';
8
- import { fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationSuccess, initializeTransactionCategorizationViewLocalData, resetOtherTabsFetchState, updateTotalCountForTransactionCategorization, updateTransactionCategorizationUIState, } from '../../reducers/transactionsViewReducer';
8
+ import { fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationSuccess, initializeTransactionCategorizationViewLocalData, resetOtherTabsFetchState, updateParentTotalCountForTab, updateTotalCountForTransactionCategorization, updateTransactionCategorizationUIState, } from '../../reducers/transactionsViewReducer';
9
+ import { DEFAULT_COMPLETED_SUB_TAB } from '../../types/completedSubTab';
9
10
  import { TRANSACTIONS_TABS, toTransactionsSortKey, } from '../../types/transactionsViewState';
10
11
  export const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchTransactionCategorization.match), switchMap((action) => {
11
12
  const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationTransactionsViewState, } = state$.value;
@@ -23,6 +24,9 @@ export const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) =>
23
24
  page_token: pageToken,
24
25
  page_size: 25,
25
26
  search_text: uiState.searchString,
27
+ sub_tab: selectedTab === 'autoCategorized'
28
+ ? expenseAutomationTransactionsViewState.selectedTransactionCategorizationCompletedSubTab
29
+ : DEFAULT_COMPLETED_SUB_TAB,
26
30
  };
27
31
  return zeniAPI
28
32
  .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/expense-automation/transactions?query=${encodeURIComponent(JSON.stringify(queryParam))}`)
@@ -45,6 +49,12 @@ export const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) =>
45
49
  selectedTab,
46
50
  totalCount: response.data.total_count,
47
51
  }));
52
+ updateActions.push(updateParentTotalCountForTab({
53
+ selectedPeriod,
54
+ selectedTab,
55
+ parentTotalCount: response.data.parent_tab_total_count ??
56
+ response.data.total_count,
57
+ }));
48
58
  updateActions.push(resetOtherTabsFetchState({
49
59
  refreshViewInBackground,
50
60
  tabs: TRANSACTIONS_TABS.filter((tab) => selectedTab !== tab),
@@ -1,5 +1,6 @@
1
1
  import { createAction, createSlice } from '@reduxjs/toolkit';
2
2
  import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
3
+ import { DEFAULT_COMPLETED_SUB_TAB, } from '../types/completedSubTab';
3
4
  import { MIN_MANUAL_TRANSACTION_SEARCH_LENGTH, } from '../types/missingReceiptsViewState';
4
5
  export const getCompletedTransactionsCacheKey = (periodId, sortKey, sortOrder, subTab) => {
5
6
  const sortKeyPart = sortKey ?? 'none';
@@ -12,7 +13,7 @@ export const initialBulkUploadState = {
12
13
  batchListByPeriod: {},
13
14
  batchListFetchState: { fetchState: 'Not-Started', error: undefined },
14
15
  batchStatusById: {},
15
- completedSubTab: 'all',
16
+ completedSubTab: DEFAULT_COMPLETED_SUB_TAB,
16
17
  completedTransactionsByPeriod: {},
17
18
  confirmMatchStatus: { fetchState: 'Not-Started', error: undefined },
18
19
  currentBatchId: undefined,
@@ -4,6 +4,7 @@ import uniq from 'lodash/uniq';
4
4
  import { toMonthYearPeriodId, } from '../../../commonStateTypes/timePeriod';
5
5
  import { isVendorTransaction } from '../../../entity/transaction/stateTypes/vendorTransaction';
6
6
  import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, filterAutoTabLineItems, mergeTabSpecificLineItems, removeTransactionFromTabView, setEntityRecommendationForLineIdInLocalData, toSetAllLineItemsToCategoryClass, toTransactionDetailLocalData, } from '../helpers/transactionCategorizationLocalDataHelper';
7
+ import { DEFAULT_COMPLETED_SUB_TAB, } from '../types/completedSubTab';
7
8
  export const initialTransactionTabViewState = {
8
9
  saveStatus: {
9
10
  fetchState: 'Not-Started',
@@ -27,10 +28,6 @@ export const initialTransactionTabViewState = {
27
28
  totalCount: {},
28
29
  limit: 10,
29
30
  },
30
- filters: {
31
- categoryCombinationOperator: 'AND',
32
- categories: [],
33
- },
34
31
  fetchState: 'Not-Started',
35
32
  error: undefined,
36
33
  hasValidState() {
@@ -45,12 +42,68 @@ export const initialTransactionTabViewState = {
45
42
  selectedTransactionLineId: undefined,
46
43
  };
47
44
  export const initialState = {
45
+ autoCategorizedSubTabCache: {},
46
+ parentTotalCountByTab: {
47
+ review: {},
48
+ autoCategorized: {},
49
+ },
48
50
  selectedTransactionCategorizationTab: 'review',
51
+ selectedTransactionCategorizationCompletedSubTab: DEFAULT_COMPLETED_SUB_TAB,
49
52
  transactionCategorizationView: {
50
53
  review: { ...initialTransactionTabViewState },
51
54
  autoCategorized: { ...initialTransactionTabViewState },
52
55
  },
53
56
  };
57
+ /**
58
+ * Capture the autoCategorized tab's current paginated dataset for a sub-tab.
59
+ * The mid-flight `'In-Progress'` state is normalised to `'Completed'` because
60
+ * the in-flight request is cancelled by `switchMap` in the fetch epic when the
61
+ * sub-tab changes — restoring `'In-Progress'` later would leave the UI stuck
62
+ * showing a phantom loading state with no fetch actually running. Length-zero
63
+ * datasets degrade to `'Not-Started'` so the next visit triggers a fresh
64
+ * fetch from page 1 instead of short-circuiting on stale empty caches.
65
+ *
66
+ * Snapshot scope (deliberately narrow):
67
+ * - Captured: `pageToken`, `totalCount`, `transactionIdsBySelectedPeriod`,
68
+ * `fetchState`, `error`. These are the keys the fetch epic's cache check
69
+ * reads to decide whether to short-circuit a sub-tab revisit.
70
+ * - Intentionally NOT captured (left in place on `autoCat` and inherited by
71
+ * the incoming sub-tab):
72
+ * - `uiState.searchString`, `uiState.sortKey`, `uiState.sortOrder`,
73
+ * `uiState.scrollPosition`, `uiState.nodeCollapseState`,
74
+ * `uiState.limit` — search and sort are user-applied preferences that
75
+ * persist across sub-tabs by design (a search query stays active when
76
+ * the user toggles between Manual / AI Accountant).
77
+ * - `selectedCheckBoxTransactionIds` — selection state is intentionally
78
+ * cleared at the action source (the fetch epic / save flow), not
79
+ * by the snapshot path. Carrying selection across sub-tabs is safe
80
+ * because every sub-tab change goes through a fetch round-trip that
81
+ * reconciles selection against the new row IDs.
82
+ * - `transactionReviewLocalDataById`, `transactionIdsWithUnsavedData`,
83
+ * `uploadReceiptStatusById`, `saveStatus`, `refreshStatus`,
84
+ * `markAsNotMiscategorizedStatus` — these are per-row / per-flight
85
+ * caches that are write-through global state, not sub-tab-scoped.
86
+ *
87
+ * If the contract changes (e.g. selection should reset on every sub-tab
88
+ * switch), update both this comment and the snapshot return shape together.
89
+ */
90
+ function snapshotAutoCategorizedTab(autoCat) {
91
+ const transactionIdsBySelectedPeriod = {
92
+ ...autoCat.transactionIdsBySelectedPeriod,
93
+ };
94
+ const hasAnyLoadedRows = Object.values(transactionIdsBySelectedPeriod).some((ids) => ids.length > 0);
95
+ let normalisedFetchState = autoCat.fetchState;
96
+ if (normalisedFetchState === 'In-Progress') {
97
+ normalisedFetchState = hasAnyLoadedRows ? 'Completed' : 'Not-Started';
98
+ }
99
+ return {
100
+ error: autoCat.error,
101
+ fetchState: normalisedFetchState,
102
+ pageToken: autoCat.uiState.pageToken,
103
+ totalCount: { ...autoCat.uiState.totalCount },
104
+ transactionIdsBySelectedPeriod,
105
+ };
106
+ }
54
107
  const expenseAutomationTransactionsView = createSlice({
55
108
  name: 'expenseAutomationTransactionsView',
56
109
  initialState,
@@ -240,12 +293,6 @@ const expenseAutomationTransactionsView = createSlice({
240
293
  uiState.totalCount;
241
294
  }
242
295
  },
243
- updateTransactionFilters(draft, action) {
244
- const { selectedTab, filters } = action.payload;
245
- if (filters != null) {
246
- draft.transactionCategorizationView[selectedTab].filters = filters;
247
- }
248
- },
249
296
  saveTransactionCategorization: {
250
297
  prepare(selectedTab, transactionIds, cotTrackingByTransactionId, isUncategorizedExpenseCategoryEnabled) {
251
298
  return {
@@ -270,6 +317,48 @@ const expenseAutomationTransactionsView = createSlice({
270
317
  return { payload: { newSelectedTab } };
271
318
  },
272
319
  },
320
+ updateTransactionCategorizationCompletedSubTab: {
321
+ reducer(draft, action) {
322
+ const { newSubTab } = action.payload;
323
+ const previousSubTab = draft.selectedTransactionCategorizationCompletedSubTab;
324
+ if (previousSubTab === newSubTab) {
325
+ return;
326
+ }
327
+ const autoCat = draft.transactionCategorizationView.autoCategorized;
328
+ // Snapshot the outgoing sub-tab so a future revisit can short-circuit
329
+ // the fetch epic (mirrors the parent-tab "don't refetch what's
330
+ // already cached" behaviour). Period-scoped data is preserved as-is
331
+ // because the snapshot itself is keyed only by sub-tab; the active
332
+ // tab's per-period maps remain the source of truth while live.
333
+ draft.autoCategorizedSubTabCache[previousSubTab] =
334
+ snapshotAutoCategorizedTab(autoCat);
335
+ const cached = draft.autoCategorizedSubTabCache[newSubTab];
336
+ if (cached != null) {
337
+ autoCat.uiState.pageToken = cached.pageToken;
338
+ autoCat.uiState.totalCount = { ...cached.totalCount };
339
+ autoCat.transactionIdsBySelectedPeriod = {
340
+ ...cached.transactionIdsBySelectedPeriod,
341
+ };
342
+ autoCat.fetchState = cached.fetchState;
343
+ autoCat.error = cached.error;
344
+ }
345
+ else {
346
+ // Sub-tab has never been visited — clear the active slot so the
347
+ // view-epic's `fetchState === 'Not-Started' || transactionIds.length
348
+ // === 0` cache check falls through and triggers a fresh page-1
349
+ // fetch for the new dataset.
350
+ autoCat.uiState.pageToken = null;
351
+ autoCat.uiState.totalCount = {};
352
+ autoCat.transactionIdsBySelectedPeriod = {};
353
+ autoCat.fetchState = 'Not-Started';
354
+ autoCat.error = undefined;
355
+ }
356
+ draft.selectedTransactionCategorizationCompletedSubTab = newSubTab;
357
+ },
358
+ prepare(newSubTab) {
359
+ return { payload: { newSubTab } };
360
+ },
361
+ },
273
362
  updateTransactionCategorization: {
274
363
  reducer(draft, action) {
275
364
  const selectedTab = action.payload.selectedTab;
@@ -707,6 +796,10 @@ const expenseAutomationTransactionsView = createSlice({
707
796
  const { selectedTab, selectedPeriod, totalCount } = action.payload;
708
797
  draft.transactionCategorizationView[selectedTab].uiState.totalCount[toMonthYearPeriodId(selectedPeriod)] = totalCount;
709
798
  },
799
+ updateParentTotalCountForTab(draft, action) {
800
+ const { selectedTab, selectedPeriod, parentTotalCount } = action.payload;
801
+ draft.parentTotalCountByTab[selectedTab][toMonthYearPeriodId(selectedPeriod)] = parentTotalCount;
802
+ },
710
803
  updateSelectedCheckboxTransactionIds(draft, action) {
711
804
  const selectedTab = action.payload.selectedTab;
712
805
  const transactionIds = action.payload.transactionIds;
@@ -717,6 +810,16 @@ const expenseAutomationTransactionsView = createSlice({
717
810
  draft.transactionCategorizationView[selectedTab] = {
718
811
  ...initialTransactionTabViewState,
719
812
  };
813
+ draft.parentTotalCountByTab[selectedTab] = {};
814
+ // The per-sub-tab snapshot cache lives at the slice root and is
815
+ // exclusively populated by the autoCategorized tab's sub-tab switching
816
+ // (see updateTransactionCategorizationCompletedSubTab). When that tab
817
+ // is reset, leaving stale snapshots behind would short-circuit the
818
+ // next sub-tab visit with phantom row IDs / page tokens that no longer
819
+ // correspond to anything in state — drop them in lockstep.
820
+ if (selectedTab === 'autoCategorized') {
821
+ draft.autoCategorizedSubTabCache = {};
822
+ }
720
823
  },
721
824
  clearExpenseAutomationTransactionsView(draft) {
722
825
  Object.assign(draft, initialState);
@@ -813,5 +916,5 @@ const expenseAutomationTransactionsView = createSlice({
813
916
  },
814
917
  },
815
918
  });
816
- export const { fetchTransactionCategorization, updateTransactionCategorizationUIState, updateTransactionFilters, initializeTransactionCategorizationViewLocalData, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateStatusForTransactionNotMiscategorizedUpdateForCategorization, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, setAllItemsToCategoryClassInLocalDataForCategorization, updateTotalCountForTransactionCategorization, fetchTransactionCategorizationSuccess, resetOtherTabsFetchState, fetchTransactionCategorizationView, updateSelectedCheckboxTransactionIds, clearExpenseAutomationTransactionsViewPerTabView, clearExpenseAutomationTransactionsView, setEntityRecommendationForLineIdsForCategorization, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, } = expenseAutomationTransactionsView.actions;
919
+ export const { fetchTransactionCategorization, updateTransactionCategorizationUIState, initializeTransactionCategorizationViewLocalData, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateStatusForTransactionNotMiscategorizedUpdateForCategorization, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, setAllItemsToCategoryClassInLocalDataForCategorization, updateTotalCountForTransactionCategorization, updateParentTotalCountForTab, fetchTransactionCategorizationSuccess, resetOtherTabsFetchState, fetchTransactionCategorizationView, updateSelectedCheckboxTransactionIds, clearExpenseAutomationTransactionsViewPerTabView, clearExpenseAutomationTransactionsView, setEntityRecommendationForLineIdsForCategorization, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, } = expenseAutomationTransactionsView.actions;
817
920
  export default expenseAutomationTransactionsView.reducer;