@zeniai/client-epic-state 5.0.69-betaAR2 → 5.0.69-betaAR4

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 (63) hide show
  1. package/lib/entity/account/accountSelector.d.ts +0 -26
  2. package/lib/entity/account/accountSelector.js +1 -47
  3. package/lib/entity/account/accountState.d.ts +0 -5
  4. package/lib/entity/account/accountState.js +4 -11
  5. package/lib/entity/approvalRule/approvalRulePayload.d.ts +27 -5
  6. package/lib/entity/approvalRule/approvalRulePayload.js +131 -10
  7. package/lib/entity/approvalRule/approvalRuleSelector.d.ts +25 -1
  8. package/lib/entity/approvalRule/approvalRuleSelector.js +40 -0
  9. package/lib/entity/approvalRule/approvalRuleState.d.ts +48 -7
  10. package/lib/entity/class/classSelector.d.ts +0 -35
  11. package/lib/entity/class/classSelector.js +0 -50
  12. package/lib/esm/entity/account/accountSelector.js +1 -46
  13. package/lib/esm/entity/account/accountState.js +1 -7
  14. package/lib/esm/entity/approvalRule/approvalRulePayload.js +131 -10
  15. package/lib/esm/entity/approvalRule/approvalRuleSelector.js +35 -0
  16. package/lib/esm/entity/class/classSelector.js +0 -48
  17. package/lib/esm/index.js +6 -11
  18. package/lib/esm/view/companyHealthMetricView/companyHealthMetricViewSelector.js +1 -1
  19. package/lib/esm/view/companyView/helpers/cockpitHelpers.js +1 -1
  20. package/lib/esm/view/companyView/selector/companyManagementViewSelector.js +1 -1
  21. package/lib/esm/view/companyView/selector/companyPortfolioViewSelector.js +1 -1
  22. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +1 -11
  23. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +12 -69
  24. package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/epic/initializeBillPaySetupApproverViewUpdateDataEpic.js +11 -7
  25. package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +61 -16
  26. package/lib/esm/view/spendManagement/billPay/editBillView/editBillViewSelector.js +7 -2
  27. package/lib/esm/view/spendManagement/reimbursement/remiSetupApproverView/epic/initializeRemiSetupApproverViewUpdateDataEpic.js +11 -7
  28. package/lib/esm/view/spendManagement/spendManagementFilterHelpers.js +2 -4
  29. package/lib/esm/view/subscriptionView/subscriptionViewSelector.js +1 -1
  30. package/lib/esm/view/taskManager/taskListView/taskListReducer.js +1 -1
  31. package/lib/index.d.ts +8 -9
  32. package/lib/index.js +38 -41
  33. package/lib/view/companyHealthMetricView/companyHealthMetricViewSelector.js +1 -1
  34. package/lib/view/companyTaskManagerView/companyTaskManagerViewReducer.d.ts +2 -2
  35. package/lib/view/companyView/helpers/cockpitHelpers.js +1 -1
  36. package/lib/view/companyView/selector/companyManagementViewSelector.js +1 -1
  37. package/lib/view/companyView/selector/companyPortfolioViewSelector.js +1 -1
  38. package/lib/view/companyView/types/cockpitTypes.d.ts +2 -2
  39. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +1 -5
  40. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +2 -12
  41. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.d.ts +1 -4
  42. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +12 -71
  43. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +0 -2
  44. package/lib/view/people/peopleTypes.d.ts +1 -1
  45. package/lib/view/spendManagement/billPay/billList/billListState.d.ts +1 -1
  46. package/lib/view/spendManagement/billPay/billPaySetupApproverView/epic/initializeBillPaySetupApproverViewUpdateDataEpic.js +10 -6
  47. package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.d.ts +9 -1
  48. package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +61 -16
  49. package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonState.d.ts +31 -5
  50. package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.js +7 -2
  51. package/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardList.d.ts +1 -1
  52. package/lib/view/spendManagement/chargeCards/chargeCardPaymentHistory/chargeCardPaymentHistory.d.ts +1 -1
  53. package/lib/view/spendManagement/reimbursement/remiListView/remiListState.d.ts +1 -1
  54. package/lib/view/spendManagement/reimbursement/remiSetupApproverView/epic/initializeRemiSetupApproverViewUpdateDataEpic.js +10 -6
  55. package/lib/view/spendManagement/spendManagementFilterHelpers.d.ts +1 -1
  56. package/lib/view/spendManagement/spendManagementFilterHelpers.js +2 -4
  57. package/lib/view/subscriptionView/subscriptionViewSelector.js +1 -1
  58. package/lib/view/taskManager/taskListView/taskList.d.ts +4 -4
  59. package/lib/view/taskManager/taskListView/taskListReducer.js +1 -1
  60. package/package.json +1 -1
  61. package/lib/esm/view/expenseAutomationView/transactionFilterHelpers.js +0 -228
  62. package/lib/view/expenseAutomationView/transactionFilterHelpers.d.ts +0 -65
  63. package/lib/view/expenseAutomationView/transactionFilterHelpers.js +0 -232
@@ -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',
@@ -14,18 +14,139 @@ export const toApprovalRule = (payload) => ({
14
14
  version: payload.version,
15
15
  criteria: toApprovalCriteria(payload.criteria),
16
16
  steps: toApprovalSteps(payload.steps),
17
+ description: payload.description ?? undefined,
18
+ priority: payload.priority,
19
+ isFallback: payload.is_fallback ?? false,
20
+ // separationOfDuties: backend doesn't ship this field yet; left undefined
21
+ // until the spec is finalized.
22
+ areApprovalsSerialized: payload.are_approvals_serialized,
23
+ pendingApprovalsCount: payload.pending_approvals_count,
24
+ pendingEntityApprovalUpdateStatus: payload.pending_entity_approval_update_status,
17
25
  });
26
+ /**
27
+ * Maps the wire-level criteria block into the state-side discriminated
28
+ * `Criteria[]` union.
29
+ *
30
+ * The wire keeps each condition as a flat row inside `conditions[]`.
31
+ * Amount comparisons can show up as a `gte` only, a `lte` only, or a
32
+ * `gte` + `lte` pair — those collapse into a single AmountCriteria whose
33
+ * `comparator` is `greater_than`, `less_than`, or `range` respectively.
34
+ *
35
+ * Vendor and department conditions map one-to-one: `in` becomes `is`,
36
+ * `not_in` becomes `is_not`.
37
+ *
38
+ * Resilient to two forms of upstream drift:
39
+ * - Missing / null criteria → returns [].
40
+ * - Legacy criteria shape (array of amount-range objects, the pre-3.0
41
+ * wire) → converted to an AmountCriteria so existing rules in production
42
+ * still render while the backend rolls out.
43
+ */
18
44
  const toApprovalCriteria = (payload) => {
19
- return payload.map((criteria) => ({
20
- rangeType: criteria.type,
21
- rangeEntity: criteria.range_entity,
22
- range: {
23
- min: toAmount(criteria.min, criteria.currency_code, criteria.currency_symbol),
24
- max: criteria.max != null
25
- ? toAmount(criteria.max, criteria.currency_code, criteria.currency_symbol)
26
- : undefined,
27
- },
28
- }));
45
+ if (payload == null) {
46
+ return [];
47
+ }
48
+ if (Array.isArray(payload)) {
49
+ // Legacy pre-3.0 wire: an array of amount-range entries.
50
+ return legacyAmountRangeToCriteria(payload);
51
+ }
52
+ if (!Array.isArray(payload.conditions)) {
53
+ return [];
54
+ }
55
+ const results = [];
56
+ const amountCriteria = toAmountCriteria(payload);
57
+ if (amountCriteria != null) {
58
+ results.push(amountCriteria);
59
+ }
60
+ payload.conditions
61
+ .filter((condition) => condition.field === 'vendor_id')
62
+ .forEach((condition) => {
63
+ const vendor = toVendorCriteria(condition);
64
+ if (vendor != null) {
65
+ results.push(vendor);
66
+ }
67
+ });
68
+ payload.conditions
69
+ .filter((condition) => condition.field === 'department_id')
70
+ .forEach((condition) => {
71
+ const department = toDepartmentCriteria(condition);
72
+ if (department != null) {
73
+ results.push(department);
74
+ }
75
+ });
76
+ return results;
77
+ };
78
+ const legacyAmountRangeToCriteria = (legacy) => {
79
+ if (legacy.length === 0) {
80
+ return [];
81
+ }
82
+ const first = legacy[0] ?? {};
83
+ const currency = first.currency_code ?? 'USD';
84
+ const symbol = first.currency_symbol ?? '$';
85
+ const min = typeof first.min === 'number'
86
+ ? toAmount(first.min, currency, symbol)
87
+ : undefined;
88
+ const max = typeof first.max === 'number'
89
+ ? toAmount(first.max, currency, symbol)
90
+ : undefined;
91
+ if (min == null && max == null) {
92
+ return [];
93
+ }
94
+ const comparator = min != null && max != null
95
+ ? 'range'
96
+ : min != null
97
+ ? 'greater_than'
98
+ : 'less_than';
99
+ return [{ type: 'amount', comparator, min, max }];
100
+ };
101
+ const toAmountCriteria = (payload) => {
102
+ if (!Array.isArray(payload.conditions)) {
103
+ return undefined;
104
+ }
105
+ const amountConditions = payload.conditions.filter((condition) => condition.field === 'amount');
106
+ const gteCondition = amountConditions.find((condition) => condition.type === 'gte' || condition.type === 'eq');
107
+ const lteCondition = amountConditions.find((condition) => condition.type === 'lte');
108
+ if (gteCondition == null && lteCondition == null) {
109
+ return undefined;
110
+ }
111
+ const currencyCode = payload.currency_code ?? 'USD';
112
+ const currencySymbol = payload.currency_symbol ?? '$';
113
+ const min = typeof gteCondition?.value === 'number'
114
+ ? toAmount(gteCondition.value, currencyCode, currencySymbol)
115
+ : undefined;
116
+ const max = typeof lteCondition?.value === 'number'
117
+ ? toAmount(lteCondition.value, currencyCode, currencySymbol)
118
+ : undefined;
119
+ let comparator;
120
+ if (min != null && max != null) {
121
+ comparator = 'range';
122
+ }
123
+ else if (min != null) {
124
+ comparator = 'greater_than';
125
+ }
126
+ else {
127
+ comparator = 'less_than';
128
+ }
129
+ return { type: 'amount', comparator, min, max };
130
+ };
131
+ const toVendorCriteria = (condition) => {
132
+ if (!Array.isArray(condition.value)) {
133
+ return undefined;
134
+ }
135
+ return {
136
+ type: 'vendor',
137
+ operator: condition.type === 'not_in' ? 'is_not' : 'is',
138
+ vendorIds: condition.value,
139
+ };
140
+ };
141
+ const toDepartmentCriteria = (condition) => {
142
+ if (!Array.isArray(condition.value)) {
143
+ return undefined;
144
+ }
145
+ return {
146
+ type: 'department',
147
+ operator: condition.type === 'not_in' ? 'is_not' : 'is',
148
+ departmentIds: condition.value,
149
+ };
29
150
  };
30
151
  const toApprovalSteps = (payload) => {
31
152
  return payload.map((step) => ({
@@ -7,3 +7,38 @@ export function getApprovalRulesByIds(approvalRuleState, approvalRuleIds) {
7
7
  .filter((value) => value != null);
8
8
  return approvalRulesByIds;
9
9
  }
10
+ /**
11
+ * Returns the amount-range portion of a rule's criteria, if any.
12
+ *
13
+ * Use this whenever a caller needs to read amount min/max from the new
14
+ * discriminated `Criteria` union without inlining a type guard.
15
+ */
16
+ export function getAmountCriteria(criteria) {
17
+ return criteria.find((c) => c.type === 'amount');
18
+ }
19
+ export function getVendorCriteria(criteria) {
20
+ return criteria.find((c) => c.type === 'vendor');
21
+ }
22
+ export function getDepartmentCriteria(criteria) {
23
+ return criteria.find((c) => c.type === 'department');
24
+ }
25
+ /**
26
+ * Returns all rules of the given entityType, sorted by `priority` ascending.
27
+ *
28
+ * Rules without a `priority` value sort to the end (treated as Infinity).
29
+ * Use this for the list page where rules render in evaluation order.
30
+ */
31
+ export function getApprovalRulesByEntityType(approvalRuleState, entityType) {
32
+ return Object.values(approvalRuleState.approvalRuleById)
33
+ .filter((rule) => rule.entityType === entityType)
34
+ .sort((a, b) => (a.priority ?? Infinity) - (b.priority ?? Infinity));
35
+ }
36
+ /**
37
+ * Returns the tenant's fallback rule for the given entityType, if one exists.
38
+ *
39
+ * The fallback rule is shown by the "fallback engine active" banner on the
40
+ * list page and is used to handle bills/reimbursements that match no other rule.
41
+ */
42
+ export function getFallbackApprovalRule(approvalRuleState, entityType) {
43
+ return Object.values(approvalRuleState.approvalRuleById).find((rule) => rule.entityType === entityType && rule.isFallback === true);
44
+ }
@@ -1,4 +1,3 @@
1
- import { createSelector } from '@reduxjs/toolkit';
2
1
  import recordGet from 'lodash/get';
3
2
  import { getCOABalances } from '../../commonStateTypes/coaBalance/coaBalance';
4
3
  import { getAccount } from '../account/accountSelector';
@@ -51,50 +50,3 @@ export function getClassReport(classState, accountState, id, filter) {
51
50
  accounts: accountReport,
52
51
  };
53
52
  }
54
- /**
55
- * Returns all classes currently in state (single pass over classesByKey).
56
- * Use for dropdowns that need class names; map to { classId, className } as needed.
57
- */
58
- export function getAllClasses(classState) {
59
- return Object.values(classState.classesByKey);
60
- }
61
- /**
62
- * Memoised projection of `getAllClasses` to the `{classId, className}` shape
63
- * expected by filter dropdowns. Consumers should prefer this over inlining a
64
- * `getAllClasses(...).map(...)` inside `useSelector`: the inline map allocates
65
- * a fresh array on every Redux dispatch, breaking `useSelector`'s
66
- * reference-equality optimisation and triggering re-renders on every state
67
- * change unrelated to class data.
68
- *
69
- * Two cleanups happen here, intentionally inside the selector so every
70
- * consumer benefits uniformly:
71
- * 1. **Drop entries with a blank `className`.** Soft-deleted classes can
72
- * retain their classId in state while the human name is blanked, which
73
- * would otherwise render as an empty row in the filter dropdown.
74
- * 2. **Dedupe by `classId`.** `classesByKey` is keyed by
75
- * `${classId}-${reportId}` (see `getClassKey`), so a class loaded under
76
- * multiple report contexts appears as multiple entries from
77
- * `Object.values(classesByKey)`. The first non-blank entry per
78
- * `classId` wins.
79
- */
80
- export const getClassFilterOptions = createSelector(
81
- // Key the memo on the underlying `classesByKey` record rather than on
82
- // `getAllClasses` output: the latter returns a fresh `Object.values(...)`
83
- // array on every call, which would defeat reselect's reference-equality
84
- // check and re-run the projection on every dispatch.
85
- [(classState) => classState.classesByKey], (classesByKey) => {
86
- const classes = Object.values(classesByKey);
87
- const seenClassIds = new Set();
88
- const options = [];
89
- for (const c of classes) {
90
- if (c.classId == null || seenClassIds.has(c.classId)) {
91
- continue;
92
- }
93
- if (c.className == null || c.className.trim() === '') {
94
- continue;
95
- }
96
- seenClassIds.add(c.classId);
97
- options.push({ classId: c.classId, className: c.className });
98
- }
99
- return options;
100
- });
package/lib/esm/index.js CHANGED
@@ -24,7 +24,6 @@ import { mapTimePeriodtoTimeframeTick, toTimePeriod, toTimeframeTick, } from './
24
24
  import { isAgingReport, isCashFlowOrBalanceSheetReport, isDashboardClassesViewReport, isDashboardReport, isFluxAnalysisOpExReport, isOpExByVendorReport, isPAndLClassesViewReport, isPAndLProjectViewReport, isPAndLReport, } from './commonStateTypes/viewAndReport/reportIDHelper';
25
25
  import { toReportFormatStrict, toReportID, } from './commonStateTypes/viewAndReport/viewAndReport';
26
26
  import { PAYMENT_BUSINESS_DAYS, filterDays, getNextNthWorkingDay, getPreviousNthWorkingDay, getYearsList, holidaysFormatted, isHoliday, isHolidayToday, } from './commonStateTypes/workingDayHelper';
27
- import { getAllAccounts, getTransactionFilterAccountOptions, } from './entity/account/accountSelector';
28
27
  import { toAccountType, toReconciliationAccountSource, } from './entity/account/accountState';
29
28
  import { getAccountGroupKey, toAccountGroupType, } from './entity/accountGroup/accountGroupState';
30
29
  /**
@@ -33,6 +32,7 @@ import { getAccountGroupKey, toAccountGroupType, } from './entity/accountGroup/a
33
32
  import { getAccountReconByAccountIdAndSelectedPeriod, } from './entity/accountRecon/accountReconSelector';
34
33
  import { getAddressByAddressId } from './entity/address/addressSelector';
35
34
  import { toAttributeOrRoleTypeStrict, toAttributeTypeStrict, toRoleTypeStrict, } from './entity/approvalRule/approvalRuleState';
35
+ import { getAmountCriteria, getApprovalRulesByEntityType, getDepartmentCriteria, getFallbackApprovalRule, getVendorCriteria, } from './entity/approvalRule/approvalRuleSelector';
36
36
  import { toOutsideZeniPaymentModeType, } from './entity/billPay/billTransaction/billTransactionState';
37
37
  import { toRecurringBillFrequency, toRecurringBillFrequencyStrict, } from './entity/billPay/recurringBills/recurringBillsState';
38
38
  import { toCardAddressType, toCardType, toCreditLimitFrequencyCodeType, toShippingAddressType, } from './entity/chargeCard/chargeCard';
@@ -169,7 +169,7 @@ import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFl
169
169
  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';
170
170
  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';
171
171
  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';
172
- import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markTransactionAsNotMiscategorized, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, updateTransactionFilters, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
172
+ import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markTransactionAsNotMiscategorized, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
173
173
  import { getExpenseAutomationFluxAnalysisView } from './view/expenseAutomationView/selectors/fluxAnalysisViewSelector';
174
174
  import { getExpenseAutomationReconciliationView, isAccountReconReport, } from './view/expenseAutomationView/selectors/reconciliationViewSelector';
175
175
  import { getExpenseAutomationTransactionView } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
@@ -337,7 +337,6 @@ import { getRemiBusinessVerificationDetails, getRemiSetupViewDetails, } from './
337
337
  import { approveOrRejectRemisBulkAction, autoReviewPendingApprovalRemis, cancelOrDeleteRemisBulkAction, clearAllRemisFromBulkActionList, clearRemiBulkActionView, incrementRemiBulkActionProcessedCount, removeRemiFromBulkActionList, reviewDraftRemisBulkAction, submitDraftRemisBulkAction, updateRemisBulkActionList, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewReducer';
338
338
  import { getRemisBulkOperationProgress, getRemisBulkReviewView, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewSelector';
339
339
  import { hideCreatedByFilter, } from './view/spendManagement/spendManagementFilterHelpers';
340
- import { TRANSACTION_FILTER_CATEGORIES, applyTransactionFilters, } from './view/expenseAutomationView/transactionFilterHelpers';
341
340
  import { acceptTreasuryTerms, clearTreasurySetupView, fetchPortfolioAllocation, fetchTreasuryFunds, fetchTreasurySetupView, updateFundAllocationLocalData, updatePortfolioAllocation, updateTreasuryVideoViewed, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewReducer';
342
341
  import { getTreasuryBusinessVerificationDetails, getTreasurySetupViewDetails, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewSelector';
343
342
  import { getTreasuryFundsMaximumYield, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewState';
@@ -450,15 +449,15 @@ export {
450
449
  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,
451
450
  // Bulk Upload Actions
452
451
  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, };
453
- export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateTransactionFilters, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
452
+ export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateSelectedCheckboxTransactionIds, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
454
453
  export { TOP_EX_TIME_PERIODS };
455
454
  export { toTimeframeTick, mapTimePeriodtoTimeframeTick, toTimePeriod, toAbsoluteDay, toMonthYearPeriodId, convertToPeriod, };
456
455
  export { toVendorSpendTrendFilterTabsTypeStrict, } from './entity/vendorExpense/vendorExpenseSelector';
457
456
  export { getNumberOfPeriods };
458
457
  export { SCHEDULE_DAYS_OF_MONTH, toScheduleDaysOfMonth, toMonth, toMonthStrict, toQuarter, toQuarterStrict, };
459
458
  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, };
460
- export { toAccountType, toAccountGroupType, getAccountGroupKey, getAllAccounts, getTransactionFilterAccountOptions, };
461
- export { getAllClasses, getClassById, getClassFilterOptions, } from './entity/class/classSelector';
459
+ export { toAccountType, toAccountGroupType, getAccountGroupKey, };
460
+ export { getClassById } from './entity/class/classSelector';
462
461
  export { getForecast };
463
462
  export { getUserName, getUserByUserId, getUsersByUserIds, getAllZeniUsersFromState, } from './entity/user/userSelector';
464
463
  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, };
@@ -558,10 +557,6 @@ export { toRemiSubTabType, toRemiSubTabTypeStrict, toRemiTabType, toRemiTabTypeS
558
557
  export { getClassList, fetchClassList, getProjectList, fetchProjectList, };
559
558
  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, };
560
559
  export { hideCreatedByFilter, };
561
- // Transaction Categorization filter API — lives under Expense Automation,
562
- // not Spend Management. Kept in a separate re-export block to make the
563
- // separation visible at the barrel level.
564
- export { TRANSACTION_FILTER_CATEGORIES, applyTransactionFilters, };
565
560
  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, };
566
561
  export { getApprovalRuleViewDetails, getBankConnectionsSetupViewDetails, getIntegrationsView, };
567
562
  export { fetchUserFinancialAccount };
@@ -569,7 +564,7 @@ export { getUserFinancialAccount };
569
564
  export { fetchRemiSetupView, updateMileageDetails, saveRemiSetupViewDataInLocalStore, acceptRemiTerms, acceptEmployeeRemiTerms, clearRemiSetupView, getRemiSetupViewDetails, getRemiBusinessVerificationDetails, };
570
565
  export { VERIFIED_PAYMENT_ACCOUNT_PROVIDER_VERIFICATION_STATUS, };
571
566
  export { isSuccessResponse, isInvalidSessionError, isAccessDeniedError, };
572
- export { toAttributeTypeStrict, toAttributeOrRoleTypeStrict, toRoleTypeStrict, };
567
+ export { getAmountCriteria, getApprovalRulesByEntityType, getDepartmentCriteria, getFallbackApprovalRule, getVendorCriteria, toAttributeTypeStrict, toAttributeOrRoleTypeStrict, toRoleTypeStrict, };
573
568
  export { getBillPaySetupApproverView, getBillPaySetupApproverUpdateDataView, fetchBillPaySetupApproverView, fetchBillPayApproversDetails, fetchBillPayApproversList, deleteBillPayApprovalRule, saveBillPaySetupApproverViewUpdateData, saveBillPaySetupApproverViewUpdates, setBillsSetupApproverViewListeningToPusherEvent, initializeBillPaySetupApproverViewUpdateData, clearBillPaySetupApproverViewUpdateData, clearBillPaySetupApproverView, };
574
569
  export { getRemiSetupApproverView, getRemiSetupApproverUpdateDataView, fetchRemiSetupApproverView, fetchRemiApproversList, fetchRemiApproversDetails, deleteRemiApprovalRule, saveRemiSetupApproverViewUpdateData, saveRemiSetupApproverViewUpdates, initializeRemiSetupApproverViewUpdateData, setRemiSetupApproverViewListeningToPusherEvent, clearRemiSetupApproverViewUpdateData, clearRemiSetupApproverView, };
575
570
  export { getRemiDetailView, checkApproveRejectBtnShowForRemi, };
@@ -291,7 +291,7 @@ const applyAdvancedFiltersOnCompaniesList = (allCompanies, filters, filteredComp
291
291
  const key = currentFilter.field;
292
292
  const categoryValue = getCategoryValueForCompany(key, company);
293
293
  if (categoryValue == null) {
294
- if (currentFilter.matchingOperator === 'not_equal') {
294
+ if (currentFilter.matchingOperator === 'not-equal') {
295
295
  return true;
296
296
  }
297
297
  return false;
@@ -48,7 +48,7 @@ export const filterCompanyOnCategoriesWithSingleValue = (categoryValue, currentF
48
48
  return filterCompanyOnRangeCategoryType(categoryValue, currentFilter);
49
49
  }
50
50
  // if filter category is not annualRecurringRevenue OR monthlyRecurringRevenue
51
- if (currentFilter.matchingOperator === 'not_equal') {
51
+ if (currentFilter.matchingOperator === 'not-equal') {
52
52
  return currentFilter.values.indexOf(categoryValue) === -1;
53
53
  }
54
54
  return currentFilter.values.indexOf(categoryValue) > -1;
@@ -150,7 +150,7 @@ const applyAdvancedFiltersOnCompaniesList = (allCompanies, filters, filteredComp
150
150
  const key = currentFilter.field;
151
151
  const categoryValue = getCategoryValueForCompany(key, company);
152
152
  if (categoryValue == null) {
153
- if (currentFilter.matchingOperator === 'not_equal') {
153
+ if (currentFilter.matchingOperator === 'not-equal') {
154
154
  return true;
155
155
  }
156
156
  return false;
@@ -116,7 +116,7 @@ const applyAdvancedFiltersOnCompaniesList = (allCompanies, filters, filteredComp
116
116
  const key = currentFilter.field;
117
117
  const categoryValue = getCategoryValueForCompany(key, company);
118
118
  if (categoryValue == null) {
119
- if (currentFilter.matchingOperator === 'not_equal') {
119
+ if (currentFilter.matchingOperator === 'not-equal') {
120
120
  return true;
121
121
  }
122
122
  return false;
@@ -28,10 +28,6 @@ export const initialTransactionTabViewState = {
28
28
  totalCount: {},
29
29
  limit: 10,
30
30
  },
31
- filters: {
32
- categoryCombinationOperator: 'AND',
33
- categories: [],
34
- },
35
31
  fetchState: 'Not-Started',
36
32
  error: undefined,
37
33
  hasValidState() {
@@ -303,12 +299,6 @@ const expenseAutomationTransactionsView = createSlice({
303
299
  uiState.totalCount;
304
300
  }
305
301
  },
306
- updateTransactionFilters(draft, action) {
307
- const { selectedTab, filters } = action.payload;
308
- if (filters != null) {
309
- draft.transactionCategorizationView[selectedTab].filters = filters;
310
- }
311
- },
312
302
  saveTransactionCategorization: {
313
303
  prepare(selectedTab, transactionIds, cotTrackingByTransactionId, isUncategorizedExpenseCategoryEnabled) {
314
304
  return {
@@ -939,5 +929,5 @@ const expenseAutomationTransactionsView = createSlice({
939
929
  },
940
930
  },
941
931
  });
942
- export const { fetchTransactionCategorization, updateTransactionCategorizationUIState, updateTransactionFilters, 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;
932
+ 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;
943
933
  export default expenseAutomationTransactionsView.reducer;
@@ -4,33 +4,14 @@ import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
4
4
  import { getCurrentTenant, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, } from '../../../entity/tenant/tenantSelector';
5
5
  import { getTransactionWithCOT } from '../../../entity/transaction/transactionHelper';
6
6
  import { getSupportedTransactionsByIds } from '../../../entity/transaction/transactionSelector';
7
- import { applyTransactionFilters, } from '../transactionFilterHelpers';
8
7
  import { getAccountList, getNestedAccountListHierarchy, getUncategorizedAccounts, } from '../../accountList/accountListSelector';
9
8
  import { getClassList, getNestedClassListHierarchy, } from '../../classList/classListSelector';
10
9
  import { getProjectList } from '../../projectList/projectListSelector';
11
10
  import { getAllSteps } from '../selectorTypes/expenseAutomationViewSelectorTypes';
12
- export const toTransactionView = (transaction, transactionLocalData) => {
13
- return {
14
- id: transaction.id,
15
- date: transaction.date,
16
- amount: transaction.amount,
17
- vendorName: transaction.vendorName,
18
- customerName: transaction.customerName,
19
- vendorId: transaction.vendorId,
20
- customerId: transaction.customerId,
21
- description: transaction.description,
22
- memo: transaction.memo,
23
- type: transaction.type,
24
- typeName: transaction.typeName,
25
- createTime: transaction.createTime,
26
- transaction: transaction,
27
- transactionLocalData,
28
- };
29
- };
30
11
  export function getExpenseAutomationTransactionView(state) {
31
12
  const { accountState, classState, classListState, accountListState, expenseAutomationTransactionsViewState, expenseAutomationViewState, projectState, projectListState, transactionState, monthEndCloseChecksState, monthEndCloseChecksViewState, } = state;
32
13
  const { selectedTransactionCategorizationCompletedSubTab, selectedTransactionCategorizationTab, } = expenseAutomationTransactionsViewState;
33
- const { uiState, refreshStatus, saveStatus, markAsNotMiscategorizedStatus, transactionIdsBySelectedPeriod, transactionReviewLocalDataById, selectedCheckBoxTransactionIds, transactionIdsWithUnsavedData, uploadReceiptStatusById, selectedTransactionId, selectedTransactionLineId, filters, } = expenseAutomationTransactionsViewState.transactionCategorizationView[selectedTransactionCategorizationTab];
14
+ const { uiState, refreshStatus, saveStatus, markAsNotMiscategorizedStatus, transactionIdsBySelectedPeriod, transactionReviewLocalDataById, selectedCheckBoxTransactionIds, transactionIdsWithUnsavedData, uploadReceiptStatusById, selectedTransactionId, selectedTransactionLineId, } = expenseAutomationTransactionsViewState.transactionCategorizationView[selectedTransactionCategorizationTab];
34
15
  const uncategorizedIncomeExpense = getUncategorizedAccounts(accountState, accountListState, 'accountList');
35
16
  const accountList = getAccountList(accountState, accountListState, 'accountList');
36
17
  const classList = getClassList(classState, classListState);
@@ -49,58 +30,20 @@ export function getExpenseAutomationTransactionView(state) {
49
30
  ? transactionIdsBySelectedPeriod[monthYearPeriodId]
50
31
  : null;
51
32
  const transactionIds = transactionIdsForSelectedPeriod ?? [];
52
- const transactions = getSupportedTransactionsByIds(transactionState, transactionIds);
53
- const transactionsWithCOT = transactions.map((transaction) => getTransactionWithCOT(transaction));
54
- const transactionLocalDataMap = new Map();
55
- transactionIds.forEach((transactionId) => {
33
+ const transactionLocalData = transactionIds
34
+ .map((transactionId) => {
56
35
  const transactionData = transactionReviewLocalDataById[transactionId];
57
36
  if (transactionData != null) {
58
- transactionLocalDataMap.set(transactionId, {
37
+ return {
59
38
  transactionId,
60
39
  transactionReviewLocalData: transactionData.transactionReviewLocalData,
61
- });
62
- }
63
- });
64
- // Step 2: Convert to TransactionView and apply advanced filters
65
- const transactionViews = transactionsWithCOT.map((transaction) => {
66
- const localData = transactionLocalDataMap.get(transaction.id);
67
- return toTransactionView(transaction, localData);
68
- });
69
- // Apply TC-specific filters (lives under expenseAutomationView, independent
70
- // of the Spend Management filter pipeline).
71
- const filteredTransactionViews = applyTransactionFilters(transactionViews, filters);
72
- // Convert back to TransactionWithCOT for return
73
- const filteredTransactionsWithCOT = filteredTransactionViews.map((view) => view.transaction);
74
- // Get transactionLocalData for filtered transactions
75
- // Also include transactionLocalData for transactions that don't exist in transactionState
76
- // but have local data (to match original behavior)
77
- const filteredTransactionIds = new Set(filteredTransactionViews.map((view) => view.id));
78
- // Pre-compute the membership set once. The previous implementation called
79
- // `transactions.some(t => t.id === transactionId)` inside the per-id loop,
80
- // turning the pipeline into O(n × m) — measurable on tenants with large
81
- // transaction lists since this selector runs on every Redux dispatch.
82
- const transactionExistsById = new Set(transactions.map((t) => t.id));
83
- // `.flatMap` returns `X[]` directly when the callback returns `[]` for the
84
- // skip case, so we don't need the trailing `.filter((d): d is X => …)` type
85
- // predicate that the previous `map → filter` pipeline required.
86
- const filteredTransactionLocalData = transactionIds.flatMap((transactionId) => {
87
- const transactionData = transactionReviewLocalDataById[transactionId];
88
- if (transactionData == null) {
89
- return [];
40
+ };
90
41
  }
91
- // Include if transaction is in filtered results, or if transaction doesn't exist in state
92
- // (to maintain backward compatibility with tests)
93
- const transactionExists = transactionExistsById.has(transactionId);
94
- if (filteredTransactionIds.has(transactionId) || !transactionExists) {
95
- return [
96
- {
97
- transactionId,
98
- transactionReviewLocalData: transactionData.transactionReviewLocalData,
99
- },
100
- ];
101
- }
102
- return [];
103
- });
42
+ return null;
43
+ })
44
+ .filter((transaction) => transaction != null);
45
+ const transactions = getSupportedTransactionsByIds(transactionState, transactionIds);
46
+ const transactionsWithCOT = transactions.map((transaction) => getTransactionWithCOT(transaction));
104
47
  const monthEndFetchState = monthYearPeriodId != null
105
48
  ? (monthEndCloseChecksViewState.monthEndCloseChecksViewByTenantId[currentTenant.tenantId]?.[monthYearPeriodId] ?? { fetchState: 'Not-Started', error: undefined })
106
49
  : { fetchState: 'Not-Started', error: undefined };
@@ -164,7 +107,7 @@ export function getExpenseAutomationTransactionView(state) {
164
107
  version: 0,
165
108
  fetchState: fetchStatus.fetchState,
166
109
  error: fetchStatus.error,
167
- transactions: filteredTransactionsWithCOT,
110
+ transactions: transactionsWithCOT,
168
111
  selectedCheckBoxTransactionIds,
169
112
  transactionIdsWithUnsavedData,
170
113
  uncategorizedAccounts: uncategorizedIncomeExpense,
@@ -175,7 +118,7 @@ export function getExpenseAutomationTransactionView(state) {
175
118
  classHierarchyList,
176
119
  isAccountingProjectsEnabled,
177
120
  projectList,
178
- transactionLocalData: filteredTransactionLocalData,
121
+ transactionLocalData,
179
122
  uiState,
180
123
  refreshStatus,
181
124
  saveStatus,
@@ -1,6 +1,6 @@
1
1
  import { from } from 'rxjs';
2
2
  import { filter, mergeMap } from 'rxjs/operators';
3
- import { getApprovalRuleById } from '../../../../../entity/approvalRule/approvalRuleSelector';
3
+ import { getAmountCriteria, getApprovalRuleById, getDepartmentCriteria, getVendorCriteria, } from '../../../../../entity/approvalRule/approvalRuleSelector';
4
4
  import { clearBillPaySetupApproverViewUpdateData, initializeBillPaySetupApproverViewUpdateData, saveBillPaySetupApproverViewUpdateData, } from '../billPaySetupApproverViewReducer';
5
5
  export const initializeBillPaySetupApproverViewUpdateDataEpic = (actions$, state$) => actions$.pipe(filter(initializeBillPaySetupApproverViewUpdateData.match), mergeMap((action) => {
6
6
  const { approvalRuleId } = action.payload;
@@ -8,16 +8,20 @@ export const initializeBillPaySetupApproverViewUpdateDataEpic = (actions$, state
8
8
  if (approvalRuleId != null) {
9
9
  const approvalRule = getApprovalRuleById(state$.value.approvalRuleState, approvalRuleId);
10
10
  if (approvalRule != null) {
11
- const criteria = approvalRule.criteria[0];
12
- const range = criteria?.range;
13
11
  const billPaySetupApproverViewUpdateData = {
14
12
  approvalRuleId,
15
13
  steps: approvalRule.steps,
16
14
  criteria: {
17
- rangeType: criteria?.rangeType,
18
- rangeEntity: criteria?.rangeEntity,
19
- range,
15
+ amount: getAmountCriteria(approvalRule.criteria),
16
+ vendor: getVendorCriteria(approvalRule.criteria),
17
+ department: getDepartmentCriteria(approvalRule.criteria),
20
18
  },
19
+ // Approval Rules 3.0 — seed rule-level fields so the form can
20
+ // round-trip them on edit. Each may be undefined on legacy rules.
21
+ name: approvalRule.name,
22
+ description: approvalRule.description,
23
+ separationOfDuties: approvalRule.separationOfDuties,
24
+ isFallback: approvalRule.isFallback,
21
25
  };
22
26
  fetchActions.push(clearBillPaySetupApproverViewUpdateData(), saveBillPaySetupApproverViewUpdateData(billPaySetupApproverViewUpdateData));
23
27
  }
@@ -25,7 +29,7 @@ export const initializeBillPaySetupApproverViewUpdateDataEpic = (actions$, state
25
29
  else {
26
30
  const billPaySetupApproverViewCreateData = {
27
31
  steps: [],
28
- criteria: undefined,
32
+ criteria: {},
29
33
  };
30
34
  fetchActions.push(clearBillPaySetupApproverViewUpdateData(), saveBillPaySetupApproverViewUpdateData(billPaySetupApproverViewCreateData));
31
35
  }