@zeniai/client-epic-state 5.0.31-beta0ND → 5.0.31-betaAR1

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 (29) hide show
  1. package/lib/entity/account/accountSelector.d.ts +18 -0
  2. package/lib/entity/account/accountSelector.js +31 -1
  3. package/lib/entity/account/accountState.d.ts +5 -0
  4. package/lib/entity/account/accountState.js +11 -4
  5. package/lib/entity/class/classSelector.d.ts +5 -0
  6. package/lib/entity/class/classSelector.js +8 -0
  7. package/lib/entity/transaction/payloadTypes/transactionLinePayload.js +1 -1
  8. package/lib/esm/entity/account/accountSelector.js +29 -1
  9. package/lib/esm/entity/account/accountState.js +7 -1
  10. package/lib/esm/entity/class/classSelector.js +7 -0
  11. package/lib/esm/entity/transaction/payloadTypes/transactionLinePayload.js +1 -1
  12. package/lib/esm/index.js +14 -14
  13. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +11 -1
  14. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +57 -8
  15. package/lib/esm/view/profitAndLossClassesView/profitAndLossHorizontalEnrichment.js +0 -42
  16. package/lib/esm/view/spendManagement/spendManagementFilterHelpers.js +198 -15
  17. package/lib/index.d.ts +19 -20
  18. package/lib/index.js +48 -42
  19. package/lib/tsconfig.typecheck.tsbuildinfo +1 -1
  20. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +5 -1
  21. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +12 -2
  22. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.d.ts +4 -1
  23. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +59 -8
  24. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +2 -0
  25. package/lib/view/profitAndLossClassesView/profitAndLossHorizontalEnrichment.d.ts +1 -15
  26. package/lib/view/profitAndLossClassesView/profitAndLossHorizontalEnrichment.js +0 -43
  27. package/lib/view/spendManagement/spendManagementFilterHelpers.d.ts +45 -4
  28. package/lib/view/spendManagement/spendManagementFilterHelpers.js +199 -16
  29. package/package.json +1 -1
@@ -123,3 +123,21 @@ 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
+ }
136
+ /**
137
+ * Partitions accounts for transaction filter dropdowns: bank/credit_card → paymentAccountNames,
138
+ * all other account types → categoryOptions. Use for payment_account_name and category filter options.
139
+ */
140
+ export declare const getTransactionFilterAccountOptions: (accountState: AccountState) => {
141
+ categoryOptions: AccountFilterOption[];
142
+ paymentAccountNames: AccountFilterOption[];
143
+ };
@@ -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.getAccountIdsForLabels = exports.getAccountIdsForTypes = exports.getAccountsByType = exports.getAccountsOrdered = exports.getAccountBase = void 0;
6
+ exports.getTransactionFilterAccountOptions = exports.getAllAccounts = 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,3 +192,33 @@ 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
+ const option = {
212
+ accountId: account.accountId,
213
+ accountName: account.accountName,
214
+ };
215
+ if ((0, accountState_1.isPaymentAccountType)(account.accountType)) {
216
+ paymentAccountNames.push(option);
217
+ }
218
+ else {
219
+ categoryOptions.push(option);
220
+ }
221
+ }
222
+ return { categoryOptions, paymentAccountNames };
223
+ };
224
+ exports.getTransactionFilterAccountOptions = getTransactionFilterAccountOptions;
@@ -8,9 +8,14 @@ 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"];
11
12
  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";
12
13
  export type AccountType = ReturnType<typeof toAccountType>;
13
14
  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;
14
19
  export type UncategorizedAccountTypes = 'expense' | 'income';
15
20
  declare const toAccountLabel: (v: string) => "prepaid_expenses" | "fixed_assets" | "uncategorized_income" | "uncategorized_expense" | "bank_charges_and_fees" | "travel_transportation" | "accrued_expenses";
16
21
  export type AccountLabel = ReturnType<typeof toAccountLabel>;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toReconciliationAccountSourceStrict = exports.toReconciliationAccountSource = exports.toAccountLabelStrict = exports.toAccountTypeStrict = exports.toAccountType = void 0;
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;
4
5
  exports.getAccountKey = getAccountKey;
5
6
  const nestedAccountID_1 = require("../../commonStateTypes/accountView/nestedAccountID");
6
7
  const nestedClassID_1 = require("../../commonStateTypes/classesView/nestedClassID");
7
8
  const stringToUnion_1 = require("../../commonStateTypes/stringToUnion");
8
- const ALL_ACCOUNT_TYPES = [
9
+ exports.ALL_ACCOUNT_TYPES = [
9
10
  'bank',
10
11
  'credit_card',
11
12
  'expenses',
@@ -27,10 +28,16 @@ const ALL_ACCOUNT_TYPES = [
27
28
  'current_liabilities',
28
29
  'current_assets',
29
30
  ];
30
- const toAccountType = (v) => (0, stringToUnion_1.stringToUnion)(v, ALL_ACCOUNT_TYPES);
31
+ const toAccountType = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.ALL_ACCOUNT_TYPES);
31
32
  exports.toAccountType = toAccountType;
32
- const toAccountTypeStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v ?? '', ALL_ACCOUNT_TYPES);
33
+ const toAccountTypeStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v ?? '', exports.ALL_ACCOUNT_TYPES);
33
34
  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
+ }
34
41
  const ALL_ACCOUNT_LABELS = [
35
42
  'uncategorized_income',
36
43
  'uncategorized_expense',
@@ -20,3 +20,8 @@ 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,6 +6,7 @@ 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;
9
10
  const get_1 = __importDefault(require("lodash/get"));
10
11
  const coaBalance_1 = require("../../commonStateTypes/coaBalance/coaBalance");
11
12
  const accountSelector_1 = require("../account/accountSelector");
@@ -58,3 +59,10 @@ function getClassReport(classState, accountState, id, filter) {
58
59
  accounts: accountReport,
59
60
  };
60
61
  }
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
+ }
@@ -26,7 +26,7 @@ const toTransactionLineBase = (payload, lineType, currency) => ({
26
26
  });
27
27
  const toLinkedTransactionLine = (payload, currency) => ({
28
28
  ...toTransactionLineBase(payload, 'linked_transaction_line', currency),
29
- linkedTransactions: payload.linked_transactions.map((transactionIDPayload) => (0, transactionIDPayload_1.toTransactionID)(transactionIDPayload)),
29
+ linkedTransactions: payload.linked_transactions != null ? payload.linked_transactions.map((transactionIDPayload) => (0, transactionIDPayload_1.toTransactionID)(transactionIDPayload)) : [],
30
30
  });
31
31
  /**
32
32
  * Transaction with account and class line payload with COT tracking
@@ -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, } from './accountState';
4
+ import { getAccountKey, isPaymentAccountType, } 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,3 +179,31 @@ 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
+ const option = {
198
+ accountId: account.accountId,
199
+ accountName: account.accountName,
200
+ };
201
+ if (isPaymentAccountType(account.accountType)) {
202
+ paymentAccountNames.push(option);
203
+ }
204
+ else {
205
+ categoryOptions.push(option);
206
+ }
207
+ }
208
+ return { categoryOptions, paymentAccountNames };
209
+ };
@@ -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
- const ALL_ACCOUNT_TYPES = [
4
+ export const ALL_ACCOUNT_TYPES = [
5
5
  'bank',
6
6
  'credit_card',
7
7
  'expenses',
@@ -25,6 +25,12 @@ 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
+ }
28
34
  const ALL_ACCOUNT_LABELS = [
29
35
  'uncategorized_income',
30
36
  'uncategorized_expense',
@@ -50,3 +50,10 @@ 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
+ }
@@ -22,7 +22,7 @@ const toTransactionLineBase = (payload, lineType, currency) => ({
22
22
  });
23
23
  const toLinkedTransactionLine = (payload, currency) => ({
24
24
  ...toTransactionLineBase(payload, 'linked_transaction_line', currency),
25
- linkedTransactions: payload.linked_transactions.map((transactionIDPayload) => toTransactionID(transactionIDPayload)),
25
+ linkedTransactions: payload.linked_transactions != null ? payload.linked_transactions.map((transactionIDPayload) => toTransactionID(transactionIDPayload)) : [],
26
26
  });
27
27
  /**
28
28
  * Transaction with account and class line payload with COT tracking
package/lib/esm/index.js CHANGED
@@ -23,7 +23,8 @@ 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 { toAccountType, toReconciliationAccountSource, } from './entity/account/accountState';
26
+ import { getAllAccounts, getTransactionFilterAccountOptions, } from './entity/account/accountSelector';
27
+ import { ALL_ACCOUNT_TYPES, toAccountType, toReconciliationAccountSource, } from './entity/account/accountState';
27
28
  import { getAccountGroupKey, toAccountGroupType, } from './entity/accountGroup/accountGroupState';
28
29
  /**
29
30
  * Expense Automation Exports starts
@@ -59,7 +60,7 @@ import { closeSnackbar, openSnackbar } from './entity/snackbar/snackbarReducer';
59
60
  import { getSnackbar } from './entity/snackbar/snackbarSelector';
60
61
  import { toPriorityCodeType, toTaskStatusCodeType, } from './entity/task/taskState';
61
62
  import { getTaskGroupById } from './entity/taskGroup/taskGroupSelector';
62
- import { clearAll, doMagicLinkSignIn, doSignIn, doSignOut, sendSessionHeartbeat, fetchActiveTenant, fetchAllTenants, fetchExcludedResources as fetchExcludedResourcesForTenant, fetchExternalConnections as fetchExternalConnectionsForTenant, fetchSubscriptionSummaryForTenant, resendVerifyDeviceOTP, resetSignInState, saveExternalConnection as saveExternalConnectionForTenant, sendEmailMagicLinkToUser, updateCurrentTenant, updateSignInState, verifyDeviceWithTwoFA, } from './entity/tenant/tenantReducer';
63
+ import { clearAll, doMagicLinkSignIn, doSignIn, doSignOut, fetchActiveTenant, fetchAllTenants, fetchExcludedResources as fetchExcludedResourcesForTenant, fetchExternalConnections as fetchExternalConnectionsForTenant, fetchSubscriptionSummaryForTenant, resendVerifyDeviceOTP, resetSignInState, saveExternalConnection as saveExternalConnectionForTenant, sendEmailMagicLinkToUser, sendSessionHeartbeat, updateCurrentTenant, updateSignInState, verifyDeviceWithTwoFA, } from './entity/tenant/tenantReducer';
63
64
  import { getCurrentTenant, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getTenantBaseById, getTenantBaseViewForTenantId, getTenantBaseViewForTenantView, getTenantsBaseByCheckInDateSelector, getTenantsByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, isOtherProductsEnabledForTenant, isTenantBankingOnly, isTenantBookkeepingEnabled, isTenantCardsOnly, isTenantUsingZeniCOA, isZeniDomainTenant, toTenantCoreDetailsView, } from './entity/tenant/tenantSelector';
64
65
  import { pushToastNotification } from './entity/toastNotification/toastNotificationReducer';
65
66
  import { getLastNotificationTime, getNotifications, } from './entity/toastNotification/toastNotificationSelector';
@@ -165,7 +166,7 @@ import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFl
165
166
  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';
166
167
  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';
167
168
  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';
168
- import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markTransactionAsNotMiscategorized, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
169
+ 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';
169
170
  import { getExpenseAutomationFluxAnalysisView } from './view/expenseAutomationView/selectors/fluxAnalysisViewSelector';
170
171
  import { getExpenseAutomationReconciliationView, isAccountReconReport, } from './view/expenseAutomationView/selectors/reconciliationViewSelector';
171
172
  import { getExpenseAutomationTransactionView } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
@@ -220,12 +221,11 @@ import { fetchProfitAndLoss, fetchProfitAndLossForTimeframe, resetProfitAndLossN
220
221
  import { getPandLReportFetchState, getProfitAndLossReport, } from './view/profitAndLoss/profitAndLossSelector';
221
222
  import { getEmptyHorizontalSectionBalancesSlice } from './view/profitAndLossClassesView/horizontalSectionEmptyBalancesSlice';
222
223
  import { getProfitAndLossClassesHorizontalView } from './view/profitAndLossClassesView/profitAndLossClassesByClassHorizontalSelector';
223
- import { aggregateHorizontalDescendantBalances } from './view/profitAndLossClassesView/profitAndLossHorizontalEnrichment';
224
224
  import { HORIZONTAL_CLASS_TOTAL_BALANCE_ID, isHorizontalAccountReportData, } from './view/profitAndLossClassesView/profitAndLossClassesByClassHorizontalSelectorTypes';
225
225
  import { fetchProfitAndLossClassesView, resetProfitAndLossClassesNodeCollapseState, updateClassViewLayout, updateAccountViewMode as updateProfitAndLossAccountViewMode, updateClassesToFilterOut as updateProfitAndLossClassesToFilterOut, updateProfitAndLossClassesViewUIState, } from './view/profitAndLossClassesView/profitAndLossClassesViewReducer';
226
226
  import { getProfitAndLossClassesView } from './view/profitAndLossClassesView/profitAndLossClassesViewSelector';
227
227
  import { isPandLReportViewCalculatedSectionID, isPandLReportViewSectionID, } from './view/profitAndLossClassesView/profitAndLossClassesViewSelectorTypes';
228
- import { clearProfitAndLossProjectView, fetchProfitAndLossForTimeframeProjectView, fetchProfitAndLossProjectView, resetProfitAndLossProjectNodeCollapseState, updateProjectViewAccountViewMode, updateProjectsToFilterOut, updateProfitAndLossProjectViewUIState, } from './view/profitAndLossProjectView/profitAndLossProjectViewReducer';
228
+ import { clearProfitAndLossProjectView, fetchProfitAndLossForTimeframeProjectView, fetchProfitAndLossProjectView, resetProfitAndLossProjectNodeCollapseState, updateProfitAndLossProjectViewUIState, updateProjectViewAccountViewMode, updateProjectsToFilterOut, } from './view/profitAndLossProjectView/profitAndLossProjectViewReducer';
229
229
  import { getProfitAndLossProjectView } from './view/profitAndLossProjectView/profitAndLossProjectViewSelector';
230
230
  import { fetchEntityRecommendationsByTransactionId, fetchRecommendationByEntityId, fetchRecommendationByEntityName, } from './view/recommendation/recommendationReducer';
231
231
  import { clearReferrals, fetchReferrals, fetchRewardsPlan, resendReferralInvite, saveReferralFormDataInLocalStore, sendReferralInvite, updateReferViewed, updateReferralListSortUiState, } from './view/referralView/referralReducer';
@@ -327,7 +327,7 @@ import { acceptEmployeeRemiTerms, acceptRemiTerms, clearRemiSetupView, fetchRemi
327
327
  import { getRemiBusinessVerificationDetails, getRemiSetupViewDetails, } from './view/spendManagement/reimbursement/remiSetupView/remiSetupViewSelector';
328
328
  import { approveOrRejectRemisBulkAction, autoReviewPendingApprovalRemis, cancelOrDeleteRemisBulkAction, clearAllRemisFromBulkActionList, clearRemiBulkActionView, incrementRemiBulkActionProcessedCount, removeRemiFromBulkActionList, reviewDraftRemisBulkAction, submitDraftRemisBulkAction, updateRemisBulkActionList, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewReducer';
329
329
  import { getRemisBulkOperationProgress, getRemisBulkReviewView, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewSelector';
330
- import { hideCreatedByFilter, } from './view/spendManagement/spendManagementFilterHelpers';
330
+ import { TRANSACTION_FILTER_CATEGORIES, hideCreatedByFilter, } from './view/spendManagement/spendManagementFilterHelpers';
331
331
  import { acceptTreasuryTerms, clearTreasurySetupView, fetchPortfolioAllocation, fetchTreasuryFunds, fetchTreasurySetupView, updateFundAllocationLocalData, updatePortfolioAllocation, updateTreasuryVideoViewed, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewReducer';
332
332
  import { getTreasuryBusinessVerificationDetails, getTreasurySetupViewDetails, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewSelector';
333
333
  import { getTreasuryFundsMaximumYield, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewState';
@@ -354,14 +354,14 @@ import { getSubscriptionEstimationData, getSubscriptionListView, getSubscription
354
354
  import { toSubscriptionSortKeyType, } from './view/subscriptionView/types/subscriptionTypes';
355
355
  import { createTag, deleteTag, fetchTagList, } from './view/tagView/tagViewReducer';
356
356
  import { getAllTags } from './view/tagView/tagViewSelector';
357
- import { initialTaskDetail, initialTaskDetailLocalData, } from './view/taskManager/taskDetailView/taskDetail';
358
- import { archiveTask, deleteTask, discardTaskUpdatesInLocalStore, fetchTaskDetailPage, saveTaskDetail, saveTaskUpdatesToLocalStore, snoozeTask, unsnoozeTask, } from './view/taskManager/taskDetailView/taskDetailReducer';
359
357
  import { deleteCannedResponse, fetchCannedResponses, saveCannedResponse, } from './view/taskManager/cannedResponsesView/cannedResponsesReducer';
360
358
  import { getCannedResponsesView } from './view/taskManager/cannedResponsesView/cannedResponsesSelector';
359
+ import { initialTaskDetail, initialTaskDetailLocalData, } from './view/taskManager/taskDetailView/taskDetail';
360
+ import { archiveTask, deleteTask, discardTaskUpdatesInLocalStore, fetchTaskDetailPage, saveTaskDetail, saveTaskUpdatesToLocalStore, snoozeTask, unsnoozeTask, } from './view/taskManager/taskDetailView/taskDetailReducer';
361
361
  import { allTaskPriority, allTaskStatus, getTaskDetail, } from './view/taskManager/taskDetailView/taskDetailSelector';
362
362
  import { createTaskFromTaskGroupTemplate } from './view/taskManager/taskGroupTemplateView/taskGroupTemplateViewReducer';
363
363
  import { createNewTaskGroup, deleteTaskGroup, fetchAllTaskGroups, updateTaskGroupName, } from './view/taskManager/taskGroupView/taskGroupViewReducer';
364
- import { TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, toDueDateGroupKeyType, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict, ALL_TASK_LIST_TABS, } from './view/taskManager/taskListView/taskList';
364
+ import { ALL_TASK_LIST_TABS, TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, toDueDateGroupKeyType, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict, } from './view/taskManager/taskListView/taskList';
365
365
  import { bulkUpdateTaskList, dragNDropTasks, fetchTaskListPage, initiateTaskListLocalData, removeTaskFromList, updateTaskFilters, updateTaskFromListView, updateTaskListLocalData, updateTaskListSearchText, updateTaskListTab, updateTaskListUIState, } from './view/taskManager/taskListView/taskListReducer';
366
366
  import { getAllTasks, } from './view/taskManager/taskListView/taskListSelector';
367
367
  import { getDueDateValueFromDueDateGroupId, getTaskUpdates, } from './view/taskManager/taskListView/taskListViewHelpers';
@@ -430,15 +430,15 @@ export {
430
430
  BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, toExpenseAutomationJEScheduleMainTab, toExpenseAutomationJEScheduleSortKey, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, fetchExpenseAutomationMissingReceipts,
431
431
  // Bulk Upload Actions
432
432
  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, };
433
- export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
433
+ export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateTransactionFilters, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, TRANSACTION_FILTER_CATEGORIES, };
434
434
  export { TOP_EX_TIME_PERIODS };
435
435
  export { toTimeframeTick, mapTimePeriodtoTimeframeTick, toTimePeriod, toAbsoluteDay, toMonthYearPeriodId, convertToPeriod, };
436
436
  export { toVendorSpendTrendFilterTabsTypeStrict, } from './entity/vendorExpense/vendorExpenseSelector';
437
437
  export { getNumberOfPeriods };
438
438
  export { SCHEDULE_DAYS_OF_MONTH, toScheduleDaysOfMonth, toMonth, toMonthStrict, toQuarter, toQuarterStrict, };
439
439
  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, fetchSubscriptionSummaryForTenant, isTenantBankingOnly, isTenantCardsOnly, isTenantBookkeepingEnabled, isOtherProductsEnabledForTenant, };
440
- export { toAccountType, toAccountGroupType, getAccountGroupKey, };
441
- export { getClassById } from './entity/class/classSelector';
440
+ export { ALL_ACCOUNT_TYPES, toAccountType, getAllAccounts, getTransactionFilterAccountOptions, toAccountGroupType, getAccountGroupKey, };
441
+ export { getAllClasses, getClassById } from './entity/class/classSelector';
442
442
  export { getForecast };
443
443
  export { getUserName, getUserByUserId, getUsersByUserIds, getAllZeniUsersFromState, } from './entity/user/userSelector';
444
444
  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, };
@@ -460,7 +460,7 @@ export { fetchDashboard, getDashboard, updateTreasuryVideoClosed, };
460
460
  export { updateDashboardLayout };
461
461
  export { getPandLWithForecast, } from './view/profitAndLoss/pAndLWithForecast/pAndLWithForecastSelector';
462
462
  export { fetchProfitAndLoss, resetProfitAndLossNodeCollapseState, updateProfitAndLossUIState, getProfitAndLossReport, getPandLReportFetchState, fetchProfitAndLossForTimeframe, };
463
- export { fetchProfitAndLossClassesView, updateProfitAndLossClassesToFilterOut, resetProfitAndLossClassesNodeCollapseState, updateProfitAndLossClassesViewUIState, updateProfitAndLossAccountViewMode, updateClassViewLayout, getProfitAndLossClassesView, aggregateHorizontalDescendantBalances, getEmptyHorizontalSectionBalancesSlice, getProfitAndLossClassesHorizontalView, isPandLReportViewCalculatedSectionID, isPandLReportViewSectionID, HORIZONTAL_CLASS_TOTAL_BALANCE_ID, isHorizontalAccountReportData, };
463
+ export { fetchProfitAndLossClassesView, updateProfitAndLossClassesToFilterOut, resetProfitAndLossClassesNodeCollapseState, updateProfitAndLossClassesViewUIState, updateProfitAndLossAccountViewMode, updateClassViewLayout, getProfitAndLossClassesView, getEmptyHorizontalSectionBalancesSlice, getProfitAndLossClassesHorizontalView, isPandLReportViewCalculatedSectionID, isPandLReportViewSectionID, HORIZONTAL_CLASS_TOTAL_BALANCE_ID, isHorizontalAccountReportData, };
464
464
  export { clearProfitAndLossProjectView, fetchProfitAndLossForTimeframeProjectView, fetchProfitAndLossProjectView, resetProfitAndLossProjectNodeCollapseState, updateProjectViewAccountViewMode, updateProjectsToFilterOut, updateProfitAndLossProjectViewUIState, getProfitAndLossProjectView, };
465
465
  export { getAccountingProviderAttachment };
466
466
  export { fetchUserListByType, getUserList };
@@ -498,7 +498,7 @@ export { fetchIncomeTrend, fetchExpenseTrend, clearTrendData };
498
498
  export { getTrendForEntity, getCurrentFiscalQuarterDateRange };
499
499
  export { CustomerIncomeTrend };
500
500
  export { VendorExpenseTrend };
501
- export { toEntityType };
501
+ export { toEntityType, };
502
502
  export { fetchEntityAutoCompleteEpic };
503
503
  export { clearEntityAutoCompleteResults, clearAllEntityAutoCompleteResults, fetchEntityAutoCompleteResults, };
504
504
  export { getEntityAutoCompleteResults };
@@ -27,6 +27,10 @@ export const initialTransactionTabViewState = {
27
27
  totalCount: {},
28
28
  limit: 10,
29
29
  },
30
+ filters: {
31
+ categoryCombinationOperator: 'AND',
32
+ categories: [],
33
+ },
30
34
  fetchState: 'Not-Started',
31
35
  error: undefined,
32
36
  hasValidState() {
@@ -236,6 +240,12 @@ const expenseAutomationTransactionsView = createSlice({
236
240
  uiState.totalCount;
237
241
  }
238
242
  },
243
+ updateTransactionFilters(draft, action) {
244
+ const { selectedTab, filters } = action.payload;
245
+ if (filters != null) {
246
+ draft.transactionCategorizationView[selectedTab].filters = filters;
247
+ }
248
+ },
239
249
  saveTransactionCategorization: {
240
250
  prepare(selectedTab, transactionIds, cotTrackingByTransactionId, isUncategorizedExpenseCategoryEnabled) {
241
251
  return {
@@ -792,5 +802,5 @@ const expenseAutomationTransactionsView = createSlice({
792
802
  },
793
803
  },
794
804
  });
795
- export const { fetchTransactionCategorization, updateTransactionCategorizationUIState, 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;
805
+ 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;
796
806
  export default expenseAutomationTransactionsView.reducer;
@@ -4,13 +4,32 @@ import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
4
4
  import { getIsAccountingClassesEnabled, getCurrentTenant, } from '../../../entity/tenant/tenantSelector';
5
5
  import { getTransactionWithCOT } from '../../../entity/transaction/transactionHelper';
6
6
  import { getSupportedTransactionsByIds } from '../../../entity/transaction/transactionSelector';
7
+ import { applyAdvancedFiltersOnList, } from '../../spendManagement/spendManagementFilterHelpers';
7
8
  import { getAccountList, getNestedAccountListHierarchy, getUncategorizedAccounts, } from '../../accountList/accountListSelector';
8
9
  import { getClassList, getNestedClassListHierarchy, } from '../../classList/classListSelector';
9
10
  import { getAllSteps } from '../selectorTypes/expenseAutomationViewSelectorTypes';
11
+ export const toTransactionView = (transaction, transactionLocalData) => {
12
+ return {
13
+ id: transaction.id,
14
+ date: transaction.date,
15
+ amount: transaction.amount,
16
+ vendorName: transaction.vendorName,
17
+ customerName: transaction.customerName,
18
+ vendorId: transaction.vendorId,
19
+ customerId: transaction.customerId,
20
+ description: transaction.description,
21
+ memo: transaction.memo,
22
+ type: transaction.type,
23
+ typeName: transaction.typeName,
24
+ createTime: transaction.createTime,
25
+ transaction: transaction,
26
+ transactionLocalData,
27
+ };
28
+ };
10
29
  export function getExpenseAutomationTransactionView(state) {
11
30
  const { accountState, classState, classListState, accountListState, expenseAutomationTransactionsViewState, expenseAutomationViewState, transactionState, monthEndCloseChecksState, monthEndCloseChecksViewState, } = state;
12
31
  const { selectedTransactionCategorizationTab } = expenseAutomationTransactionsViewState;
13
- const { uiState, refreshStatus, saveStatus, markAsNotMiscategorizedStatus, transactionIdsBySelectedPeriod, transactionReviewLocalDataById, selectedCheckBoxTransactionIds, transactionIdsWithUnsavedData, uploadReceiptStatusById, selectedTransactionId, selectedTransactionLineId, } = expenseAutomationTransactionsViewState.transactionCategorizationView[selectedTransactionCategorizationTab];
32
+ const { uiState, refreshStatus, saveStatus, markAsNotMiscategorizedStatus, transactionIdsBySelectedPeriod, transactionReviewLocalDataById, selectedCheckBoxTransactionIds, transactionIdsWithUnsavedData, uploadReceiptStatusById, selectedTransactionId, selectedTransactionLineId, filters, } = expenseAutomationTransactionsViewState.transactionCategorizationView[selectedTransactionCategorizationTab];
14
33
  const uncategorizedIncomeExpense = getUncategorizedAccounts(accountState, accountListState, 'accountList');
15
34
  const accountList = getAccountList(accountState, accountListState, 'accountList');
16
35
  const classList = getClassList(classState, classListState);
@@ -27,10 +46,42 @@ export function getExpenseAutomationTransactionView(state) {
27
46
  ? transactionIdsBySelectedPeriod[monthYearPeriodId]
28
47
  : null;
29
48
  const transactionIds = transactionIdsForSelectedPeriod ?? [];
30
- const transactionLocalData = transactionIds
31
- .map((transactionId) => {
49
+ const transactions = getSupportedTransactionsByIds(transactionState, transactionIds);
50
+ const transactionsWithCOT = transactions.map((transaction) => getTransactionWithCOT(transaction));
51
+ const transactionLocalDataMap = new Map();
52
+ transactionIds.forEach((transactionId) => {
32
53
  const transactionData = transactionReviewLocalDataById[transactionId];
33
54
  if (transactionData != null) {
55
+ transactionLocalDataMap.set(transactionId, {
56
+ transactionId,
57
+ transactionReviewLocalData: transactionData.transactionReviewLocalData,
58
+ });
59
+ }
60
+ });
61
+ // Step 2: Convert to TransactionView and apply advanced filters
62
+ const transactionViews = transactionsWithCOT.map((transaction) => {
63
+ const localData = transactionLocalDataMap.get(transaction.id);
64
+ return toTransactionView(transaction, localData);
65
+ });
66
+ // Apply advanced filters if they exist
67
+ const filteredTransactionViews = applyAdvancedFiltersOnList('transaction_categorization', transactionViews, filters);
68
+ // Convert back to TransactionWithCOT for return
69
+ const filteredTransactionsWithCOT = filteredTransactionViews.map((view) => view.transaction);
70
+ // Get transactionLocalData for filtered transactions
71
+ // Also include transactionLocalData for transactions that don't exist in transactionState
72
+ // but have local data (to match original behavior)
73
+ const filteredTransactionIds = new Set(filteredTransactionViews.map((view) => view.id));
74
+ const filteredTransactionLocalData = transactionIds
75
+ .map((transactionId) => {
76
+ const transactionData = transactionReviewLocalDataById[transactionId];
77
+ if (transactionData == null) {
78
+ return null;
79
+ }
80
+ // Include if transaction is in filtered results, or if transaction doesn't exist in state
81
+ // (to maintain backward compatibility with tests)
82
+ const transactionExists = transactions.some((t) => t.id === transactionId);
83
+ if (filteredTransactionIds.has(transactionId) ||
84
+ !transactionExists) {
34
85
  return {
35
86
  transactionId,
36
87
  transactionReviewLocalData: transactionData.transactionReviewLocalData,
@@ -38,9 +89,7 @@ export function getExpenseAutomationTransactionView(state) {
38
89
  }
39
90
  return null;
40
91
  })
41
- .filter((transaction) => transaction != null);
42
- const transactions = getSupportedTransactionsByIds(transactionState, transactionIds);
43
- const transactionsWithCOT = transactions.map((transaction) => getTransactionWithCOT(transaction));
92
+ .filter((data) => data != null);
44
93
  const monthEndFetchState = monthYearPeriodId != null
45
94
  ? (monthEndCloseChecksViewState.monthEndCloseChecksViewByTenantId[currentTenant.tenantId]?.[monthYearPeriodId] ?? { fetchState: 'Not-Started', error: undefined })
46
95
  : { fetchState: 'Not-Started', error: undefined };
@@ -87,7 +136,7 @@ export function getExpenseAutomationTransactionView(state) {
87
136
  version: 0,
88
137
  fetchState: fetchStatus.fetchState,
89
138
  error: fetchStatus.error,
90
- transactions: transactionsWithCOT,
139
+ transactions: filteredTransactionsWithCOT,
91
140
  selectedCheckBoxTransactionIds,
92
141
  transactionIdsWithUnsavedData,
93
142
  uncategorizedAccounts: uncategorizedIncomeExpense,
@@ -96,7 +145,7 @@ export function getExpenseAutomationTransactionView(state) {
96
145
  classList: allClasses,
97
146
  accountsHierarchyList,
98
147
  classHierarchyList,
99
- transactionLocalData,
148
+ transactionLocalData: filteredTransactionLocalData,
100
149
  uiState,
101
150
  refreshStatus,
102
151
  saveStatus,
@@ -115,48 +115,6 @@ function buildHorizontalClassColumnBalancesSlice(report, classAmounts, totalAmou
115
115
  },
116
116
  };
117
117
  }
118
- /**
119
- * Sum balances across descendant accounts (recursive).
120
- *
121
- * Parent rows in the horizontal pivot only carry their own direct postings
122
- * (zero for "container" accounts), so callers rendering "Total {parent}" rows
123
- * must aggregate from descendants to get the real per-class totals.
124
- *
125
- * Returns one `COABalance` per class column + total (same shape as the
126
- * enriched `balancesInTimeframe.balances`), with `amount` summed and `type`
127
- * set to `default_with_null_balance` for zeros. Returns `[]` when no
128
- * descendants have enriched data.
129
- */
130
- export function aggregateHorizontalDescendantBalances(accounts, childIndices, childrenByParent) {
131
- let template;
132
- const sums = new Map();
133
- const walk = (idx) => {
134
- const childRow = accounts[idx];
135
- const childBalances = childRow?.accountReportData?.balancesInTimeframe.balances;
136
- if (childBalances != null) {
137
- if (template == null) {
138
- template = childBalances;
139
- }
140
- childBalances.forEach((b, i) => {
141
- sums.set(i, (sums.get(i) ?? 0) + (b.balance.amount ?? 0));
142
- });
143
- const grandChildren = childrenByParent[idx] ?? [];
144
- grandChildren.forEach(walk);
145
- }
146
- };
147
- childIndices.forEach(walk);
148
- if (template == null) {
149
- return [];
150
- }
151
- return template.map((tpl, i) => {
152
- const amount = sums.get(i) ?? 0;
153
- return {
154
- ...tpl,
155
- balance: { ...tpl.balance, amount },
156
- type: amount === 0 ? 'default_with_null_balance' : 'default',
157
- };
158
- });
159
- }
160
118
  /**
161
119
  * Parent index per DFS row — O(n). Matches the scan in the former
162
120
  * `findHorizontalAccountParentIndex` (depth &lt;= 2 rows have no parent).