@zeniai/client-epic-state 5.0.81-betaJK7 → 5.0.81-betaML3

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 (94) hide show
  1. package/lib/commonStateTypes/viewAndReport/viewAndReport.d.ts +2 -2
  2. package/lib/commonStateTypes/viewAndReport/viewAndReport.js +2 -0
  3. package/lib/entity/account/accountSelector.d.ts +9 -0
  4. package/lib/entity/account/accountSelector.js +14 -1
  5. package/lib/entity/account/accountState.d.ts +1 -1
  6. package/lib/entity/accountGroup/accountGroupState.d.ts +1 -1
  7. package/lib/entity/class/classReducer.d.ts +4 -4
  8. package/lib/entity/class/classState.d.ts +1 -1
  9. package/lib/entity/forecast/forecastState.d.ts +1 -1
  10. package/lib/entity/sectionAccountsView/sectionAccountsView.d.ts +1 -1
  11. package/lib/entity/sectionClassesViewV2/sectionClassesView.d.ts +1 -1
  12. package/lib/entity/sectionClassesViewV2/sectionClassesViewReducer.d.ts +2 -2
  13. package/lib/entity/sectionProjectView/sectionProjectView.d.ts +1 -1
  14. package/lib/entity/sectionProjectView/sectionProjectViewReducer.d.ts +2 -2
  15. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  16. package/lib/entity/snackbar/snackbarTypes.js +1 -0
  17. package/lib/entity/task/taskPayload.d.ts +1 -3
  18. package/lib/entity/task/taskPayload.js +0 -2
  19. package/lib/entity/task/taskState.d.ts +0 -2
  20. package/lib/entity/tenant/clearAllEpic.d.ts +2 -1
  21. package/lib/entity/tenant/clearAllEpic.js +2 -0
  22. package/lib/entity/transaction/payloadTypes/transactionPayload.d.ts +4 -0
  23. package/lib/entity/transaction/payloadTypes/transactionPayload.js +18 -10
  24. package/lib/entity/transaction/stateTypes/transaction.d.ts +3 -0
  25. package/lib/epic.d.ts +3 -2
  26. package/lib/epic.js +3 -2
  27. package/lib/esm/commonStateTypes/viewAndReport/viewAndReport.js +2 -0
  28. package/lib/esm/entity/account/accountSelector.js +11 -0
  29. package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
  30. package/lib/esm/entity/task/taskPayload.js +0 -2
  31. package/lib/esm/entity/tenant/clearAllEpic.js +2 -0
  32. package/lib/esm/entity/transaction/payloadTypes/transactionPayload.js +18 -10
  33. package/lib/esm/epic.js +3 -2
  34. package/lib/esm/index.js +8 -7
  35. package/lib/esm/reducer.js +3 -0
  36. package/lib/esm/view/companyTaskManagerView/companyTaskManagerViewReducer.js +11 -26
  37. package/lib/esm/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +28 -37
  38. package/lib/esm/view/companyView/epic/fetchAllCockpitViewsEpic.js +2 -2
  39. package/lib/esm/view/createTransferEntry/createTransferEntryReducer.js +82 -0
  40. package/lib/esm/view/createTransferEntry/createTransferEntrySelector.js +64 -0
  41. package/lib/esm/view/createTransferEntry/createTransferEntryState.js +17 -0
  42. package/lib/esm/view/createTransferEntry/epics/createTransferEntryEpic.js +130 -0
  43. package/lib/esm/view/createTransferEntry/epics/fetchTransferAccountsEpic.js +37 -0
  44. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +13 -1
  45. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +9 -1
  46. package/lib/esm/view/transactionDetail/transactionDetailSelector.js +6 -1
  47. package/lib/index.d.ts +9 -8
  48. package/lib/index.js +46 -37
  49. package/lib/reducer.d.ts +3 -0
  50. package/lib/reducer.js +3 -0
  51. package/lib/view/auditReportView/auditReportViewState.d.ts +1 -1
  52. package/lib/view/billPayCard/billPayCardSelector.d.ts +1 -1
  53. package/lib/view/cardBalance/cardBalanceSelector.d.ts +1 -1
  54. package/lib/view/cashBalance/cashBalanceSelector.d.ts +1 -1
  55. package/lib/view/cashInCashOut/cashInCashOutSelector.d.ts +1 -1
  56. package/lib/view/cashPosition/cashPositionSelector.d.ts +1 -1
  57. package/lib/view/companyTaskManagerView/companyTaskManagerViewPayload.d.ts +15 -13
  58. package/lib/view/companyTaskManagerView/companyTaskManagerViewReducer.d.ts +4 -5
  59. package/lib/view/companyTaskManagerView/companyTaskManagerViewReducer.js +12 -27
  60. package/lib/view/companyTaskManagerView/companyTaskManagerViewState.d.ts +3 -3
  61. package/lib/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.d.ts +3 -1
  62. package/lib/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +28 -37
  63. package/lib/view/companyView/epic/fetchAllCockpitViewsEpic.js +2 -2
  64. package/lib/view/companyView/types/cockpitTypes.d.ts +1 -2
  65. package/lib/view/createTransferEntry/createTransferEntryReducer.d.ts +32 -0
  66. package/lib/view/createTransferEntry/createTransferEntryReducer.js +86 -0
  67. package/lib/view/createTransferEntry/createTransferEntrySelector.d.ts +39 -0
  68. package/lib/view/createTransferEntry/createTransferEntrySelector.js +69 -0
  69. package/lib/view/createTransferEntry/createTransferEntryState.d.ts +30 -0
  70. package/lib/view/createTransferEntry/createTransferEntryState.js +20 -0
  71. package/lib/view/createTransferEntry/epics/createTransferEntryEpic.d.ts +11 -0
  72. package/lib/view/createTransferEntry/epics/createTransferEntryEpic.js +134 -0
  73. package/lib/view/createTransferEntry/epics/fetchTransferAccountsEpic.d.ts +14 -0
  74. package/lib/view/createTransferEntry/epics/fetchTransferAccountsEpic.js +41 -0
  75. package/lib/view/dashboard/dashboardReducer.d.ts +2 -2
  76. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  77. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +3 -1
  78. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +14 -2
  79. package/lib/view/expenseAutomationView/selectorTypes/transactionsViewSelectorTypes.d.ts +4 -1
  80. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.d.ts +1 -0
  81. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +11 -2
  82. package/lib/view/financeStatement/financeStatementReducer.d.ts +1 -1
  83. package/lib/view/globalMerchantView/globalMerchantViewReducer.d.ts +2 -2
  84. package/lib/view/reimbursementCard/reimbursementCardSelector.d.ts +1 -1
  85. package/lib/view/reportsResync/reportsResyncReducer.d.ts +2 -2
  86. package/lib/view/tasksCard/tasksCardSelector.d.ts +1 -1
  87. package/lib/view/topEx/topExSelector.d.ts +1 -1
  88. package/lib/view/transactionDetail/transactionDetailPayload.d.ts +1 -1
  89. package/lib/view/transactionDetail/transactionDetailSelector.d.ts +6 -1
  90. package/lib/view/transactionDetail/transactionDetailSelector.js +6 -1
  91. package/package.json +1 -1
  92. package/lib/esm/view/companyTaskManagerView/epics/updateCompanyTaskManagerViewUIStateEpic.js +0 -16
  93. package/lib/view/companyTaskManagerView/epics/updateCompanyTaskManagerViewUIStateEpic.d.ts +0 -6
  94. package/lib/view/companyTaskManagerView/epics/updateCompanyTaskManagerViewUIStateEpic.js +0 -20
package/lib/esm/index.js CHANGED
@@ -144,7 +144,7 @@ import { clearCompanyHealthMetricView, fetchCompanyHealthMetricView, initializeC
144
144
  import { companyHealthMetricDropDownOptions, getCompanyHealthMetricView, hasCompanyHealthMetricFormFieldChanged, isCompanyRunwayInfinite, } from './view/companyHealthMetricView/companyHealthMetricViewSelector';
145
145
  import { fetchCompanyMonthEndReportHistoricData, fetchCompanyMonthEndReportHistoricDates, fetchCompanyMonthEndReportTemplates, fetchCompanyMonthEndReportView, fetchImproveUsingZeniGPT, resetCompanyMonthEndReportFetchStatus, resetSendCompanyMonthEndReportFetchStatus, saveCompanyMonthEndReport, sendCompanyMonthEndReport, } from './view/companyMonthEndReportView/companyMonthEndReportViewReducer';
146
146
  import { getCompanyMonthEndReportHistoricData, getCompanyMonthEndReportSelectorView, } from './view/companyMonthEndReportView/companyMonthEndReportViewSelector';
147
- import { fetchCompanyTaskManagerView, fetchTaskManagerMetrics, updateCompanyTaskManagerViewUIState, } from './view/companyTaskManagerView/companyTaskManagerViewReducer';
147
+ import { fetchCompanyTaskManagerView, fetchTaskManagerMetrics, } from './view/companyTaskManagerView/companyTaskManagerViewReducer';
148
148
  import { getCompanyTaskManagerView, } from './view/companyTaskManagerView/companyTaskManagerViewSelector';
149
149
  import { clearCompanyView, companyManagementSaveUpdates, companyPassportClearDataInLocalStore, companyPassportSaveDataInLocalStore, deleteCompanyOfficerInLocalStore, fetchAllCockpitViews, fetchCompanyManagementView, fetchCompanyPassportView, fetchCompanyPortfolioView, fetchManagementView, fetchOnboardingView, fetchParentSubsidiaryManagementView, fetchPortfolioView, fetchSubscriptionView, fetchZeniUsers, saveCompanyPassportDetails, saveIndustryAndIncDateInCompanyPassportLocalStore, updateAccountingClassesEnabled, updateCompanyDownloadState, updateCompanyManagementUIState, updateCompanyPassportLocalStoreData, updateCompanyPortfolioUIState, } from './view/companyView/companyViewReducer';
150
150
  import { canSendMonthEndEmailReport, shouldEnableCalendarPickerForLastReportSent, } from './view/companyView/helpers/cockpitHelpers';
@@ -156,6 +156,7 @@ import { getAllCockpitTabsFilterView, } from './view/companyView/selector/getAll
156
156
  import { ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, toCockpitTabsFileTypeStrict, toCockpitTabsIDStrict, } from './view/companyView/types/cockpitTabsID';
157
157
  import { toHealthSortKeyType, toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toTaskManagerSortKeyType, } from './view/companyView/types/cockpitTypes';
158
158
  import { toCompanyPassportLocalData, } from './view/companyView/types/companyPassport/companyPassportLocalData';
159
+ import { clearTransferEntryRouteReplacement, createTransferEntry, createTransferEntryFailure, createTransferEntryReplacedTransaction, createTransferEntrySuccess, fetchAccountsForTransferFlow, resetCreateTransferEntryStatus, } from './view/createTransferEntry/createTransferEntryReducer';
159
160
  import { fetchDashboard, updateTreasuryVideoClosed, } from './view/dashboard/dashboardReducer';
160
161
  import { getDashboard, } from './view/dashboard/dashboardSelector';
161
162
  import { updateDashboardLayout } from './view/dashboardLayout/dashboardLayoutReducer';
@@ -169,11 +170,10 @@ import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFl
169
170
  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
171
  import { acknowledgeBulkUploadConfirmMatchComplete, bulkUploadAutomatchingTimedOut, bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, clearBulkUpload, clearBulkUploadBatchDetailsForScopeChange, clearManualSearchResults, clearMissingReceiptsTabNavigation, confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, fetchMissingReceipts as fetchExpenseAutomationMissingReceipts, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, markBatchDetailRefreshAttempted, markMissingReceiptAsDone as markExpenseAutomationMissingReceiptAsDone, pusherBatchStatusUpdate, refreshBatchDetailsForBatchId, 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
172
  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, markCategoryClassRecommendationsFailureForCategorization, markTransactionAsNotMiscategorized, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, updateTransactionFilters, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
173
+ import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markCategoryClassRecommendationsFailureForCategorization, markTransactionAsNotMiscategorized, removeTransactionFromAllTabs, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, updateTransactionFilters, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
173
174
  import { getExpenseAutomationFluxAnalysisView } from './view/expenseAutomationView/selectors/fluxAnalysisViewSelector';
174
175
  import { getExpenseAutomationReconciliationView, isAccountReconReport, } from './view/expenseAutomationView/selectors/reconciliationViewSelector';
175
- import { getExpenseAutomationTransactionView } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
176
- import { TRANSACTION_FILTER_CATEGORIES, applyTransactionFilters, } from './view/expenseAutomationView/transactionFilterHelpers';
176
+ import { getExpenseAutomationTransactionView, getLastTransferEntryReplacement, } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
177
177
  import { DEFAULT_COMPLETED_SUB_TAB, toCompletedSubTab, } from './view/expenseAutomationView/types/completedSubTab';
178
178
  import { toJEScheduleMainTab as toExpenseAutomationJEScheduleMainTab, toJEScheduleSortKey as toExpenseAutomationJEScheduleSortKey, } from './view/expenseAutomationView/types/jeSchedulesViewState';
179
179
  import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toMatchSource, toMissingReceiptsTab, } from './view/expenseAutomationView/types/missingReceiptsViewState';
@@ -338,6 +338,7 @@ import { getRemiBusinessVerificationDetails, getRemiSetupViewDetails, } from './
338
338
  import { approveOrRejectRemisBulkAction, autoReviewPendingApprovalRemis, cancelOrDeleteRemisBulkAction, clearAllRemisFromBulkActionList, clearRemiBulkActionView, incrementRemiBulkActionProcessedCount, removeRemiFromBulkActionList, reviewDraftRemisBulkAction, submitDraftRemisBulkAction, updateRemisBulkActionList, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewReducer';
339
339
  import { getRemisBulkOperationProgress, getRemisBulkReviewView, } from './view/spendManagement/reimbursement/remisBulkActionView/remisBulkActionViewSelector';
340
340
  import { hideCreatedByFilter, } from './view/spendManagement/spendManagementFilterHelpers';
341
+ import { TRANSACTION_FILTER_CATEGORIES, applyTransactionFilters, } from './view/expenseAutomationView/transactionFilterHelpers';
341
342
  import { acceptTreasuryTerms, clearTreasurySetupView, fetchPortfolioAllocation, fetchTreasuryFunds, fetchTreasurySetupView, updateFundAllocationLocalData, updatePortfolioAllocation, updateTreasuryVideoViewed, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewReducer';
342
343
  import { getTreasuryBusinessVerificationDetails, getTreasurySetupViewDetails, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewSelector';
343
344
  import { getTreasuryFundsMaximumYield, } from './view/spendManagement/treasury/treasurySetUp/treasurySetupViewState';
@@ -449,8 +450,8 @@ export {
449
450
  // Bulk Upload Types
450
451
  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
452
  // Bulk Upload Actions
452
- bulkUploadReceipts, bulkUploadAutomatchingTimedOut, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, clearBulkUploadBatchDetailsForScopeChange, markBatchDetailRefreshAttempted, refreshBatchDetailsForBatchId, 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, markCategoryClassRecommendationsFailureForCategorization, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
453
+ bulkUploadReceipts, bulkUploadAutomatchingTimedOut, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, clearBulkUploadBatchDetailsForScopeChange, markBatchDetailRefreshAttempted, refreshBatchDetailsForBatchId, 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, getLastTransferEntryReplacement, 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, };
454
+ export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateTransactionFilters, updateSelectedCheckboxTransactionIds, markCategoryClassRecommendationsFailureForCategorization, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, createTransferEntry, createTransferEntryFailure, createTransferEntryReplacedTransaction, createTransferEntrySuccess, resetCreateTransferEntryStatus, clearTransferEntryRouteReplacement, fetchAccountsForTransferFlow, removeTransactionFromAllTabs, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
454
455
  export { TOP_EX_TIME_PERIODS };
455
456
  export { toTimeframeTick, mapTimePeriodtoTimeframeTick, toTimePeriod, toAbsoluteDay, toMonthYearPeriodId, convertToPeriod, };
456
457
  export { toVendorSpendTrendFilterTabsTypeStrict, } from './entity/vendorExpense/vendorExpenseSelector';
@@ -535,7 +536,7 @@ export { getCompanyPortfolioView, isInfiniteRunway };
535
536
  export { getAllCockpitTabsFilterView };
536
537
  export { fetchImproveUsingZeniGPT, fetchCompanyMonthEndReportView, sendCompanyMonthEndReport, saveCompanyMonthEndReport, resetCompanyMonthEndReportFetchStatus, resetSendCompanyMonthEndReportFetchStatus, getCompanyMonthEndReportSelectorView, fetchCompanyMonthEndReportHistoricDates, fetchCompanyMonthEndReportHistoricData, fetchCompanyMonthEndReportTemplates, getCompanyMonthEndReportHistoricData, };
537
538
  export { newAddressInLocalStore, getAddress, getNewAddress, getAllNewAddresses, getFormattedAddress, fetchAddress, clearAddressView, createAddress, removeNewAddressDataInLocalStore, };
538
- export { toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toHealthSortKeyType, toTaskManagerSortKeyType, updateCompanyTaskManagerViewUIState, };
539
+ export { toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toHealthSortKeyType, toTaskManagerSortKeyType, };
539
540
  export { ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, toCockpitTabsIDStrict, toCockpitTabsFileTypeStrict, };
540
541
  export { isAllowedValueWithCode, isAllowedValueWithID, };
541
542
  export { fetchCompanyPassportView, getCompanyPassportView, getCompanyPassportLocalStoreData, isCompanyPassportDataToBeSaved, companyPassportSaveDataInLocalStore, saveIndustryAndIncDateInCompanyPassportLocalStore, deleteCompanyOfficerInLocalStore, companyPassportClearDataInLocalStore, updateCompanyPassportLocalStoreData, saveCompanyPassportDetails, updateAccountingClassesEnabled, clearCompanyView, };
@@ -98,6 +98,7 @@ import companyHealthMetricView, { initialState as initialCompanyHealthMetricView
98
98
  import companyMonthEndReportView, { initialState as initialCompanyMonthEndReportViewState, } from './view/companyMonthEndReportView/companyMonthEndReportViewReducer';
99
99
  import companyTaskManagerView, { initialState as initialCompanyTaskManagerViewState, } from './view/companyTaskManagerView/companyTaskManagerViewReducer';
100
100
  import companyView, { initialState as initialCompanyViewState, } from './view/companyView/companyViewReducer';
101
+ import createTransferEntry, { initialState as initialCreateTransferEntryState, } from './view/createTransferEntry/createTransferEntryReducer';
101
102
  import creditAgentView, { initialState as initialCreditAgentViewState, } from './view/creditAgentView/creditAgentViewReducer';
102
103
  import dashboard, { initialState as initialDashboardState, } from './view/dashboard/dashboardReducer';
103
104
  import dashboardLayout, { initialState as initialDashboardLayoutState, } from './view/dashboardLayout/dashboardLayoutReducer';
@@ -360,6 +361,7 @@ const initialViewsState = {
360
361
  expenseAutomationReconciliationViewState: initialExpenseAutomationReconciliationViewState,
361
362
  expenseAutomationTransactionsViewState: initialExpenseAutomationTransactionsViewState,
362
363
  expenseAutomationViewState: initialExpenseAutomationViewState,
364
+ createTransferEntryState: initialCreateTransferEntryState,
363
365
  expressPayState: initialExpressPayState,
364
366
  featureNotificationViewState: initialFeatureNotificationViewState,
365
367
  fileViewState: initialFileViewState,
@@ -595,6 +597,7 @@ const viewReducers = {
595
597
  expenseAutomationReconciliationViewState: expenseAutomationReconciliationView,
596
598
  expenseAutomationTransactionsViewState: expenseAutomationTransactionsView,
597
599
  expenseAutomationViewState: expenseAutomationView,
600
+ createTransferEntryState: createTransferEntry,
598
601
  expressPayState: expressPay,
599
602
  featureNotificationViewState: featureNotificationView,
600
603
  fileViewState: fileView,
@@ -3,8 +3,7 @@ export const initialUIState = {
3
3
  filterText: '',
4
4
  sortKey: 'dueDate',
5
5
  sortOrder: 'descending',
6
- from: 0,
7
- filters: {},
6
+ pageToken: null,
8
7
  };
9
8
  const initialMetrics = {
10
9
  closed: 0,
@@ -29,11 +28,10 @@ const companyTaskManagerView = createSlice({
29
28
  initialState,
30
29
  reducers: {
31
30
  fetchCompanyTaskManagerView: {
32
- prepare(from, sortKey, sortOrder, keepExistingListItems = true, searchString, filters) {
31
+ prepare(pageToken, sortKey, sortOrder, keepExistingListItems = true, searchString) {
33
32
  return {
34
33
  payload: {
35
- from,
36
- filters,
34
+ pageToken,
37
35
  searchString,
38
36
  sortKey,
39
37
  sortOrder,
@@ -42,10 +40,10 @@ const companyTaskManagerView = createSlice({
42
40
  };
43
41
  },
44
42
  reducer(draft, action) {
45
- const { from, searchString, sortKey, sortOrder, keepExistingListItems } = action.payload;
43
+ const { pageToken, searchString, sortKey, sortOrder, keepExistingListItems, } = action.payload;
46
44
  draft.uiState.sortKey = sortKey;
47
45
  draft.uiState.sortOrder = sortOrder;
48
- draft.uiState.from = from;
46
+ draft.uiState.pageToken = pageToken;
49
47
  if (keepExistingListItems === false) {
50
48
  draft.taskIds = [];
51
49
  }
@@ -58,14 +56,15 @@ const companyTaskManagerView = createSlice({
58
56
  },
59
57
  updateCompanyTaskManagerViewOnSuccess(draft, action) {
60
58
  const { data } = action.payload;
61
- const tasks = data.aggregations.group_by_company_name.buckets.flatMap((bucket) => bucket.tasks);
59
+ const { tasks, query, total_count } = data;
62
60
  draft.fetchState = 'Completed';
63
61
  draft.error = undefined;
64
62
  draft.taskIds = [...draft.taskIds, ...tasks.map((task) => task.task_id)];
65
- if (draft.uiState.filterText === '' && draft.uiState.from === 0) {
66
- draft.totalTaskCount = data.total;
63
+ // consider total count only when fetching for first time
64
+ if (draft.uiState.filterText === '' && draft.uiState.pageToken == null) {
65
+ draft.totalTaskCount = total_count;
67
66
  }
68
- draft.uiState.from = data.from + data.limit;
67
+ draft.uiState.pageToken = query.page_token;
69
68
  },
70
69
  updateCompanyTaskManagerViewOnFailure: {
71
70
  reducer(draft, action) {
@@ -86,24 +85,10 @@ const companyTaskManagerView = createSlice({
86
85
  updateTaskManagerMetricsOnFailure(draft) {
87
86
  draft.metricsFetchState = 'Error';
88
87
  },
89
- updateCompanyTaskManagerViewUIState(draft, action) {
90
- if (action.payload.filters != null) {
91
- draft.uiState.filters = action.payload.filters;
92
- }
93
- if (action.payload.filterText != null) {
94
- draft.uiState.filterText = action.payload.filterText;
95
- }
96
- if (action.payload.sortKey != null) {
97
- draft.uiState.sortKey = action.payload.sortKey;
98
- }
99
- if (action.payload.sortOrder != null) {
100
- draft.uiState.sortOrder = action.payload.sortOrder;
101
- }
102
- },
103
88
  clearCompanyTaskManagerView(draft) {
104
89
  Object.assign(draft, initialState);
105
90
  },
106
91
  },
107
92
  });
108
- export const { fetchCompanyTaskManagerView, updateCompanyTaskManagerViewOnSuccess, updateCompanyTaskManagerViewOnFailure, fetchTaskManagerMetrics, updateTaskManagerMetrics, updateTaskManagerMetricsOnFailure, clearCompanyTaskManagerView, updateCompanyTaskManagerViewUIState, } = companyTaskManagerView.actions;
93
+ export const { fetchCompanyTaskManagerView, updateCompanyTaskManagerViewOnSuccess, updateCompanyTaskManagerViewOnFailure, fetchTaskManagerMetrics, updateTaskManagerMetrics, updateTaskManagerMetricsOnFailure, clearCompanyTaskManagerView, } = companyTaskManagerView.actions;
109
94
  export default companyTaskManagerView.reducer;
@@ -1,35 +1,51 @@
1
1
  import { from } from 'rxjs';
2
2
  import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
3
  import { getSortOrder } from '../../../commonPayloadTypes/sortOrderPayload';
4
+ import { updateCompanies } from '../../../entity/company/companyReducer';
4
5
  import { updateTags } from '../../../entity/tag/tagReducer';
5
6
  import { updateTasks } from '../../../entity/task/taskReducer';
7
+ import { updateAllUsers } from '../../../entity/user/userReducer';
6
8
  import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
7
9
  import { fetchCompanyTaskManagerView, updateCompanyTaskManagerViewOnFailure, updateCompanyTaskManagerViewOnSuccess, } from '../companyTaskManagerViewReducer';
8
- const DEFAULT_PAGE_SIZE = 100;
10
+ const toSortKeyPayload = (sortKey) => {
11
+ switch (sortKey) {
12
+ case 'taskName':
13
+ return 'name';
14
+ case 'dueDate':
15
+ return 'due_date';
16
+ case 'createdBy':
17
+ return 'created_by';
18
+ case 'name':
19
+ return 'company_name';
20
+ default:
21
+ return sortKey;
22
+ }
23
+ };
9
24
  export const fetchCompanyTaskManagerViewEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchCompanyTaskManagerView.match), switchMap((action) => {
10
- const { from: fromOffset, searchString, sortKey, sortOrder, filters, } = action.payload;
25
+ const { pageToken, sortKey, sortOrder, searchString } = action.payload;
11
26
  const queryValue = {
12
- bool_type: 'should',
13
- size: DEFAULT_PAGE_SIZE,
14
- from: fromOffset,
15
- global_search: searchString ?? '',
27
+ page_token: pageToken,
16
28
  sort_by: toSortKeyPayload(sortKey),
17
29
  sort_order: getSortOrder(sortOrder),
18
- ...(filters?.categories != null && filters.categories.length > 0
19
- ? { filter_by: toFilterByPayload(filters) }
20
- : {}),
30
+ search_text: searchString ?? '',
31
+ view: 'cockpit_task_manager_view',
21
32
  };
22
33
  return zeniAPI
23
- .getJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels/tasks-es?query=${encodeURIComponent(JSON.stringify(queryValue))}`)
34
+ .getJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels/tasks?query=${encodeURIComponent(JSON.stringify(queryValue))}`)
24
35
  .pipe(mergeMap((response) => {
25
36
  if (isSuccessResponse(response) && response.data != null) {
26
- const tasksList = response.data.aggregations.group_by_company_name.buckets.flatMap((bucket) => bucket.tasks);
37
+ const tasksList = response.data.tasks;
27
38
  const actions = [
28
39
  updateCompanyTaskManagerViewOnSuccess({
29
40
  data: response.data,
30
41
  }),
31
42
  updateTasks(tasksList),
32
- updateTags(tasksList.flatMap((task) => task.tags)),
43
+ updateCompanies({
44
+ payload: response.data.companies,
45
+ schema: {},
46
+ }),
47
+ updateTags(tasksList.map((task) => task.tags).flat()),
48
+ updateAllUsers({ users: response.data.users }),
33
49
  ];
34
50
  return from(actions);
35
51
  }
@@ -46,28 +62,3 @@ export const fetchCompanyTaskManagerViewEpic = (actions$, _state$, zeniAPI) => a
46
62
  return from(actions);
47
63
  }));
48
64
  }));
49
- const toSortKeyPayload = (sortKey) => {
50
- switch (sortKey) {
51
- case 'taskName':
52
- return 'name';
53
- case 'dueDate':
54
- return 'due_date';
55
- case 'createdBy':
56
- return 'created_by';
57
- case 'name':
58
- return 'company_name';
59
- default:
60
- return sortKey;
61
- }
62
- };
63
- const toFilterByPayload = (filters) => {
64
- if (filters.categories == null) {
65
- return [];
66
- }
67
- return filters.categories.map((category) => ({
68
- field: category.field ?? '',
69
- operator: category.matchingOperator === 'equal' ? 'is' : 'is_not',
70
- values: category.values.map((v) => String(v)),
71
- join: category.valuesCombinationOperator === 'ALL' ? 'and' : 'or',
72
- }));
73
- };
@@ -21,7 +21,7 @@ export const fetchAllCockpitViewsEpic = (actions$, state$) => actions$.pipe(filt
21
21
  fetchReviewCompanyView(),
22
22
  fetchCompanyHealthMetricView(),
23
23
  fetchCompanyMetaData(),
24
- fetchCompanyTaskManagerView(0, 'dueDate', 'descending', false),
24
+ fetchCompanyTaskManagerView(null, 'dueDate', 'descending', false),
25
25
  fetchCompanyHealthMetricConfig(),
26
26
  ]);
27
27
  }
@@ -74,7 +74,7 @@ export const fetchAllCockpitViewsEpic = (actions$, state$) => actions$.pipe(filt
74
74
  }
75
75
  if (state.companyTaskManagerViewState.fetchState !== 'In-Progress' &&
76
76
  state.companyTaskManagerViewState.hasValidState() === false) {
77
- fetchActions.push(fetchCompanyTaskManagerView(0, 'dueDate', 'descending', false));
77
+ fetchActions.push(fetchCompanyTaskManagerView(null, 'dueDate', 'descending', false));
78
78
  }
79
79
  return from(fetchActions);
80
80
  }
@@ -0,0 +1,82 @@
1
+ import { createSlice } from '@reduxjs/toolkit';
2
+ import { initialCreateTransferEntryState, } from './createTransferEntryState';
3
+ export const initialState = initialCreateTransferEntryState;
4
+ const createTransferEntrySlice = createSlice({
5
+ name: 'createTransferEntry',
6
+ initialState,
7
+ reducers: {
8
+ fetchAccountsForTransferFlow(draft, action) {
9
+ const slice = draft.transferAccountsByType[action.payload.kind];
10
+ // Idempotent: a duplicate dispatch must not briefly downgrade
11
+ // 'Completed' back to 'In-Progress' (would clear loaded data from a
12
+ // consumer's perspective) nor restart the in-flight epic stream.
13
+ // The hook (`useFetchTransferAccountsForFlow`) is the sole caller and
14
+ // already dedupes via `store.getState()`; this guard is defense in
15
+ // depth for any future caller.
16
+ if (slice.fetchState === 'In-Progress' ||
17
+ slice.fetchState === 'Completed') {
18
+ return;
19
+ }
20
+ slice.fetchState = 'In-Progress';
21
+ },
22
+ updateAccountsForTransferFlow(draft, action) {
23
+ const slice = draft.transferAccountsByType[action.payload.kind];
24
+ slice.fetchState = 'Completed';
25
+ slice.accountIds = action.payload.accountIds;
26
+ },
27
+ updateAccountsForTransferFlowFailure(draft, action) {
28
+ draft.transferAccountsByType[action.payload.kind].fetchState = 'Error';
29
+ },
30
+ createTransferEntry: {
31
+ prepare(payload) {
32
+ return { payload };
33
+ },
34
+ /**
35
+ * Defense-in-depth: clear any stale `lastTransferEntryReplacement` on a
36
+ * fresh dispatch so a second `createTransferEntry` never inherits the
37
+ * previous run's replacement signal (e.g. if the prior `timer(0)` cleanup
38
+ * never fired). Mirrors the host hook's `consumedReplacementRef` guard
39
+ * (see `useTransferEntryRouteReplacement` in zeni-web-app-ui).
40
+ */
41
+ reducer(draft) {
42
+ draft.createTransferEntryStatus = 'In-Progress';
43
+ draft.lastTransferEntryReplacement = undefined;
44
+ },
45
+ },
46
+ createTransferEntrySuccess(draft) {
47
+ draft.createTransferEntryStatus = 'Completed';
48
+ },
49
+ createTransferEntryFailure(draft) {
50
+ draft.createTransferEntryStatus = 'Error';
51
+ },
52
+ resetCreateTransferEntryStatus(draft) {
53
+ draft.createTransferEntryStatus = 'Not-Started';
54
+ },
55
+ createTransferEntryReplacedTransaction: {
56
+ prepare(previousTransactionId, newTransactionId) {
57
+ return { payload: { newTransactionId, previousTransactionId } };
58
+ },
59
+ reducer(draft, action) {
60
+ draft.lastTransferEntryReplacement = action.payload;
61
+ },
62
+ },
63
+ /**
64
+ * One-shot acknowledgement: the host has consumed the route-replacement
65
+ * signal and navigated to the new transaction url, so we can drop the
66
+ * record. Re-dispatching is idempotent.
67
+ */
68
+ clearTransferEntryRouteReplacement(draft) {
69
+ draft.lastTransferEntryReplacement = undefined;
70
+ },
71
+ /**
72
+ * Full slice reset. Dispatched from `clearAllEpic` on tenant switch so
73
+ * stale per-tenant state (account-id pools, status, replacement signal)
74
+ * doesn't bleed across tenants.
75
+ */
76
+ clearCreateTransferEntry(draft) {
77
+ Object.assign(draft, initialState);
78
+ },
79
+ },
80
+ });
81
+ export const { fetchAccountsForTransferFlow, updateAccountsForTransferFlow, updateAccountsForTransferFlowFailure, createTransferEntry, createTransferEntrySuccess, createTransferEntryFailure, resetCreateTransferEntryStatus, createTransferEntryReplacedTransaction, clearTransferEntryRouteReplacement, clearCreateTransferEntry, } = createTransferEntrySlice.actions;
82
+ export default createTransferEntrySlice.reducer;
@@ -0,0 +1,64 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+ import { getAccountBase, getAccountBaseForCreditCardTransferAccounts, getAccountBaseForTransferAccounts, } from '../../entity/account/accountSelector';
3
+ import { getAccountList } from '../accountList/accountListSelector';
4
+ export function getCreateTransferEntryStatus(state) {
5
+ return state.createTransferEntryState.createTransferEntryStatus;
6
+ }
7
+ export function getLastTransferEntryReplacement(state) {
8
+ return state.createTransferEntryState.lastTransferEntryReplacement;
9
+ }
10
+ /**
11
+ * Shared resolver for the credit/debit dropdowns in the transfer drawer.
12
+ *
13
+ * Resolution policy (intentional):
14
+ * 1. Prefer the dedicated API fetch results (`transferEntryEligible` for the
15
+ * debit pool, `creditCardOnlyEligible` for the credit-card-payment credit
16
+ * pool).
17
+ * 2. If the dedicated fetch returns an empty list while the COA is loaded,
18
+ * fall back to the COA: the full account list for `transferEntryEligible`,
19
+ * and COA accounts filtered to `credit_card` for `creditCardOnlyEligible`.
20
+ * This keeps the dropdown populated for older tenants where the dedicated
21
+ * endpoints haven't been backfilled yet.
22
+ *
23
+ * Intent — what this selector deliberately does NOT do:
24
+ * - Does NOT distinguish "fetch in-flight" / "fetch errored" / "fetch returned
25
+ * empty" — all three collapse to the COA fallback. The product preference
26
+ * is "always show something selectable" over "show a spinner that may never
27
+ * resolve". Loading/error UI belongs in the view layer; if you need a
28
+ * spinner, observe the `fetchState` on `transferAccountsByType[kind]`
29
+ * separately rather than changing the resolution policy here.
30
+ * - Does NOT enforce "API result is authoritative even if empty" — a tenant
31
+ * whose dedicated endpoint is correctly returning `[]` (e.g. no eligible
32
+ * transfer destinations) will still see the COA. That trade-off is
33
+ * accepted because the alternative blocks the user from picking anything;
34
+ * the backend distinguishes "no result" from "endpoint not implemented" by
35
+ * surfacing an error response, which the view layer handles separately.
36
+ *
37
+ * Memoized with reselect so consuming view-models don't recompute on every
38
+ * unrelated state change.
39
+ */
40
+ export const getResolvedTransferAccounts = createSelector([
41
+ (state) => state.accountState,
42
+ (state) => state.accountListState,
43
+ (state) => state.createTransferEntryState.transferAccountsByType
44
+ .transferEntryEligible.accountIds,
45
+ (state) => state.createTransferEntryState.transferAccountsByType
46
+ .creditCardOnlyEligible.accountIds,
47
+ ], (accountState, accountListState, transferEligibleIds, creditCardOnlyIds) => {
48
+ const accountList = getAccountList(accountState, accountListState, 'accountList');
49
+ const transferEligibleFromApi = transferEligibleIds
50
+ .map((id) => getAccountBaseForTransferAccounts(accountState, id))
51
+ .filter((account) => account != null);
52
+ const coaFallbackAllAccounts = accountList.accounts
53
+ .map((a) => getAccountBase(accountState, a.accountId, 'account_list'))
54
+ .filter((account) => account != null);
55
+ const transferAccountsList = transferEligibleFromApi.length > 0
56
+ ? transferEligibleFromApi
57
+ : coaFallbackAllAccounts;
58
+ const creditCardFromApi = creditCardOnlyIds
59
+ .map((id) => getAccountBaseForCreditCardTransferAccounts(accountState, id))
60
+ .filter((account) => account != null);
61
+ const coaFallbackCreditCards = coaFallbackAllAccounts.filter((a) => a.accountType === 'credit_card');
62
+ const creditCardTransferAccountsList = creditCardFromApi.length > 0 ? creditCardFromApi : coaFallbackCreditCards;
63
+ return { creditCardTransferAccountsList, transferAccountsList };
64
+ });
@@ -0,0 +1,17 @@
1
+ /** Which pool `fetchAccountsForTransferFlow` / transfer-flow epic should load. */
2
+ export const TRANSFER_ACCOUNTS_FETCH_TYPE = [
3
+ 'transferEntryEligible',
4
+ 'creditCardOnlyEligible',
5
+ ];
6
+ const initialTransferAccountsState = {
7
+ accountIds: [],
8
+ fetchState: 'Not-Started',
9
+ };
10
+ export const initialCreateTransferEntryState = {
11
+ createTransferEntryStatus: 'Not-Started',
12
+ lastTransferEntryReplacement: undefined,
13
+ transferAccountsByType: {
14
+ transferEntryEligible: initialTransferAccountsState,
15
+ creditCardOnlyEligible: initialTransferAccountsState,
16
+ },
17
+ };
@@ -0,0 +1,130 @@
1
+ import { concat, from, timer } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
4
+ import { toTransactionID } from '../../../entity/transaction/payloadTypes/transactionIDPayload';
5
+ import { removeTransaction, updateTransaction, } from '../../../entity/transaction/transactionReducer';
6
+ import { isSuccessResponse } from '../../../responsePayload';
7
+ import { removeTransactionFromAllTabs } from '../../expenseAutomationView/reducers/transactionsViewReducer';
8
+ import { initializeTransactionDetailLocalData, removeTransactionDetail, } from '../../transactionDetail/transactionDetailReducer';
9
+ import { getTransactionDetailKey } from '../../transactionDetail/transactionDetailState';
10
+ import { clearTransferEntryRouteReplacement, createTransferEntry, createTransferEntryFailure, createTransferEntryReplacedTransaction, createTransferEntrySuccess, resetCreateTransferEntryStatus, } from '../createTransferEntryReducer';
11
+ // ─── Pure helpers ────────────────────────────────────────────────────────────
12
+ function transactionIdsAreEqual(a, b) {
13
+ return a.id === b.id && a.type === b.type;
14
+ }
15
+ const successSnackbar = () => openSnackbar({
16
+ messageSection: 'create_transfer_entry',
17
+ messageText: 'success',
18
+ type: 'success',
19
+ });
20
+ const failureSnackbar = () => openSnackbar({
21
+ messageSection: 'create_transfer_entry',
22
+ messageText: 'failed',
23
+ type: 'error',
24
+ });
25
+ function buildFailureActions() {
26
+ return [createTransferEntryFailure(), failureSnackbar()];
27
+ }
28
+ /**
29
+ * Defensive guard: a BE response that returns 200 with `transaction != null`
30
+ * but where the body lacks a usable id/type is unsafe to seed into the store —
31
+ * downstream code would store under a garbage key and the host hook would try
32
+ * to navigate to a broken url. Treat that case as failure so the source row
33
+ * stays visible and the user can retry.
34
+ */
35
+ function isWellFormedTransactionPayload(t) {
36
+ return (t != null &&
37
+ typeof t.transaction_id === 'string' &&
38
+ t.transaction_id !== '' &&
39
+ typeof t.transaction_type === 'string' &&
40
+ t.transaction_type !== '');
41
+ }
42
+ function buildSuccessSideEffects(sourceTransactionId) {
43
+ return [
44
+ createTransferEntrySuccess(),
45
+ removeTransactionFromAllTabs(sourceTransactionId),
46
+ successSnackbar(),
47
+ ];
48
+ }
49
+ function buildPreviousTransactionCleanupActions(previousTransactionId) {
50
+ return [
51
+ removeTransaction(getTransactionDetailKey(previousTransactionId)),
52
+ removeTransactionDetail(previousTransactionId),
53
+ clearTransferEntryRouteReplacement(),
54
+ ];
55
+ }
56
+ /**
57
+ * Emits `resetCreateTransferEntryStatus()` (and, on the replacement path, the
58
+ * follow-up cleanup actions) one scheduler tick after the success actions.
59
+ *
60
+ * Why the `timer(0)` (and not synchronous emission):
61
+ * On the replacement path the host (web-app-ui) watches
62
+ * `lastTransferEntryReplacement`, navigates to the new transaction url, and
63
+ * then sees `clearTransferEntryRouteReplacement` clear the signal. If we
64
+ * dispatched the cleanup actions in the same tick as
65
+ * `createTransferEntryReplacedTransaction`, redux subscribers would observe
66
+ * `lastTransferEntryReplacement` flicker on then off in a single render, and
67
+ * the old transaction's state (which the still-mounted detail view may be
68
+ * reading) would be torn down before the host has had a chance to start
69
+ * navigating. Deferring by one microtask gives the host exactly one render
70
+ * pass to react before we tear down the previous transaction.
71
+ */
72
+ function delayedResetAndPreviousCleanup(previousTransactionId) {
73
+ return timer(0).pipe(mergeMap(() => {
74
+ const actions = [resetCreateTransferEntryStatus()];
75
+ if (previousTransactionId != null) {
76
+ actions.push(...buildPreviousTransactionCleanupActions(previousTransactionId));
77
+ }
78
+ return from(actions);
79
+ }));
80
+ }
81
+ // ─── Success-path branches ───────────────────────────────────────────────────
82
+ function handleSuccessWithoutTransactionBody(transactionId) {
83
+ return concat(from(buildSuccessSideEffects(transactionId)), delayedResetAndPreviousCleanup(undefined));
84
+ }
85
+ function handleSuccessWithTransactionBody(transactionPayload, vendorPayload, previousTransactionId, sourceTransactionId) {
86
+ const newTransactionId = toTransactionID(transactionPayload);
87
+ const replaced = !transactionIdsAreEqual(previousTransactionId, newTransactionId);
88
+ const immediate = [
89
+ updateTransaction(getTransactionDetailKey(newTransactionId), transactionPayload),
90
+ initializeTransactionDetailLocalData({
91
+ transactionId: newTransactionId,
92
+ vendorId: vendorPayload?.[0]?.vendor_id,
93
+ }),
94
+ ...buildSuccessSideEffects(sourceTransactionId),
95
+ ];
96
+ if (replaced) {
97
+ immediate.push(createTransferEntryReplacedTransaction(previousTransactionId, newTransactionId));
98
+ }
99
+ return concat(from(immediate), delayedResetAndPreviousCleanup(replaced ? previousTransactionId : undefined));
100
+ }
101
+ // ─── Top-level epic ──────────────────────────────────────────────────────────
102
+ export const createTransferEntryEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(createTransferEntry.match), mergeMap((action) => {
103
+ const { transactionId, creditAccountIntegrationId, debitAccountIntegrationId, memo, transactionType, sourceTransactionType, } = action.payload;
104
+ const previousTransactionId = {
105
+ id: transactionId,
106
+ type: sourceTransactionType,
107
+ };
108
+ const payload = {
109
+ transaction_type: transactionType,
110
+ transaction_id: transactionId,
111
+ to_account_integration_id: creditAccountIntegrationId,
112
+ from_account_integration_id: debitAccountIntegrationId,
113
+ memo,
114
+ };
115
+ return zeniAPI
116
+ .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/transaction-type-update`, payload)
117
+ .pipe(mergeMap((response) => {
118
+ if (!isSuccessResponse(response)) {
119
+ return from(buildFailureActions());
120
+ }
121
+ const transaction = response.data?.transaction;
122
+ if (transaction != null) {
123
+ if (!isWellFormedTransactionPayload(transaction)) {
124
+ return from(buildFailureActions());
125
+ }
126
+ return handleSuccessWithTransactionBody(transaction, response.data?.vendors, previousTransactionId, transactionId);
127
+ }
128
+ return handleSuccessWithoutTransactionBody(transactionId);
129
+ }), catchError(() => from(buildFailureActions())));
130
+ }));