@zeniai/client-epic-state 5.1.68-betaDI2 → 5.1.68-betaNB1

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 (54) hide show
  1. package/lib/entity/accountRecon/accountReconReducer.js +4 -0
  2. package/lib/entity/accountRecon/accountReconState.d.ts +4 -1
  3. package/lib/entity/accountRecon/accountReconState.js +1 -0
  4. package/lib/epic.d.ts +2 -1
  5. package/lib/epic.js +2 -1
  6. package/lib/esm/entity/accountRecon/accountReconReducer.js +4 -0
  7. package/lib/esm/entity/accountRecon/accountReconState.js +1 -0
  8. package/lib/esm/epic.js +2 -1
  9. package/lib/esm/index.js +5 -5
  10. package/lib/esm/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +37 -0
  11. package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +74 -5
  12. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  13. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +10 -2
  14. package/lib/esm/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +29 -5
  15. package/lib/esm/view/expenseAutomationView/payload/reconciliationPayload.js +106 -0
  16. package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +86 -13
  17. package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -6
  18. package/lib/esm/view/expenseAutomationView/selectors/statementParseViewSelector.js +51 -10
  19. package/lib/esm/view/expenseAutomationView/types/reconciliationViewState.js +15 -1
  20. package/lib/esm/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +12 -9
  21. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewPayload.js +2 -7
  22. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewReducer.js +2 -47
  23. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewSelector.js +0 -9
  24. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewState.js +0 -1
  25. package/lib/index.d.ts +5 -5
  26. package/lib/index.js +54 -47
  27. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.d.ts +21 -0
  28. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +41 -0
  29. package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +73 -4
  30. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.d.ts +1 -1
  31. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  32. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +9 -1
  33. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.d.ts +2 -0
  34. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +30 -4
  35. package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +98 -4
  36. package/lib/view/expenseAutomationView/payload/reconciliationPayload.js +113 -0
  37. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +31 -4
  38. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +87 -14
  39. package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.d.ts +4 -1
  40. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -6
  41. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.d.ts +4 -2
  42. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.js +53 -10
  43. package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +66 -0
  44. package/lib/view/expenseAutomationView/types/reconciliationViewState.js +19 -1
  45. package/lib/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.d.ts +8 -2
  46. package/lib/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +9 -6
  47. package/lib/view/notificationPreferencesView/notificationPreferencesViewPayload.d.ts +0 -1
  48. package/lib/view/notificationPreferencesView/notificationPreferencesViewPayload.js +2 -7
  49. package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.d.ts +1 -6
  50. package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.js +3 -48
  51. package/lib/view/notificationPreferencesView/notificationPreferencesViewSelector.js +0 -9
  52. package/lib/view/notificationPreferencesView/notificationPreferencesViewState.d.ts +0 -1
  53. package/lib/view/notificationPreferencesView/notificationPreferencesViewState.js +0 -1
  54. package/package.json +1 -1
package/lib/esm/index.js CHANGED
@@ -175,7 +175,7 @@ import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLine
175
175
  import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFluxAnalysisView, updateFluxAnalysisViewPageMetaData, updateFluxAnalysisViewUIState, updateOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview, } from './view/expenseAutomationView/reducers/fluxAnalysisViewReducer';
176
176
  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';
177
177
  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';
178
- import { clearStatementDateConflict, deleteAccountStatement, excludeAccountFromReconciliation, fetchReconciliation as fetchReconciliationView, includeAccountInReconciliation, parseStatement, parseStatementFailure, parseStatementSuccess, reparseStatement, reparseStatementFailure, reparseStatementSuccess, resetReparseStatementStatus, saveReconciliationDetail as saveExpenseAutomationReconciliationDetail, saveReconciliationReview as saveExpenseAutomationReconciliationReview, setConnectionInProgressForAccount as setConnectionInProgressForAccountReconciliation, setStatementParseInProgress, setStatementProcessingDismissedToBackground, submitStatementUpdate, 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, updateParsedStatementData, updateStatementProcessingBackgroundCompletedSteps, updateStatementProcessingFailed, updateStatementUpdateLocalData, updateStatementUploadChosen, uploadAccountStatement, } from './view/expenseAutomationView/reducers/reconciliationViewReducer';
178
+ import { clearConfirmStatementMappingConflict, clearStatementDateConflict, confirmStatementMapping, confirmStatementMappingFailure, confirmStatementMappingSuccess, deleteAccountStatement, excludeAccountFromReconciliation, fetchReconciliation as fetchReconciliationView, includeAccountInReconciliation, parseStatement, parseStatementFailure, parseStatementSuccess, reparseStatement, reparseStatementFailure, reparseStatementSuccess, resetReparseStatementStatus, saveReconciliationDetail as saveExpenseAutomationReconciliationDetail, saveReconciliationReview as saveExpenseAutomationReconciliationReview, setConnectionInProgressForAccount as setConnectionInProgressForAccountReconciliation, setStatementParseInProgress, setStatementProcessingDismissedToBackground, submitStatementUpdate, 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, updateParsedStatementData, updateStatementProcessingBackgroundCompletedSteps, updateStatementProcessingFailed, updateStatementUpdateLocalData, updateStatementUploadChosen, uploadAccountStatement, } from './view/expenseAutomationView/reducers/reconciliationViewReducer';
179
179
  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';
180
180
  import { getExpenseAutomationFluxAnalysisView } from './view/expenseAutomationView/selectors/fluxAnalysisViewSelector';
181
181
  import { getExpenseAutomationReconciliationView, getReparseStatementStatusByAccountId, isAccountReconReport, } from './view/expenseAutomationView/selectors/reconciliationViewSelector';
@@ -185,7 +185,7 @@ import { DEFAULT_COMPLETED_SUB_TAB, toCompletedSubTab, } from './view/expenseAut
185
185
  import { toJEScheduleMainTab as toExpenseAutomationJEScheduleMainTab, toJEScheduleSortKey as toExpenseAutomationJEScheduleSortKey, } from './view/expenseAutomationView/types/jeSchedulesViewState';
186
186
  import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toMatchSource, toMissingReceiptsTab, } from './view/expenseAutomationView/types/missingReceiptsViewState';
187
187
  import { toMissingReceiptsSortKey as toExpenseAutomationMissingReceiptsSortKey, } from './view/expenseAutomationView/types/missingReceiptsViewState';
188
- import { toReconciliationTabsType, } from './view/expenseAutomationView/types/reconciliationViewState';
188
+ import { STATEMENT_ACCOUNT_SCOPES, toReconciliationTabsType, toStatementAccountScope, toStatementAccountScopeStrict, toStatementBalanceSource, toStatementBalanceSourceStrict, } from './view/expenseAutomationView/types/reconciliationViewState';
189
189
  import { toTransactionsTabKey as toExpenseAutomationTransactionsTabKey, toTransactionsSortKey, } from './view/expenseAutomationView/types/transactionsViewState';
190
190
  import { clearFeatureNotificationView, fetchRegisteredInterests, notifyMeForFeature, } from './view/featureNotificationView/featureNotificationViewReducer';
191
191
  import { getFeatureNotificationView, getRegisteredInterests, getRegisteredInterestsByFeature, isFeatureInterestRegistered, } from './view/featureNotificationView/featureNotificationViewSelector';
@@ -212,7 +212,7 @@ import { isNetBurnOrIncomeClassesViewCalculatedSectionID, isNetBurnOrIncomeClass
212
212
  import { toAverageMonthsCount } from './view/netBurnOrIncomeStoryCard/epic/updateNetBurnOrIncomeStoryCardSettingsEpic';
213
213
  import { fetchNetBurnOrIncomeStoryCard, updateNetBurnOrIncomeStoryCardSettings, } from './view/netBurnOrIncomeStoryCard/netBurnOrIncomeStoryCardReducer';
214
214
  import { getNetBurnOrIncomeStoryCardReport } from './view/netBurnOrIncomeStoryCard/netBurnOrIncomeStoryCardSelector';
215
- import { clearAllNotificationPreferencesView, clearNotificationPreferencesLocalOverrides, saveNotificationPreferences, setGroupChannelMaster, setGroupFrequency, toggleEventChannel, } from './view/notificationPreferencesView/notificationPreferencesViewReducer';
215
+ import { clearAllNotificationPreferencesView, clearNotificationPreferencesLocalOverrides, setGroupFrequency, toggleEventChannel, } from './view/notificationPreferencesView/notificationPreferencesViewReducer';
216
216
  import { getEffectiveNotificationPreferences, getNotificationLocalOverrides, getNotificationPreferencesSaveState, hasUnsavedNotificationPreferences, } from './view/notificationPreferencesView/notificationPreferencesViewSelector';
217
217
  import { fetchNotificationUnreadCount, fetchNotificationUnreadCountSuccess, fetchNotificationView, updateNotificationViewAllNotificationsStatus, updateNotificationViewCurrentTabAndSubTab, updateNotificationViewNotificationStatus, updateNotificationViewSubTab, updateNotificationViewTabState, updateNotificationViewUIState, } from './view/notificationView/notificationViewReducer';
218
218
  import { getExternalNotificationsForSelectedSubTab, getNotificationView, getNotificationsForSelectedSubTab, } from './view/notificationView/notificationViewSelector';
@@ -465,7 +465,7 @@ export {
465
465
  // Bulk Upload Types
466
466
  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,
467
467
  // Bulk Upload Actions
468
- 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, getReparseStatementStatusByAccountId, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, getAccountReconByAccountIdAndSelectedPeriod, toReconciliationTabsType, isAccountReconReport, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, updateStatementProcessingFailed, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, toReconciliationAccountSource, deleteAccountStatement, uploadAccountStatement, parseStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateNodeCollapseState, updateStatementUploadChosen, submitStatementUpdate, clearStatementDateConflict, updateStatementUpdateLocalData, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, setStatementProcessingDismissedToBackground, updateStatementProcessingBackgroundCompletedSteps, };
468
+ 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, getReparseStatementStatusByAccountId, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, getAccountReconByAccountIdAndSelectedPeriod, toReconciliationTabsType, isAccountReconReport, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, updateStatementProcessingFailed, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, toReconciliationAccountSource, STATEMENT_ACCOUNT_SCOPES, toStatementAccountScope, toStatementAccountScopeStrict, toStatementBalanceSource, toStatementBalanceSourceStrict, deleteAccountStatement, uploadAccountStatement, parseStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateNodeCollapseState, updateStatementUploadChosen, submitStatementUpdate, clearStatementDateConflict, confirmStatementMapping, confirmStatementMappingSuccess, confirmStatementMappingFailure, clearConfirmStatementMappingConflict, updateStatementUpdateLocalData, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, setStatementProcessingDismissedToBackground, updateStatementProcessingBackgroundCompletedSteps, };
469
469
  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, };
470
470
  export { TOP_EX_TIME_PERIODS };
471
471
  export { toTimeframeTick, mapTimePeriodtoTimeframeTick, toTimePeriod, toAbsoluteDay, toMonthYearPeriodId, convertToPeriod, };
@@ -646,7 +646,7 @@ export { toNotificationModeStrict, updateCommentsNotifications, updateCommentsNo
646
646
  export { toNotificationSubTabTypeStrict, toNotificationTabTypeStrict, fetchNotificationView, fetchNotificationUnreadCount, fetchNotificationUnreadCountSuccess, updateNotificationViewAllNotificationsStatus, updateNotificationViewNotificationStatus, updateNotificationViewTabState, updateNotificationViewCurrentTabAndSubTab, updateNotificationViewSubTab, updateNotificationViewUIState, getNotificationView, getExternalNotificationsForSelectedSubTab, getNotificationsForSelectedSubTab, };
647
647
  export { clearFeatureNotificationView, fetchRegisteredInterests, notifyMeForFeature, getFeatureNotificationView, getRegisteredInterests, getRegisteredInterestsByFeature, isFeatureInterestRegistered, };
648
648
  export { pushToastNotification, getLastNotificationTime, getNotifications, };
649
- export { getEffectiveNotificationPreferences, getNotificationLocalOverrides, getNotificationPreferencesSaveState, getNotificationRegistry, hasUnsavedNotificationPreferences, clearAllNotificationPreferencesView, clearNotificationPreferencesLocalOverrides, saveNotificationPreferences, setGroupChannelMaster, setGroupFrequency, toggleEventChannel, toNotificationChannel, toNotificationFrequency, };
649
+ export { getEffectiveNotificationPreferences, getNotificationLocalOverrides, getNotificationPreferencesSaveState, getNotificationRegistry, hasUnsavedNotificationPreferences, clearAllNotificationPreferencesView, clearNotificationPreferencesLocalOverrides, setGroupFrequency, toggleEventChannel, toNotificationChannel, toNotificationFrequency, };
650
650
  export { getReferralListView, getInviteFormView, toReferralListViewSortKeyType, StatusTypes, AmountStatusTypes, DEFAULT_REFERRER_AMOUNT, fetchReferrals, sendReferralInvite, clearReferrals, saveReferralFormDataInLocalStore, updateReferralListSortUiState, resendReferralInvite, fetchRewardsPlan, getRewardsPlanCard, updateReferViewed, };
651
651
  export { ALL_WEEK_DAYS, SEMI_WEEKLY_REQUIRED_DAYS_COUNT, getMinAllowedEndDate, getRecurringEndDateFromCount, toDayOfWeek, toRecurringFrequency, };
652
652
  export { fetchCockpitContext, fetchCompanyTaskManagerView, fetchTaskManagerMetrics, getCompanyTaskManagerView, createTaskFromTaskGroupTemplate, };
@@ -0,0 +1,37 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
+ import { isConfirmStatementMappingConflictResponse, transformConfirmStatementMappingConflictToState, transformConfirmStatementMappingPayloadToState, } from '../../payload/reconciliationPayload';
5
+ import { confirmStatementMapping, confirmStatementMappingFailure, confirmStatementMappingSuccess, } from '../../reducers/reconciliationViewReducer';
6
+ export const confirmStatementMappingEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(confirmStatementMapping.match), switchMap((action) => {
7
+ const { accountId, selectedPeriod, statementUploadId, accountMappings } = action.payload;
8
+ const confirmMappingApi$ = zeniAPI.postAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/1.0/reconciliation/statements/${statementUploadId}/confirm-mapping`, {
9
+ account_mappings: accountMappings.map((mapping) => ({
10
+ ledger_identifier: mapping.ledgerIdentifier,
11
+ account_id: mapping.accountId,
12
+ })),
13
+ });
14
+ return confirmMappingApi$.pipe(mergeMap((response) => {
15
+ if (isSuccessResponse(response) === true && response.data != null) {
16
+ return of(confirmStatementMappingSuccess({
17
+ accountId,
18
+ selectedPeriod,
19
+ statementUploads: transformConfirmStatementMappingPayloadToState(response.data),
20
+ }));
21
+ }
22
+ const mappingConflict = isConfirmStatementMappingConflictResponse(response)
23
+ ? transformConfirmStatementMappingConflictToState(response)
24
+ : null;
25
+ return of(confirmStatementMappingFailure({
26
+ accountId,
27
+ selectedPeriod,
28
+ error: response.status,
29
+ mappingConflict,
30
+ }));
31
+ }), catchError((error) => of(confirmStatementMappingFailure({
32
+ accountId,
33
+ selectedPeriod,
34
+ error: createZeniAPIStatus('Unexpected Error', 'Confirm Statement Mapping REST API call errored out ' +
35
+ (error instanceof Error ? error.message : String(error))),
36
+ }))));
37
+ }));
@@ -2,17 +2,86 @@ import { of } from 'rxjs';
2
2
  import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
3
  import { toMonthYearPeriodId } from '../../../../commonStateTypes/timePeriod';
4
4
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
5
- import { mapStatementUpdateLocalDataToRequestBody } from '../../helpers/mapStatementUpdateLocalDataToRequestBody';
5
+ import { hasCombinedStatementUpdateLocalData, mapCombinedStatementUpdateLocalDataToRequestBody, mapStatementUpdateLocalDataToRequestBody, } from '../../helpers/mapStatementUpdateLocalDataToRequestBody';
6
6
  import { isStatementDateConflictResponse, transformStatementDateConflictToState, transformUpdateStatementInfoPayloadToState, } from '../../payload/reconciliationPayload';
7
+ import { isCombinedParsedStatementData } from '../../selectors/statementParseViewSelector';
7
8
  import { submitStatementUpdate, submitStatementUpdateFailure, submitStatementUpdateSuccess, updateParsedStatementData, } from '../../reducers/reconciliationViewReducer';
8
9
  export const updateStatementInfoEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(submitStatementUpdate.match), switchMap((action) => {
9
10
  const { accountId, selectedPeriod, statementUploadId } = action.payload;
10
11
  const state = state$.value;
11
12
  const reconciliationView = state.expenseAutomationReconciliationViewState;
12
13
  const accountRecon = reconciliationView.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
13
- const localData = accountRecon?.localData?.statementUpdateLocalData;
14
14
  const parsedStatementData = accountRecon?.parsedStatementData;
15
- if (localData == null || parsedStatementData == null) {
15
+ const isCombined = isCombinedParsedStatementData(parsedStatementData) === true;
16
+ const localDataByUploadId = accountRecon?.localData?.statementUpdateLocalDataByUploadId;
17
+ const localData = accountRecon?.localData?.statementUpdateLocalData;
18
+ if (parsedStatementData == null) {
19
+ return of(submitStatementUpdateFailure({
20
+ accountId,
21
+ selectedPeriod,
22
+ error: createZeniAPIStatus('Missing Data', 'No statement update data found'),
23
+ }));
24
+ }
25
+ if (isCombined === true) {
26
+ if (hasCombinedStatementUpdateLocalData(parsedStatementData, localDataByUploadId) === false ||
27
+ localDataByUploadId == null) {
28
+ return of(submitStatementUpdateFailure({
29
+ accountId,
30
+ selectedPeriod,
31
+ error: createZeniAPIStatus('Missing Data', 'No statement update data found for combined accounts'),
32
+ }));
33
+ }
34
+ const hasInvalidUpdates = Object.values(localDataByUploadId).some((uploadLocalData) => uploadLocalData.statementTransactions.updated.some((txn) => txn.statementTransactionId == null));
35
+ if (hasInvalidUpdates === true) {
36
+ return of(submitStatementUpdateFailure({
37
+ accountId,
38
+ selectedPeriod,
39
+ error: createZeniAPIStatus('Invalid Data', 'One or more edited transactions are missing statement transaction ids'),
40
+ }));
41
+ }
42
+ let body;
43
+ try {
44
+ body = mapCombinedStatementUpdateLocalDataToRequestBody(localDataByUploadId, parsedStatementData);
45
+ }
46
+ catch (error) {
47
+ return of(submitStatementUpdateFailure({
48
+ accountId,
49
+ selectedPeriod,
50
+ error: createZeniAPIStatus('Missing Data', error instanceof Error
51
+ ? error.message
52
+ : 'Failed to build combined statement update body'),
53
+ }));
54
+ }
55
+ const updateStatementApi$ = zeniAPI.putAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/2.0/statement-uploads/${statementUploadId}`, body);
56
+ return updateStatementApi$.pipe(mergeMap((response) => {
57
+ if (isSuccessResponse(response) === true && response.data != null) {
58
+ const nextParsedStatementData = transformUpdateStatementInfoPayloadToState(response.data);
59
+ return of(updateParsedStatementData({
60
+ accountId,
61
+ selectedPeriod,
62
+ parsedStatementData: nextParsedStatementData,
63
+ }), submitStatementUpdateSuccess({
64
+ accountId,
65
+ selectedPeriod,
66
+ }));
67
+ }
68
+ const dateConflict = isStatementDateConflictResponse(response)
69
+ ? transformStatementDateConflictToState(response)
70
+ : null;
71
+ return of(submitStatementUpdateFailure({
72
+ accountId,
73
+ selectedPeriod,
74
+ error: response.status,
75
+ dateConflict,
76
+ }));
77
+ }), catchError((error) => of(submitStatementUpdateFailure({
78
+ accountId,
79
+ selectedPeriod,
80
+ error: createZeniAPIStatus('Unexpected Error', 'Update Statement REST API call errored out ' +
81
+ (error instanceof Error ? error.message : String(error))),
82
+ }))));
83
+ }
84
+ if (localData == null) {
16
85
  return of(submitStatementUpdateFailure({
17
86
  accountId,
18
87
  selectedPeriod,
@@ -31,11 +100,11 @@ export const updateStatementInfoEpic = (actions$, state$, zeniAPI) => actions$.p
31
100
  const updateStatementApi$ = zeniAPI.putAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/2.0/statement-uploads/${statementUploadId}`, body);
32
101
  return updateStatementApi$.pipe(mergeMap((response) => {
33
102
  if (isSuccessResponse(response) === true && response.data != null) {
34
- const parsedStatementData = transformUpdateStatementInfoPayloadToState(response.data);
103
+ const nextParsedStatementData = transformUpdateStatementInfoPayloadToState(response.data);
35
104
  return of(updateParsedStatementData({
36
105
  accountId,
37
106
  selectedPeriod,
38
- parsedStatementData,
107
+ parsedStatementData: nextParsedStatementData,
39
108
  }), submitStatementUpdateSuccess({
40
109
  accountId,
41
110
  selectedPeriod,
@@ -1,14 +1,22 @@
1
1
  import fetch from 'cross-fetch';
2
2
  import { zeniAPI } from '../../../../init';
3
- export default async function uploadAccountStatementIntoDocumentAI(accountType, fileBlob, authParams) {
3
+ function toStatementDocumentType(accountType, isCombinedStatement) {
4
+ if (isCombinedStatement === true) {
5
+ return accountType === 'credit_card'
6
+ ? 'reconciliation_combined_card_statement_upload'
7
+ : 'reconciliation_combined_bank_statement_upload';
8
+ }
9
+ return accountType === 'credit_card'
10
+ ? 'reconciliation_card_statement_upload'
11
+ : 'reconciliation_bank_statement_upload';
12
+ }
13
+ export default async function uploadAccountStatementIntoDocumentAI(accountType, fileBlob, authParams, isCombinedStatement = false) {
4
14
  let statementUpload;
5
15
  const urlEndPoint = `${zeniAPI.apiEndPoints.documentAIMicroServiceBaseUrl}/1.0/processors/statement`;
6
16
  const data = new FormData();
7
17
  data.append('attachment_file_0', fileBlob);
8
18
  const attachment_json = JSON.stringify({
9
- document_type: accountType === 'credit_card'
10
- ? 'reconciliation_card_statement_upload'
11
- : 'reconciliation_bank_statement_upload',
19
+ document_type: toStatementDocumentType(accountType, isCombinedStatement),
12
20
  purpose_id: 'reconciliation',
13
21
  });
14
22
  data.append('attachment_json_0', attachment_json);
@@ -1,6 +1,6 @@
1
1
  import { from, of } from 'rxjs';
2
2
  import { catchError, filter, mergeMap } from 'rxjs/operators';
3
- import { convertToPeriod } from '../../../../commonStateTypes/timePeriod';
3
+ import { convertToPeriod, toMonthYearPeriodId, } from '../../../../commonStateTypes/timePeriod';
4
4
  import { getAccountBase } from '../../../../entity/account/accountSelector';
5
5
  import { updateAccountReconUploadStatement } from '../../../../entity/accountRecon/accountReconReducer';
6
6
  import { toAccountReconKey } from '../../../../entity/accountRecon/accountReconState';
@@ -8,7 +8,7 @@ import { updateFiles } from '../../../../entity/file/fileReducer';
8
8
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
9
9
  import { uploadAccountStatement, uploadAccountStatementFailure, uploadAccountStatementSuccess, } from '../../reducers/reconciliationViewReducer';
10
10
  export const uploadAccountStatementEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(uploadAccountStatement.match), mergeMap((action) => {
11
- const { accountId, selectedPeriod, payload } = action.payload;
11
+ const { accountId, selectedPeriod, payload, statementAccountScope } = action.payload;
12
12
  const { start, end } = convertToPeriod(selectedPeriod, true);
13
13
  const accountBase = getAccountBase(state$.value.accountState, accountId, 'account_reconciliation');
14
14
  if (accountBase == null) {
@@ -19,6 +19,13 @@ export const uploadAccountStatementEpic = (actions$, state$, zeniAPI) => actions
19
19
  }));
20
20
  }
21
21
  const statementType = accountBase.accountType == 'credit_card' ? 'card' : 'bank';
22
+ const localStatementAccountScope = state$.value.expenseAutomationReconciliationViewState
23
+ .accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId]?.localData
24
+ ?.statementAccountScope;
25
+ const resolvedStatementAccountScope = statementAccountScope ??
26
+ localStatementAccountScope ??
27
+ 'single_account';
28
+ const isCombinedStatement = resolvedStatementAccountScope === 'multi_account';
22
29
  const requestPayload = {
23
30
  account_id: accountId,
24
31
  statement_start_date: start.toString(),
@@ -26,6 +33,7 @@ export const uploadAccountStatementEpic = (actions$, state$, zeniAPI) => actions
26
33
  processor_run_id: payload.processor_run_id,
27
34
  file_id: payload.files[0].file_id,
28
35
  statement_type: statementType,
36
+ is_combined_statement: isCombinedStatement,
29
37
  };
30
38
  const uploadAccountStatementApi$ = zeniAPI.postAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/1.0/reconciliation/statements`, requestPayload);
31
39
  return uploadAccountStatementApi$.pipe(mergeMap((response) => {
@@ -1,7 +1,7 @@
1
- import { toStatementUpdateRequestBody } from '../payload/reconciliationPayload';
2
- import { getEffectiveStatementPeriod, mergeStatementParseDeletedTransactionIds, } from '../selectors/statementParseViewSelector';
3
- const prepareStatementUpdateLocalData = (localData, parsedStatementData) => {
4
- const { statementMeta, statementTransactions } = parsedStatementData.statementUpload;
1
+ import { toBulkStatementUpdateRequestBody, toStatementUpdateRequestBody, } from '../payload/reconciliationPayload';
2
+ import { getEffectiveStatementPeriod, getStatementUploadsFromParsedData, isCombinedParsedStatementData, mergeStatementParseDeletedTransactionIds, } from '../selectors/statementParseViewSelector';
3
+ const prepareStatementUpdateLocalData = (localData, statementUpload) => {
4
+ const { statementMeta, statementTransactions } = statementUpload;
5
5
  const statementPeriod = getEffectiveStatementPeriod(statementMeta, localData.statementMeta);
6
6
  const localDeletedIds = localData.statementTransactions?.deletedIds ?? [];
7
7
  const currentTransactionIds = new Set(statementTransactions
@@ -27,4 +27,28 @@ const prepareStatementUpdateLocalData = (localData, parsedStatementData) => {
27
27
  },
28
28
  };
29
29
  };
30
- export const mapStatementUpdateLocalDataToRequestBody = (localData, parsedStatementData) => toStatementUpdateRequestBody(prepareStatementUpdateLocalData(localData, parsedStatementData));
30
+ export const mapStatementUpdateLocalDataToRequestBody = (localData, parsedStatementData) => toStatementUpdateRequestBody(prepareStatementUpdateLocalData(localData, parsedStatementData.statementUpload));
31
+ export const mapCombinedStatementUpdateLocalDataToRequestBody = (localDataByUploadId, parsedStatementData) => {
32
+ const statementUploads = getStatementUploadsFromParsedData(parsedStatementData);
33
+ const updates = statementUploads.map((statementUpload) => {
34
+ const statementUploadId = statementUpload.statementMeta.statementUploadId;
35
+ const localData = localDataByUploadId[statementUploadId];
36
+ if (localData == null) {
37
+ throw new Error(`Missing statement update local data for upload ${statementUploadId}`);
38
+ }
39
+ return {
40
+ statementUploadId,
41
+ localData: prepareStatementUpdateLocalData(localData, statementUpload),
42
+ };
43
+ });
44
+ return toBulkStatementUpdateRequestBody(updates);
45
+ };
46
+ export const hasCombinedStatementUpdateLocalData = (parsedStatementData, localDataByUploadId) => {
47
+ if (isCombinedParsedStatementData(parsedStatementData) === false ||
48
+ localDataByUploadId == null) {
49
+ return false;
50
+ }
51
+ const statementUploads = getStatementUploadsFromParsedData(parsedStatementData);
52
+ return statementUploads.every((statementUpload) => localDataByUploadId[statementUpload.statementMeta.statementUploadId] !=
53
+ null);
54
+ };
@@ -1,6 +1,7 @@
1
1
  import { convertToPeriod, } from '../../../commonStateTypes/timePeriod';
2
2
  import { toTransactionsToReviewPayload, } from '../../../entity/accountRecon/accountReconPayload';
3
3
  import { toMatchedTransactionPayload, } from '../../../entity/transaction/payloadTypes/reconciliationTransactionPayloads';
4
+ import { toStatementBalanceSourceStrict, } from '../types/reconciliationViewState';
4
5
  export function createSaveReconciliationPayloadBasedOnActionAndMethod(state, selectedPeriod, localData, accountReconciliationEntity, action, method) {
5
6
  const { balance, initialClearedBalance } = accountReconciliationEntity;
6
7
  const { expenseAutomationReconciliationViewState: { selectedAccountId, reconTabsState: { reconcile: { localData: { selectedTransactionIds }, }, }, }, } = state;
@@ -67,10 +68,58 @@ function createReviewTransactionPayload(accountReconciliationEntity) {
67
68
  });
68
69
  return reviewTransactionsPayload;
69
70
  }
71
+ export function isParseStatementCombinedResponsePayload(payload) {
72
+ return ('statement_uploads' in payload &&
73
+ Array.isArray(payload.statement_uploads) &&
74
+ payload.statement_uploads.length > 0);
75
+ }
76
+ export function isUpdateStatementInfoCombinedResponsePayload(payload) {
77
+ return ('statement_uploads' in payload &&
78
+ Array.isArray(payload.statement_uploads) &&
79
+ payload.statement_uploads.length > 0);
80
+ }
70
81
  export function isStatementDateConflictResponse(response) {
71
82
  return response.status.code === 409 && response.error_code != null;
72
83
  }
84
+ function transformConfirmedCombinedStatementUploadsToState(statementUploads) {
85
+ return (statementUploads ?? []).map((statementUpload) => ({
86
+ accountId: statementUpload.account_id,
87
+ isCombinedStatementAnchor: statementUpload.is_combined_statement_anchor,
88
+ ledgerIdentifiers: statementUpload.ledger_identifiers ?? [],
89
+ statementUploadId: statementUpload.statement_upload_id,
90
+ }));
91
+ }
92
+ function transformCombinedStatementDetailsToState(details) {
93
+ if (details == null) {
94
+ return undefined;
95
+ }
96
+ return {
97
+ combinedStatementGroupId: details.combined_statement_group_id,
98
+ isMappingConfirmed: details.is_mapping_confirmed,
99
+ accounts: (details.accounts ?? []).map((account) => ({
100
+ ledgerIdentifier: account.ledger_identifier,
101
+ accountName: account.account_name,
102
+ accountType: account.account_type,
103
+ maskedAccountNumber: account.masked_account_number,
104
+ openingBalance: account.opening_balance,
105
+ closingBalance: account.closing_balance,
106
+ transactionCount: account.transaction_count,
107
+ isUploadContext: account.is_upload_context,
108
+ existingStatementStatus: account.existing_statement_status ?? null,
109
+ suggestion: account.suggestion != null
110
+ ? {
111
+ accountId: account.suggestion.account_id,
112
+ accountName: account.suggestion.account_name,
113
+ matchedBy: account.suggestion.matched_by,
114
+ matchConfidence: account.suggestion.match_confidence,
115
+ }
116
+ : null,
117
+ })),
118
+ statementUploads: transformConfirmedCombinedStatementUploadsToState(details.statement_uploads),
119
+ };
120
+ }
73
121
  function transformStatementUploadPayloadToState(statementUploadPayload) {
122
+ const balanceSource = toStatementBalanceSourceStrict(statementUploadPayload.statement_meta.balance_source);
74
123
  return {
75
124
  account: {
76
125
  accountId: statementUploadPayload.account.account_id,
@@ -96,6 +145,12 @@ function transformStatementUploadPayloadToState(statementUploadPayload) {
96
145
  statementUploadId: statementUploadPayload.statement_meta.statement_upload_id,
97
146
  totalDeposits: statementUploadPayload.statement_meta.total_deposits,
98
147
  totalPayments: statementUploadPayload.statement_meta.total_payments,
148
+ isCombinedStatement: statementUploadPayload.statement_meta.is_combined_statement ??
149
+ undefined,
150
+ isCombinedStatementAnchor: statementUploadPayload.statement_meta.is_combined_statement_anchor ??
151
+ undefined,
152
+ combinedStatementGroupId: statementUploadPayload.statement_meta.combined_statement_group_id ?? undefined,
153
+ ...(balanceSource != null ? { balanceSource } : {}),
99
154
  },
100
155
  statementTransactions: (statementUploadPayload.statement_transactions ?? []).map((txn) => ({
101
156
  amount: txn.amount,
@@ -117,6 +172,7 @@ function transformStatementUploadPayloadToState(statementUploadPayload) {
117
172
  transactionMemo: txn.transaction_memo,
118
173
  })),
119
174
  aiSummary: transformAiSummaryPayloadToState(statementUploadPayload.ai_summary),
175
+ combinedStatementDetails: transformCombinedStatementDetailsToState(statementUploadPayload.combined_statement_details),
120
176
  };
121
177
  }
122
178
  function transformPreviousReconciliationInfoToState(payload) {
@@ -177,11 +233,45 @@ export function transformStatementDateConflictToState(response) {
177
233
  };
178
234
  }
179
235
  export function transformParseStatementPayloadToState(payload) {
236
+ if (isParseStatementCombinedResponsePayload(payload) === true) {
237
+ const statementUploads = payload.statement_uploads.map(transformStatementUploadPayloadToState);
238
+ const anchorUpload = statementUploads.find((upload) => upload.statementMeta.isCombinedStatementAnchor === true) ?? statementUploads[0];
239
+ return {
240
+ statementUpload: anchorUpload,
241
+ statementUploads,
242
+ };
243
+ }
180
244
  return {
181
245
  statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
182
246
  };
183
247
  }
248
+ export function isConfirmStatementMappingConflictResponse(response) {
249
+ return response.status.code === 409;
250
+ }
251
+ export function transformConfirmStatementMappingPayloadToState(payload) {
252
+ return transformConfirmedCombinedStatementUploadsToState(payload.statement_uploads);
253
+ }
254
+ export function transformConfirmStatementMappingConflictToState(response) {
255
+ if (isConfirmStatementMappingConflictResponse(response) === false) {
256
+ return null;
257
+ }
258
+ return {
259
+ collidingAccountId: response.colliding_account_id != null
260
+ ? response.colliding_account_id
261
+ : undefined,
262
+ collidingLedgerIdentifiers: response.colliding_ledger_identifiers ?? [],
263
+ previousReconciliationInfo: transformPreviousReconciliationInfoToState(response.previous_reconciliation_info),
264
+ };
265
+ }
184
266
  export function transformUpdateStatementInfoPayloadToState(payload) {
267
+ if (isUpdateStatementInfoCombinedResponsePayload(payload) === true) {
268
+ const statementUploads = payload.statement_uploads.map(transformStatementUploadPayloadToState);
269
+ const anchorUpload = statementUploads.find((upload) => upload.statementMeta.isCombinedStatementAnchor === true) ?? statementUploads[0];
270
+ return {
271
+ statementUpload: anchorUpload,
272
+ statementUploads,
273
+ };
274
+ }
185
275
  return {
186
276
  statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
187
277
  };
@@ -221,3 +311,19 @@ export function transformStatementUpdateStateToPayload(localData) {
221
311
  export function toStatementUpdateRequestBody(localData) {
222
312
  return transformStatementUpdateStateToPayload(localData);
223
313
  }
314
+ export function transformBulkStatementUpdateStateToPayload(updates) {
315
+ return {
316
+ statement_uploads: updates.map(({ localData, statementUploadId }) => {
317
+ const body = transformStatementUpdateStateToPayload(localData);
318
+ return {
319
+ statement_upload_id: statementUploadId,
320
+ statement_meta: body.statement_meta,
321
+ statement_transactions: body.statement_transactions,
322
+ };
323
+ }),
324
+ };
325
+ }
326
+ /** Bulk PUT body for combined multi-account Confirm & Save. */
327
+ export function toBulkStatementUpdateRequestBody(updates) {
328
+ return transformBulkStatementUpdateStateToPayload(updates);
329
+ }