@zeniai/client-epic-state 5.2.34-beta0ND → 5.2.35-beta0MM

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 (114) hide show
  1. package/lib/entity/actualMatching/actualMatchingPayload.d.ts +25 -0
  2. package/lib/entity/actualMatching/actualMatchingPayload.js +43 -0
  3. package/lib/entity/actualMatching/actualMatchingReducer.d.ts +8 -0
  4. package/lib/entity/actualMatching/actualMatchingReducer.js +33 -0
  5. package/lib/entity/actualMatching/actualMatchingSelector.d.ts +3 -0
  6. package/lib/entity/actualMatching/actualMatchingSelector.js +6 -0
  7. package/lib/entity/actualMatching/actualMatchingState.d.ts +22 -0
  8. package/lib/entity/actualMatching/actualMatchingState.js +2 -0
  9. package/lib/entity/actualMatching/actualMatchingTypes.d.ts +1 -0
  10. package/lib/entity/actualMatching/actualMatchingTypes.js +2 -0
  11. package/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +29 -0
  12. package/lib/entity/jeSchedules/jeSchedulesPayload.js +49 -0
  13. package/lib/entity/jeSchedules/jeSchedulesState.d.ts +31 -0
  14. package/lib/entity/notificationRegistry/notificationRegistryReducer.d.ts +1 -2
  15. package/lib/entity/notificationRegistry/notificationRegistryReducer.js +9 -20
  16. package/lib/entity/notificationRegistry/notificationRegistrySelector.d.ts +1 -2
  17. package/lib/entity/notificationRegistry/notificationRegistrySelector.js +1 -7
  18. package/lib/entity/notificationRegistry/notificationRegistryState.d.ts +0 -5
  19. package/lib/entity/notificationRegistry/notificationRegistryState.js +1 -7
  20. package/lib/entity/sectionProjectView/sectionProjectViewReducer.js +1 -3
  21. package/lib/epic.d.ts +8 -1
  22. package/lib/epic.js +18 -4
  23. package/lib/esm/entity/actualMatching/actualMatchingPayload.js +40 -0
  24. package/lib/esm/entity/actualMatching/actualMatchingReducer.js +30 -0
  25. package/lib/esm/entity/actualMatching/actualMatchingSelector.js +3 -0
  26. package/lib/esm/entity/actualMatching/actualMatchingState.js +1 -0
  27. package/lib/esm/entity/actualMatching/actualMatchingTypes.js +1 -0
  28. package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +49 -0
  29. package/lib/esm/entity/notificationRegistry/notificationRegistryReducer.js +9 -20
  30. package/lib/esm/entity/notificationRegistry/notificationRegistrySelector.js +0 -5
  31. package/lib/esm/entity/notificationRegistry/notificationRegistryState.js +0 -5
  32. package/lib/esm/entity/sectionProjectView/sectionProjectViewReducer.js +1 -3
  33. package/lib/esm/epic.js +18 -4
  34. package/lib/esm/index.js +10 -6
  35. package/lib/esm/reducer.js +6 -0
  36. package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +2 -4
  37. package/lib/esm/view/aiCfoView/epics/fetchRoutineRunsEpic.js +1 -3
  38. package/lib/esm/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.js +46 -0
  39. package/lib/esm/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.js +35 -0
  40. package/lib/esm/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingPageEpic.js +7 -0
  41. package/lib/esm/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +52 -0
  42. package/lib/esm/view/expenseAutomationView/epics/actualMatching/searchMatchAccrualsEpic.js +44 -0
  43. package/lib/esm/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.js +73 -0
  44. package/lib/esm/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +52 -0
  45. package/lib/esm/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +28 -11
  46. package/lib/esm/view/expenseAutomationView/epics/common/refreshExpenseAutomationCurrentTabEpic.js +9 -1
  47. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/prefetchOtherJeSchedulesTabEpic.js +3 -1
  48. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +5 -0
  49. package/lib/esm/view/expenseAutomationView/expenseAutomationViewSelector.js +22 -7
  50. package/lib/esm/view/expenseAutomationView/payload/actualMatchingPayload.js +68 -0
  51. package/lib/esm/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +364 -0
  52. package/lib/esm/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.js +1 -0
  53. package/lib/esm/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +281 -0
  54. package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +3 -0
  55. package/lib/esm/view/expenseAutomationView/types/actualMatchingViewState.js +32 -0
  56. package/lib/esm/view/expenseAutomationView/types/jeSchedulesViewState.js +5 -1
  57. package/lib/esm/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +7 -20
  58. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewReducer.js +17 -43
  59. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewSelector.js +4 -24
  60. package/lib/esm/view/settingsView/epic/fetchNotificationSettingsEpic.js +2 -12
  61. package/lib/index.d.ts +16 -8
  62. package/lib/index.js +78 -55
  63. package/lib/reducer.d.ts +2 -0
  64. package/lib/reducer.js +6 -0
  65. package/lib/rootStateTypes.d.ts +4 -0
  66. package/lib/view/aiCfoView/aiCfoViewReducer.js +2 -4
  67. package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +1 -1
  68. package/lib/view/aiCfoView/epics/fetchRoutineRunsEpic.js +1 -3
  69. package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.d.ts +9 -0
  70. package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.js +50 -0
  71. package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.d.ts +12 -0
  72. package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.js +39 -0
  73. package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingPageEpic.d.ts +5 -0
  74. package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingPageEpic.js +11 -0
  75. package/lib/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.d.ts +8 -0
  76. package/lib/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +56 -0
  77. package/lib/view/expenseAutomationView/epics/actualMatching/searchMatchAccrualsEpic.d.ts +8 -0
  78. package/lib/view/expenseAutomationView/epics/actualMatching/searchMatchAccrualsEpic.js +48 -0
  79. package/lib/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.d.ts +8 -0
  80. package/lib/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.js +77 -0
  81. package/lib/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.d.ts +8 -0
  82. package/lib/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +56 -0
  83. package/lib/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.d.ts +2 -1
  84. package/lib/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +28 -11
  85. package/lib/view/expenseAutomationView/epics/common/refreshExpenseAutomationCurrentTabEpic.d.ts +2 -1
  86. package/lib/view/expenseAutomationView/epics/common/refreshExpenseAutomationCurrentTabEpic.js +9 -1
  87. package/lib/view/expenseAutomationView/epics/jeSchedule/prefetchOtherJeSchedulesTabEpic.js +3 -1
  88. package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.d.ts +2 -1
  89. package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +5 -0
  90. package/lib/view/expenseAutomationView/expenseAutomationViewSelector.js +22 -7
  91. package/lib/view/expenseAutomationView/payload/actualMatchingPayload.d.ts +85 -0
  92. package/lib/view/expenseAutomationView/payload/actualMatchingPayload.js +74 -0
  93. package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.d.ts +74 -0
  94. package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +368 -0
  95. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +4 -4
  96. package/lib/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.d.ts +83 -0
  97. package/lib/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.js +2 -0
  98. package/lib/view/expenseAutomationView/selectorTypes/expenseAutomationViewSelectorTypes.d.ts +2 -0
  99. package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.d.ts +29 -0
  100. package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +296 -0
  101. package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +3 -0
  102. package/lib/view/expenseAutomationView/types/actualMatchingViewState.d.ts +99 -0
  103. package/lib/view/expenseAutomationView/types/actualMatchingViewState.js +38 -0
  104. package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +1 -1
  105. package/lib/view/expenseAutomationView/types/jeSchedulesViewState.js +5 -1
  106. package/lib/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +6 -19
  107. package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.d.ts +5 -8
  108. package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.js +17 -43
  109. package/lib/view/notificationPreferencesView/notificationPreferencesViewSelector.d.ts +0 -4
  110. package/lib/view/notificationPreferencesView/notificationPreferencesViewSelector.js +5 -30
  111. package/lib/view/notificationPreferencesView/notificationPreferencesViewState.d.ts +3 -4
  112. package/lib/view/settingsView/epic/fetchNotificationSettingsEpic.js +2 -12
  113. package/lib/view/settingsView/settingsViewPayload.d.ts +0 -2
  114. package/package.json +1 -1
package/lib/epic.js CHANGED
@@ -53,21 +53,21 @@ const acceptMasterTOSEpic_1 = require("./view/aiCfoView/epics/acceptMasterTOSEpi
53
53
  const createSessionAndSubmitEpic_1 = require("./view/aiCfoView/epics/createSessionAndSubmitEpic");
54
54
  const createSessionEpic_1 = require("./view/aiCfoView/epics/createSessionEpic");
55
55
  const deleteChatSessionEpic_1 = require("./view/aiCfoView/epics/deleteChatSessionEpic");
56
- const deleteRoutineEpic_1 = require("./view/aiCfoView/epics/deleteRoutineEpic");
57
56
  const deleteSkillEpic_1 = require("./view/aiCfoView/epics/deleteSkillEpic");
58
57
  const fetchChatHistoryEpic_1 = require("./view/aiCfoView/epics/fetchChatHistoryEpic");
59
58
  const fetchChatSessionsForUserEpic_1 = require("./view/aiCfoView/epics/fetchChatSessionsForUserEpic");
60
- const fetchRoutineRunsEpic_1 = require("./view/aiCfoView/epics/fetchRoutineRunsEpic");
61
- const fetchRoutinesEpic_1 = require("./view/aiCfoView/epics/fetchRoutinesEpic");
62
59
  const fetchSkillDetailEpic_1 = require("./view/aiCfoView/epics/fetchSkillDetailEpic");
63
60
  const fetchSkillVersionBodyEpic_1 = require("./view/aiCfoView/epics/fetchSkillVersionBodyEpic");
64
61
  const fetchSkillVersionsEpic_1 = require("./view/aiCfoView/epics/fetchSkillVersionsEpic");
65
62
  const fetchSkillsEpic_1 = require("./view/aiCfoView/epics/fetchSkillsEpic");
66
63
  const fetchSuggestedQuestionsEpic_1 = require("./view/aiCfoView/epics/fetchSuggestedQuestionsEpic");
64
+ const deleteRoutineEpic_1 = require("./view/aiCfoView/epics/deleteRoutineEpic");
65
+ const fetchRoutineRunsEpic_1 = require("./view/aiCfoView/epics/fetchRoutineRunsEpic");
66
+ const fetchRoutinesEpic_1 = require("./view/aiCfoView/epics/fetchRoutinesEpic");
67
67
  const runRoutineEpic_1 = require("./view/aiCfoView/epics/runRoutineEpic");
68
68
  const saveRoutineEpic_1 = require("./view/aiCfoView/epics/saveRoutineEpic");
69
- const saveSkillEpic_1 = require("./view/aiCfoView/epics/saveSkillEpic");
70
69
  const setRoutineEnabledEpic_1 = require("./view/aiCfoView/epics/setRoutineEnabledEpic");
70
+ const saveSkillEpic_1 = require("./view/aiCfoView/epics/saveSkillEpic");
71
71
  const setSkillVisibilityEpic_1 = require("./view/aiCfoView/epics/setSkillVisibilityEpic");
72
72
  const stopSubmitEpic_1 = require("./view/aiCfoView/epics/stopSubmitEpic");
73
73
  const stopSubmitQuestionEpic_1 = require("./view/aiCfoView/epics/stopSubmitQuestionEpic");
@@ -199,6 +199,13 @@ const updateCombinedStatementInfoEpic_1 = require("./view/expenseAutomationView/
199
199
  const updateReconcileTabLocalDataEpic_1 = require("./view/expenseAutomationView/epics/accountRecon/updateReconcileTabLocalDataEpic");
200
200
  const updateStatementInfoEpic_1 = require("./view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic");
201
201
  const uploadAccountStatementEpic_1 = require("./view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic");
202
+ const fetchActualMatchingEpic_1 = require("./view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic");
203
+ const fetchActualMatchingMatchEpic_1 = require("./view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic");
204
+ const fetchActualMatchingPageEpic_1 = require("./view/expenseAutomationView/epics/actualMatching/fetchActualMatchingPageEpic");
205
+ const matchAndReverseAccrualsEpic_1 = require("./view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic");
206
+ const searchMatchAccrualsEpic_1 = require("./view/expenseAutomationView/epics/actualMatching/searchMatchAccrualsEpic");
207
+ const searchMatchTransactionsEpic_1 = require("./view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic");
208
+ const undoReversalAccrualsEpic_1 = require("./view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic");
202
209
  const fetchAllExpenseAutomationTabsEpic_1 = require("./view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic");
203
210
  const refreshExpenseAutomationCurrentTabEpic_1 = require("./view/expenseAutomationView/epics/common/refreshExpenseAutomationCurrentTabEpic");
204
211
  const fetchFluxAnalysisViewEpic_1 = require("./view/expenseAutomationView/epics/fluxAnalysis/fetchFluxAnalysisViewEpic");
@@ -1004,6 +1011,9 @@ const ALL_EPICS = [
1004
1011
  fetchEntityRecommendationsByTransactionIdEpic_1.fetchEntityRecommendationsByTransactionIdEpic,
1005
1012
  fetchEntityRecommendationsForLineUpdateEpic_1.fetchEntityRecommendationsForLineUpdateEpic,
1006
1013
  fetchExcludedResourcesEpic_1.fetchExcludedResourcesEpic,
1014
+ fetchActualMatchingEpic_1.fetchActualMatchingEpic,
1015
+ fetchActualMatchingMatchEpic_1.fetchActualMatchingMatchEpic,
1016
+ fetchActualMatchingPageEpic_1.fetchActualMatchingPageEpic,
1007
1017
  fetchFluxAnalysisViewEpic_1.fetchFluxAnalysisViewEpic,
1008
1018
  initializeTransactionCategorizationLocalDataEpic_1.initializeTransactionCategorizationViewLocalDataEpic,
1009
1019
  fetchJeSchedulesEpic_1.fetchJeSchedulesEpic,
@@ -1298,6 +1308,7 @@ const ALL_EPICS = [
1298
1308
  lockChargeCardsEpic_1.lockChargeCardsEpic,
1299
1309
  markAsCompleteScheduleDetailEpic_1.markAsCompleteScheduleDetailEpic,
1300
1310
  markTransactionAsNotMiscategorizedEpic_2.markTransactionAsNotMiscategorizedEpic,
1311
+ matchAndReverseAccrualsEpic_1.matchAndReverseAccrualsEpic,
1301
1312
  notifyMeForFeatureEpic_1.notifyMeForFeatureEpic,
1302
1313
  oneTimeAccrualActionsEpic_1.oneTimeAccrualActionsEpic,
1303
1314
  parallelFetchAccountTransactionListEpic_1.parallelFetchAccountTransactionListEpic,
@@ -1406,6 +1417,8 @@ const ALL_EPICS = [
1406
1417
  saveVendorFirstReviewViewEpic_1.saveVendorFirstReviewViewEpic,
1407
1418
  saveVendorsTabVendorEpic_1.saveVendorsTabVendorEpic,
1408
1419
  scheduleTenantCreditScoreCronEpic_1.scheduleTenantCreditScoreCronEpic,
1420
+ searchMatchAccrualsEpic_1.searchMatchAccrualsEpic,
1421
+ searchMatchTransactionsEpic_1.searchMatchTransactionsEpic,
1409
1422
  searchTransactionsForManualMatchEpic_1.searchTransactionsForManualMatchEpic,
1410
1423
  searchTransactionsForNewScheduleEpic_1.searchTransactionsForNewScheduleEpic,
1411
1424
  seedAiCardCreationFormDraftEpic_1.seedAiCardCreationFormDraftEpic,
@@ -1445,6 +1458,7 @@ const ALL_EPICS = [
1445
1458
  treasuryTransferMoneyEpic_1.treasuryTransferMoneyEpic,
1446
1459
  triggerAiAccountantJobEpic_1.triggerAiAccountantJobEpic,
1447
1460
  triggerReviewTabRefetchEpic_1.triggerReviewTabRefetchEpic,
1461
+ undoReversalAccrualsEpic_1.undoReversalAccrualsEpic,
1448
1462
  unlinkPaymentAccountEpic_1.unlinkPaymentAccountEpic,
1449
1463
  unlockChargeCardEpic_1.unlockChargeCardEpic,
1450
1464
  unlockChargeCardsEpic_1.unlockChargeCardsEpic,
@@ -0,0 +1,40 @@
1
+ import { toAmount } from '../../commonStateTypes/amount';
2
+ import { toJEOneTimeAccrual, } from '../jeSchedules/jeSchedulesPayload';
3
+ const USD_CURRENCY_CODE = 'USD';
4
+ const USD_CURRENCY_SYMBOL = '$';
5
+ const MATCH_KINDS = [
6
+ 'auto_reversed',
7
+ 'pending_review',
8
+ 'manually_reversed',
9
+ ];
10
+ function toMatchKind(raw) {
11
+ if (MATCH_KINDS.includes(raw)) {
12
+ return raw;
13
+ }
14
+ console.error(`Unknown ActualMatchingMatchKind: ${raw}`);
15
+ return 'auto_reversed';
16
+ }
17
+ export function toActualMatchingMatch(payload) {
18
+ const currencyCode = payload.currency_code != null && payload.currency_code !== ''
19
+ ? payload.currency_code
20
+ : USD_CURRENCY_CODE;
21
+ const currencySymbol = payload.currency_symbol != null && payload.currency_symbol !== ''
22
+ ? payload.currency_symbol
23
+ : currencyCode === USD_CURRENCY_CODE
24
+ ? USD_CURRENCY_SYMBOL
25
+ : currencyCode;
26
+ return {
27
+ matchId: payload.match_id,
28
+ transactionType: (payload.transaction_type || '').toLowerCase(),
29
+ transactionIntegrationId: payload.transaction_integration_id,
30
+ transactionDate: payload.transaction_date ?? undefined,
31
+ vendorId: payload.vendor_id ?? undefined,
32
+ vendorName: payload.vendor_name ?? '',
33
+ kind: toMatchKind(payload.kind),
34
+ matchTier: payload.match_tier ?? undefined,
35
+ matchShape: payload.match_shape ?? undefined,
36
+ accruedAmount: toAmount(payload.accrued_amount, currencyCode, currencySymbol),
37
+ actualAmount: toAmount(payload.actual_amount, currencyCode, currencySymbol),
38
+ members: payload.members.map(toJEOneTimeAccrual),
39
+ };
40
+ }
@@ -0,0 +1,30 @@
1
+ import { createSlice } from '@reduxjs/toolkit';
2
+ import { clearAll } from '../../rootActions';
3
+ import { toActualMatchingMatch, } from './actualMatchingPayload';
4
+ export const initialState = {
5
+ byMatchId: {},
6
+ };
7
+ const actualMatching = createSlice({
8
+ name: 'actualMatching',
9
+ initialState,
10
+ reducers: {
11
+ updateActualMatchingMatches: {
12
+ prepare(matches) {
13
+ return { payload: { matches } };
14
+ },
15
+ reducer(draft, action) {
16
+ action.payload.matches.forEach((payload) => {
17
+ const match = toActualMatchingMatch(payload);
18
+ draft.byMatchId[match.matchId] = match;
19
+ });
20
+ },
21
+ },
22
+ },
23
+ extraReducers: (builder) => {
24
+ builder.addCase(clearAll, (draft) => {
25
+ Object.assign(draft, initialState);
26
+ });
27
+ },
28
+ });
29
+ export const { updateActualMatchingMatches } = actualMatching.actions;
30
+ export default actualMatching.reducer;
@@ -0,0 +1,3 @@
1
+ export function getActualMatchingMatchById(actualMatchingState, matchId) {
2
+ return actualMatchingState.byMatchId[matchId];
3
+ }
@@ -444,6 +444,52 @@ function toJEOneTimeAccrualAiSuggestion(payload, currencyCode) {
444
444
  : undefined,
445
445
  };
446
446
  }
447
+ function toJEOneTimeAccrualCleared(payload, currencyCode) {
448
+ if (payload == null) {
449
+ return undefined;
450
+ }
451
+ return {
452
+ matchedTransactionIntegrationId: payload.matched_transaction_integration_id ?? undefined,
453
+ matchedTransactionId: payload.matched_transaction_id ?? undefined,
454
+ matchedTransactionType: payload.matched_transaction_type ?? undefined,
455
+ matchedLineId: payload.matched_line_id ?? undefined,
456
+ consumedLineIds: payload.consumed_line_ids ?? undefined,
457
+ matchedAmount: payload.matched_amount != null
458
+ ? toOneTimeAccrualAmount(payload.matched_amount, currencyCode)
459
+ : undefined,
460
+ groupSum: payload.group_sum != null
461
+ ? toOneTimeAccrualAmount(payload.group_sum, currencyCode)
462
+ : undefined,
463
+ accrualIds: payload.accrual_ids ?? undefined,
464
+ reversedAt: payload.reversed_at != null ? date(payload.reversed_at) : undefined,
465
+ matchedTransactionDate: payload.matched_transaction_date != null
466
+ ? date(payload.matched_transaction_date)
467
+ : undefined,
468
+ matchTier: payload.match_tier ?? undefined,
469
+ matchShape: payload.match_shape ?? undefined,
470
+ matchedTransactionSyncToken: payload.matched_transaction_sync_token ?? undefined,
471
+ };
472
+ }
473
+ function toJEOneTimeAccrualMatchSuggestion(payload, currencyCode) {
474
+ if (payload == null) {
475
+ return undefined;
476
+ }
477
+ return {
478
+ resolution: payload.resolution ?? undefined,
479
+ matchTier: payload.match_tier ?? undefined,
480
+ matchedTransactionIntegrationId: payload.matched_transaction_integration_id ?? undefined,
481
+ matchedTransactionId: payload.matched_transaction_id ?? undefined,
482
+ matchedTransactionType: payload.matched_transaction_type ?? undefined,
483
+ matchedLineId: payload.matched_line_id ?? undefined,
484
+ matchedAmount: payload.matched_amount != null
485
+ ? toOneTimeAccrualAmount(payload.matched_amount, currencyCode)
486
+ : undefined,
487
+ matchedTransactionDate: payload.matched_transaction_date != null
488
+ ? date(payload.matched_transaction_date)
489
+ : undefined,
490
+ matchedTransactionSyncToken: payload.matched_transaction_sync_token ?? undefined,
491
+ };
492
+ }
447
493
  export function toJEOneTimeAccrual(payload) {
448
494
  return {
449
495
  accrualId: payload._id,
@@ -460,6 +506,8 @@ export function toJEOneTimeAccrual(payload) {
460
506
  profileSnapshot: toJEOneTimeAccrualProfileSnapshot(payload.profile_snapshot, payload.currency),
461
507
  isIgnored: payload.is_ignored === true,
462
508
  aiSuggestion: toJEOneTimeAccrualAiSuggestion(payload.ai_suggestion, payload.currency),
509
+ cleared: toJEOneTimeAccrualCleared(payload.cleared, payload.currency),
510
+ matchSuggestion: toJEOneTimeAccrualMatchSuggestion(payload.match_suggestion, payload.currency),
463
511
  // Exclusive by contract: a scheduled row reverses on expectedReversalDate and bills never
464
512
  // drive it, so the two never need reconciling. Defaulting to on_bill_match matches the
465
513
  // create path's default when the field is absent on an older document.
@@ -487,6 +535,7 @@ export function toJEOneTimeAccrual(payload) {
487
535
  transactionIntegrationId: payload.transaction_integration_id ?? undefined,
488
536
  reversalTransactionId: payload.reversal_transaction_id ?? undefined,
489
537
  createdBy: toJEOneTimeAccrualCreator(payload.created_by_user),
538
+ reversedBy: toJEOneTimeAccrualCreator(payload.reversed_by_user),
490
539
  };
491
540
  }
492
541
  // The accrual wire format carries a currency CODE but no symbol, so the symbol has to be derived.
@@ -1,7 +1,6 @@
1
1
  import { createSlice } from '@reduxjs/toolkit';
2
2
  import { clearAll } from '../../rootActions';
3
3
  import { mapNotificationRegistryPayloadToRegistry, } from './notificationRegistryPayload';
4
- import { NOTIFICATION_DOMAINS, } from './notificationRegistryState';
5
4
  export const initialState = { registryEpoch: 0 };
6
5
  const notificationRegistry = createSlice({
7
6
  name: 'notificationRegistry',
@@ -20,24 +19,16 @@ const notificationRegistry = createSlice({
20
19
  // `task_checklist_registry` CLEARS so tenant B doesn't inherit A's
21
20
  // Task Checklist section. Guarded by the epoch check above so a stale
22
21
  // absent-response can't wipe a fresh registry.
23
- const { registriesByDomain } = action.payload;
24
- // Absent `registriesByDomain` means a pre-domain caller: treat `registry`
25
- // as the task_checklist snapshot so their behaviour is unchanged.
26
- const snapshots = registriesByDomain ?? { task_checklist: action.payload.registry };
27
- draft.registryByDomain = {};
28
- for (const domain of NOTIFICATION_DOMAINS) {
29
- const payload = snapshots[domain];
30
- // Full-replace per domain, and an absent snapshot CLEARS that domain so
31
- // tenant B never inherits A's section. The gates are independent
32
- // server-side, so one domain clearing must not touch the other.
33
- if (payload != null) {
34
- draft.registryByDomain[domain] =
35
- mapNotificationRegistryPayloadToRegistry(payload);
36
- }
22
+ if (action.payload.registry == null) {
23
+ draft.registry = undefined;
24
+ return;
37
25
  }
38
- // Mirrored for consumers that predate the domain-keyed map.
39
- draft.registry = draft.registryByDomain.task_checklist;
40
- return;
26
+ // Full-replace contract: the registry payload is atomic — every fetch
27
+ // returns the complete group/event tree. If the backend ever ships a
28
+ // partial registry response, this write MUST switch to a merge (mirror
29
+ // the preferences slice's `mergePreferences`). Do not assume the
30
+ // current payload is partial without also updating this reducer.
31
+ draft.registry = mapNotificationRegistryPayloadToRegistry(action.payload.registry);
41
32
  },
42
33
  },
43
34
  extraReducers: (builder) => {
@@ -50,8 +41,6 @@ const notificationRegistry = createSlice({
50
41
  // — Cursor Bugbot 67d6918e. Returning `initialState` verbatim would
51
42
  // rewind the counter and let a stale in-flight GET restore A's
52
43
  // registry over B's.
53
- // Drops `registry` and `registryByDomain` together: a tenant switch must
54
- // not leave one domain's section behind.
55
44
  return { registryEpoch: draft.registryEpoch + 1 };
56
45
  });
57
46
  },
@@ -4,8 +4,3 @@
4
4
  // off for this tenant". Both currently surface as `undefined`. Distinguishing
5
5
  // them (e.g. an explicit `gate_off` signal from the server) is a follow-up.
6
6
  export const getNotificationRegistry = (slice) => slice.registry;
7
- // `undefined` conflates gate-off with no-preferences-yet; consumers hide the
8
- // section either way. Falls back to `registry` for task_checklist so state built
9
- // in the pre-domain shape (consumer mocks, older callers) still resolves.
10
- export const getNotificationRegistryForDomain = (slice, domain) => slice.registryByDomain?.[domain] ??
11
- (domain === 'task_checklist' ? slice.registry : undefined);
@@ -1,9 +1,4 @@
1
1
  import { stringToUnion } from '../../commonStateTypes/stringToUnion';
2
- // Wire vocabulary owned by the notifications service, not by this slice.
3
- export const NOTIFICATION_DOMAINS = ['task_checklist', 'commenting'];
4
- // Callers that predate the domain split mean Task Checklist.
5
- export const DEFAULT_NOTIFICATION_DOMAIN = 'task_checklist';
6
- export const toNotificationDomain = (raw) => stringToUnion(raw, NOTIFICATION_DOMAINS);
7
2
  export const NOTIFICATION_CHANNELS = ['email', 'slack', 'in_app'];
8
3
  export const toNotificationChannel = (raw) => stringToUnion(raw, NOTIFICATION_CHANNELS);
9
4
  export const NOTIFICATION_FREQUENCIES = ['instant', 'daily'];
@@ -32,9 +32,7 @@ const sectionProjectView = createSlice({
32
32
  Object.keys(sectionPayload.projects).forEach((projectId) => {
33
33
  const projectPayload = sectionPayload.projects[projectId];
34
34
  // A calculated section is grouped by project with no accounts under it.
35
- const projectAccounts = 'accounts' in projectPayload
36
- ? projectPayload.accounts
37
- : undefined;
35
+ const projectAccounts = 'accounts' in projectPayload ? projectPayload.accounts : undefined;
38
36
  const nestedAccountIds = projectAccounts != null
39
37
  ? getNestedAccountIDHierarchyForAccounts(Object.keys(projectAccounts), accountsMetadata)
40
38
  : [];
package/lib/esm/epic.js CHANGED
@@ -50,21 +50,21 @@ import { acceptMasterTOSEpic, } from './view/aiCfoView/epics/acceptMasterTOSEpic
50
50
  import { createSessionAndSubmitEpic, } from './view/aiCfoView/epics/createSessionAndSubmitEpic';
51
51
  import { createSessionEpic, } from './view/aiCfoView/epics/createSessionEpic';
52
52
  import { deleteChatSessionEpic, } from './view/aiCfoView/epics/deleteChatSessionEpic';
53
- import { deleteRoutineEpic } from './view/aiCfoView/epics/deleteRoutineEpic';
54
53
  import { deleteSkillEpic } from './view/aiCfoView/epics/deleteSkillEpic';
55
54
  import { fetchChatHistoryEpic, } from './view/aiCfoView/epics/fetchChatHistoryEpic';
56
55
  import { fetchChatSessionsForUserEpic, } from './view/aiCfoView/epics/fetchChatSessionsForUserEpic';
57
- import { fetchRoutineRunsEpic } from './view/aiCfoView/epics/fetchRoutineRunsEpic';
58
- import { fetchRoutinesEpic } from './view/aiCfoView/epics/fetchRoutinesEpic';
59
56
  import { fetchSkillDetailEpic } from './view/aiCfoView/epics/fetchSkillDetailEpic';
60
57
  import { fetchSkillVersionBodyEpic } from './view/aiCfoView/epics/fetchSkillVersionBodyEpic';
61
58
  import { fetchSkillVersionsEpic } from './view/aiCfoView/epics/fetchSkillVersionsEpic';
62
59
  import { fetchSkillsEpic, } from './view/aiCfoView/epics/fetchSkillsEpic';
63
60
  import { fetchSuggestedQuestionsEpic, } from './view/aiCfoView/epics/fetchSuggestedQuestionsEpic';
61
+ import { deleteRoutineEpic } from './view/aiCfoView/epics/deleteRoutineEpic';
62
+ import { fetchRoutineRunsEpic } from './view/aiCfoView/epics/fetchRoutineRunsEpic';
63
+ import { fetchRoutinesEpic } from './view/aiCfoView/epics/fetchRoutinesEpic';
64
64
  import { runRoutineEpic } from './view/aiCfoView/epics/runRoutineEpic';
65
65
  import { saveRoutineEpic } from './view/aiCfoView/epics/saveRoutineEpic';
66
- import { saveSkillEpic } from './view/aiCfoView/epics/saveSkillEpic';
67
66
  import { setRoutineEnabledEpic } from './view/aiCfoView/epics/setRoutineEnabledEpic';
67
+ import { saveSkillEpic } from './view/aiCfoView/epics/saveSkillEpic';
68
68
  import { setSkillVisibilityEpic } from './view/aiCfoView/epics/setSkillVisibilityEpic';
69
69
  import { stopSubmitEpic, } from './view/aiCfoView/epics/stopSubmitEpic';
70
70
  import { stopSubmitQuestionEpic, } from './view/aiCfoView/epics/stopSubmitQuestionEpic';
@@ -196,6 +196,13 @@ import { updateCombinedStatementInfoEpic, } from './view/expenseAutomationView/e
196
196
  import { updateReconcileTabLocalDataEpic as updateExpenseAutomationReconciliationBalanceLocalDataEpic, } from './view/expenseAutomationView/epics/accountRecon/updateReconcileTabLocalDataEpic';
197
197
  import { updateStatementInfoEpic, } from './view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic';
198
198
  import { uploadAccountStatementEpic, } from './view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic';
199
+ import { fetchActualMatchingEpic as fetchExpenseAutomationActualMatchingEpic, } from './view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic';
200
+ import { fetchActualMatchingMatchEpic as fetchExpenseAutomationActualMatchingMatchEpic, } from './view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic';
201
+ import { fetchActualMatchingPageEpic as fetchExpenseAutomationActualMatchingPageEpic, } from './view/expenseAutomationView/epics/actualMatching/fetchActualMatchingPageEpic';
202
+ import { matchAndReverseAccrualsEpic, } from './view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic';
203
+ import { searchMatchAccrualsEpic, } from './view/expenseAutomationView/epics/actualMatching/searchMatchAccrualsEpic';
204
+ import { searchMatchTransactionsEpic, } from './view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic';
205
+ import { undoReversalAccrualsEpic, } from './view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic';
199
206
  import { fetchAllExpenseAutomationTabsEpic, } from './view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic';
200
207
  import { refreshExpenseAutomationCurrentTabEpic, } from './view/expenseAutomationView/epics/common/refreshExpenseAutomationCurrentTabEpic';
201
208
  import { fetchFluxAnalysisViewEpic as fetchExpenseAutomationFluxAnalysisViewEpic, } from './view/expenseAutomationView/epics/fluxAnalysis/fetchFluxAnalysisViewEpic';
@@ -1001,6 +1008,9 @@ const ALL_EPICS = [
1001
1008
  fetchEntityRecommendationsByTransactionIdEpic,
1002
1009
  fetchEntityRecommendationsForLineUpdateEpic,
1003
1010
  fetchExcludedResourcesEpic,
1011
+ fetchExpenseAutomationActualMatchingEpic,
1012
+ fetchExpenseAutomationActualMatchingMatchEpic,
1013
+ fetchExpenseAutomationActualMatchingPageEpic,
1004
1014
  fetchExpenseAutomationFluxAnalysisViewEpic,
1005
1015
  fetchExpenseAutomationInitializeTransactionCategorizationViewLocalDataEpic,
1006
1016
  fetchExpenseAutomationJeSchedulesEpic,
@@ -1295,6 +1305,7 @@ const ALL_EPICS = [
1295
1305
  lockChargeCardsEpic,
1296
1306
  markAsCompleteScheduleDetailEpic,
1297
1307
  markTransactionAsNotMiscategorizedEpic,
1308
+ matchAndReverseAccrualsEpic,
1298
1309
  notifyMeForFeatureEpic,
1299
1310
  oneTimeAccrualActionsEpic,
1300
1311
  parallelFetchAccountTransactionListEpic,
@@ -1403,6 +1414,8 @@ const ALL_EPICS = [
1403
1414
  saveVendorFirstReviewViewEpic,
1404
1415
  saveVendorsTabVendorEpic,
1405
1416
  scheduleTenantCreditScoreCronEpic,
1417
+ searchMatchAccrualsEpic,
1418
+ searchMatchTransactionsEpic,
1406
1419
  searchTransactionsForManualMatchEpic,
1407
1420
  searchTransactionsForNewScheduleEpic,
1408
1421
  seedAiCardCreationFormDraftEpic,
@@ -1442,6 +1455,7 @@ const ALL_EPICS = [
1442
1455
  treasuryTransferMoneyEpic,
1443
1456
  triggerAiAccountantJobEpic,
1444
1457
  triggerReviewTabRefetchEpic,
1458
+ undoReversalAccrualsEpic,
1445
1459
  unlinkPaymentAccountEpic,
1446
1460
  unlockChargeCardEpic,
1447
1461
  unlockChargeCardsEpic,
package/lib/esm/index.js CHANGED
@@ -64,8 +64,8 @@ import { ALL_JE_SCHEDULE_IGNORE_REASONS, ALL_JE_SCHEDULE_REVERT_REASONS, ALL_ONE
64
64
  import { ALL_MONTH_END_CLOSE_CHECKS_FREQUENCY, } from './entity/monthEndCloseChecks/monthEndCloseChecksState';
65
65
  import { updateCommentsNotifications, updateCommentsNotificationsStatuses, } from './entity/notification/notificationReducer';
66
66
  import { toNotificationModeStrict, } from './entity/notification/types/notificationTypes';
67
- import { getNotificationRegistry, getNotificationRegistryForDomain, } from './entity/notificationRegistry/notificationRegistrySelector';
68
- import { DEFAULT_NOTIFICATION_DOMAIN, NOTIFICATION_DOMAINS, toNotificationChannel, toNotificationDomain, toNotificationFrequency, } from './entity/notificationRegistry/notificationRegistryState';
67
+ import { getNotificationRegistry } from './entity/notificationRegistry/notificationRegistrySelector';
68
+ import { toNotificationChannel, toNotificationFrequency, } from './entity/notificationRegistry/notificationRegistryState';
69
69
  import { getPlaidPaymentAccounts } from './entity/paymentAccount/paymentAccountSelector';
70
70
  import { VERIFIED_PAYMENT_ACCOUNT_PROVIDER_VERIFICATION_STATUS, } from './entity/paymentAccount/paymentAccountState';
71
71
  import { closeSnackbar, openSnackbar } from './entity/snackbar/snackbarReducer';
@@ -188,6 +188,7 @@ import { toExpenseAutomationViewType, } from './view/expenseAutomationView/expen
188
188
  import { computeNewScheduleJeDetails } from './view/expenseAutomationView/helpers/newScheduleLocalDataHelper';
189
189
  import { isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardCreditType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, } from './view/expenseAutomationView/helpers/reconciliationHelpers';
190
190
  import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, } from './view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper';
191
+ import { clearActualMatchingView as clearExpenseAutomationActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching as fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchActualMatchingPage as fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateActualMatchingUIState as updateExpenseAutomationActualMatchingUIState, } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
191
192
  import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFluxAnalysisView, updateFluxAnalysisViewPageMetaData, updateFluxAnalysisViewUIState, updateOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview, } from './view/expenseAutomationView/reducers/fluxAnalysisViewReducer';
192
193
  import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearSearchTransactionsForNewSchedule as clearJeSearchTransactionsForNewSchedule, createOneTimeAccrual, createOneTimeAccrualFailure, createOneTimeAccrualSuccess, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, fetchOneTimeAccrual, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, ignoreOneTimeAccrual, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeNewSchedule as initializeJeNewSchedule, initializeJeScheduleLocalData, promoteOneTimeAccrual, removeJeOneTimeAccrualLocalData, removeJeScheduleTransactionKey, resetNewScheduleLocalData as resetJeNewScheduleLocalData, retryJeSchedule as retryExpenseAutomationJESchedule, revertJeSchedule, revertOneTimeAccrual, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData, saveNewSchedule as saveJeNewSchedule, saveNewScheduleFailure as saveJeNewScheduleFailure, saveNewScheduleSuccess as saveJeNewScheduleSuccess, searchTransactionsForNewSchedule as searchJeTransactionsForNewSchedule, searchTransactionsForNewScheduleFailure as searchJeTransactionsForNewScheduleFailure, searchTransactionsForNewScheduleSuccess as searchJeTransactionsForNewScheduleSuccess, toggleJECreatedGroupCollapsed, toggleJEPendingGroupCollapsed, updateJESchedulesUIState as updateExpenseAutomationJESchedulesUIState, updateJEScheduleTypeFilter, updateNewScheduleLocalData as updateJeNewScheduleLocalData, updateJeOneTimeAccrualLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
193
194
  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';
@@ -199,8 +200,9 @@ import { getExpenseAutomationReconciliationView, getLedgerAccountIdsWithStatemen
199
200
  import { getExpenseAutomationTransactionView, getLastTransferEntryReplacement, } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
200
201
  import { applyTransactionFilters } from './view/expenseAutomationView/transactionFilterHelpers';
201
202
  import { TRANSACTION_FILTER_CATEGORIES, } from './view/expenseAutomationView/transactionFilterTypes';
203
+ import { MATCH_ACCRUAL_SEARCH_LIMIT, MATCH_SEARCH_DEBOUNCE_MS, MATCH_TRANSACTION_SEARCH_PAGE_SIZE, toActualMatchingSortKey as toExpenseAutomationActualMatchingSortKey, toMatchAndReverseResultStatus, toUndoReversalResultStatus, } from './view/expenseAutomationView/types/actualMatchingViewState';
202
204
  import { DEFAULT_COMPLETED_SUB_TAB, toCompletedSubTab, } from './view/expenseAutomationView/types/completedSubTab';
203
- import { toJEScheduleSortKey as toExpenseAutomationJEScheduleSortKey, toJEPageTab, } from './view/expenseAutomationView/types/jeSchedulesViewState';
205
+ import { ALL_JE_PAGE_TABS, toJEScheduleSortKey as toExpenseAutomationJEScheduleSortKey, toJEPageTab, } from './view/expenseAutomationView/types/jeSchedulesViewState';
204
206
  import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toMatchSource, toMissingReceiptsTab, } from './view/expenseAutomationView/types/missingReceiptsViewState';
205
207
  import { toMissingReceiptsSortKey as toExpenseAutomationMissingReceiptsSortKey, } from './view/expenseAutomationView/types/missingReceiptsViewState';
206
208
  import { toReconciliationTabsType, } from './view/expenseAutomationView/types/reconciliationViewState';
@@ -234,7 +236,7 @@ import { toAverageMonthsCount } from './view/netBurnOrIncomeStoryCard/epic/updat
234
236
  import { fetchNetBurnOrIncomeStoryCard, updateNetBurnOrIncomeStoryCardSettings, } from './view/netBurnOrIncomeStoryCard/netBurnOrIncomeStoryCardReducer';
235
237
  import { getNetBurnOrIncomeStoryCardReport } from './view/netBurnOrIncomeStoryCard/netBurnOrIncomeStoryCardSelector';
236
238
  import { clearAllNotificationPreferencesView, clearNotificationPreferencesLocalOverrides, saveNotificationPreferences, setGroupChannelMaster, setGroupFrequency, toggleEventChannel, } from './view/notificationPreferencesView/notificationPreferencesViewReducer';
237
- import { getEffectiveNotificationPreferences, getEffectiveNotificationPreferencesForDomain, getNotificationLocalOverrides, getNotificationLocalOverridesForDomain, getNotificationPreferencesSaveState, hasUnsavedNotificationPreferences, hasUnsavedNotificationPreferencesForDomain, } from './view/notificationPreferencesView/notificationPreferencesViewSelector';
239
+ import { getEffectiveNotificationPreferences, getNotificationLocalOverrides, getNotificationPreferencesSaveState, hasUnsavedNotificationPreferences, } from './view/notificationPreferencesView/notificationPreferencesViewSelector';
238
240
  import { fetchNotificationUnreadCount, fetchNotificationUnreadCountSuccess, fetchNotificationView, updateNotificationViewAllNotificationsStatus, updateNotificationViewCurrentTabAndSubTab, updateNotificationViewNotificationStatus, updateNotificationViewSubTab, updateNotificationViewTabState, updateNotificationViewUIState, } from './view/notificationView/notificationViewReducer';
239
241
  import { getExternalNotificationsForSelectedSubTab, getNotificationView, getNotificationsForSelectedSubTab, } from './view/notificationView/notificationViewSelector';
240
242
  import { toNotificationSubTabTypeStrict, toNotificationTabTypeStrict, } from './view/notificationView/notificationViewState';
@@ -489,7 +491,7 @@ export { stringToUnion, stringToUnionStrict };
489
491
  export { fetchMonthEndCloseChecks, fetchMonthClosePerformanceTrend, getMonthEndCloseChecksViewByTenantId, ALL_MONTH_END_CLOSE_CHECKS_FREQUENCY, };
490
492
  export {
491
493
  // Bulk Upload Types
492
- BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, DEFAULT_COMPLETED_SUB_TAB, DEFAULT_TRANSACTION_GROUP, TRANSACTION_GROUPS, toTransactionGroup, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, toExpenseAutomationJEScheduleSortKey, toJEPageTab, toggleJECreatedGroupCollapsed, toggleJEPendingGroupCollapsed, updateJEScheduleTypeFilter, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, updateTransactionGroup, fetchExpenseAutomationMissingReceipts,
494
+ BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, DEFAULT_COMPLETED_SUB_TAB, DEFAULT_TRANSACTION_GROUP, TRANSACTION_GROUPS, toTransactionGroup, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, ALL_JE_PAGE_TABS, MATCH_ACCRUAL_SEARCH_LIMIT, MATCH_SEARCH_DEBOUNCE_MS, MATCH_TRANSACTION_SEARCH_PAGE_SIZE, toExpenseAutomationJEScheduleSortKey, toExpenseAutomationActualMatchingSortKey, toJEPageTab, toMatchAndReverseResultStatus, toUndoReversalResultStatus, toggleJECreatedGroupCollapsed, toggleJEPendingGroupCollapsed, updateJEScheduleTypeFilter, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, updateTransactionGroup, fetchExpenseAutomationMissingReceipts,
493
495
  // Bulk Upload Actions
494
496
  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, getLedgerAccountIdsWithStatementOverrideWarning, getLedgerAccountsForCombinedStatementMapping, getReparseStatementStatusByAccountId, getUnavailableLedgerAccountIds, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, getAccountReconByAccountIdAndSelectedPeriod, toReconciliationTabsType, isAccountReconReport, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, updateStatementProcessingFailed, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, toReconciliationAccountSource, deleteAccountStatement, deleteCombinedStatement, uploadAccountStatement, parseCombinedStatement, parseStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateNodeCollapseState, updateStatementUploadChosen, submitCombinedStatementUpdate, submitStatementUpdate, clearStatementDateConflict, confirmStatementMapping, updateStatementUpdateLocalData, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, setStatementProcessingDismissedToBackground, updateStatementProcessingBackgroundCompletedSteps, };
495
497
  export { computeNewScheduleJeDetails, createOneTimeAccrual, createOneTimeAccrualFailure, createOneTimeAccrualSuccess, fetchOneTimeAccrual, getJeNewAccrualAccountsView, ignoreOneTimeAccrual, promoteOneTimeAccrual, revertJeSchedule, revertOneTimeAccrual, getJeNewScheduleSearchTransactionsView, getJeNewScheduleView, };
@@ -660,6 +662,7 @@ export { TIME_SERIES_DURATIONS, convertToTimeSeriesSelectionRange, toTimeSeriesD
660
662
  export { fetchApAging, getApAgingReport, updateApAgingUIState, };
661
663
  export { fetchApAgingDetail, getApAgingDetailForVendor, updateApAgingDetailUIState, };
662
664
  export { clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearJeSearchTransactionsForNewSchedule, fetchExpenseAutomationJESchedulesPage, ignoreExpenseAutomationJESchedule, initializeJeAccountSettingsView, initializeJeNewSchedule, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, resetJeNewScheduleLocalData, retryExpenseAutomationJESchedule, saveJeNewSchedule, saveJeNewScheduleFailure, saveJeNewScheduleSuccess, searchJeTransactionsForNewSchedule, searchJeTransactionsForNewScheduleFailure, searchJeTransactionsForNewScheduleSuccess, updateExpenseAutomationJESchedulesUIState, updateJeNewScheduleLocalData, removeJeOneTimeAccrualLocalData, updateJeOneTimeAccrualLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, };
665
+ export { clearExpenseAutomationActualMatchingView, closeMatchNewModal, clearMatchNewModal, fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateExpenseAutomationActualMatchingUIState, };
663
666
  export { createNewSchedulesAccrued, deleteScheduleAccruedDetail, cancelScheduleAccruedJournalEntry, fetchScheduleAccruedDetails, fetchScheduleAccruedDetailsPage, resetJEAccruedLinkInLocalData, saveScheduleAccruedDetails, updateAmountsInScheduleAccruedDetail, updatedJEAccruedLinkWithRecommendedLocalData, updatedJELinkInLocalDataAccruedExpenses, fetchRecommendedTransactionRowIndex, clearSelectedJELinkRowIndex, updateLinkBillExpenseLocalData, updateScheduleAccruedDetailsLocalData, updateSelectedJEAccruedScheduleKey, resetSelectedJEAccruedScheduleKey, resetAccruedDetailNewScheduleState, };
664
667
  export { getJEScheduleTransactionKey, ALL_JE_SCHEDULE_IGNORE_REASONS, ALL_JE_SCHEDULE_REVERT_REASONS, ALL_ONE_TIME_ACCRUAL_IGNORE_REASONS, ALL_ONE_TIME_ACCRUAL_REVERT_REASONS, ALL_SCHEDULES_TYPES, getScheduleListReport, getAccruedScheduleListReport, fetchScheduleList, fetchAccruedScheduleList, fetchDownloadSchedules, fetchSchedulesAccount, updateScheduleListLocalData, getFetchStateForScheduleAccountList, toScheduleTypesType, toScheduleTypesTypeStrict, toScheduleListTabsFileTypeStrict, toScheduleSubTabType, updateScheduleListSubTab, updateScheduleListSearchText, updateScheduleListScrollState, updateScheduleListSortState, updateSelectedJEScheduleKey, fetchScheduleDetails, getScheduleDetailsView, getAccruedScheduleDetailsView, fetchScheduleDetailsPage, saveScheduleDetails, deleteScheduleDetail, createNewSchedules, updateScheduleDetailsLocalData, updateScheduleListDownloadState, updateAccruedJEScheduleAccruedByListKey, updatedSelectedJELinkRowIndex, getQBOUrlForLink, getThirdPartyIDFromQBOURL, updatedJELinkInLocalData, updateAmountsInScheduleDetail, resetJELinkInLocalData, updatedJELinkWithRecommendedLocalData, getFetchStateForScheduleListByType, getDefaultSelectedTimeframeForScheduleType, markAsCompleteScheduleDetail, resetMarkAsCompleteStatus, fetchVendorTabView, updateVendorTabViewTab, getVendorTabView, };
665
668
  export { toVendorFirstReviewViewColumnKeyType, getGlobalMerchantAutoCompleteResults, getVendorFirstReviewView, getVendorFirstReviewAttachmentView, fetchVendorFirstReviewView, fetchVendorFirstReviewAttachments, updateVendorFirstReviewViewScrollYOffset, resetVendorFirstReviewLocalData, updateVendorFirstReviewViewPageToken, clearRecentlySavedErroredVendorData, saveVendorFirstReviewView, updateVendorFirstReviewViewLocalData, updateVendorFirstReviewSortUiState, fetchGlobalMerchantAutoCompleteView, clearGlobalMerchantAutoCompleteResults, updateReviewVendorDetailLocalData, saveVendorDetailsView, getVendorDetailSelectorView, };
@@ -677,7 +680,7 @@ export { toNotificationModeStrict, updateCommentsNotifications, updateCommentsNo
677
680
  export { toNotificationSubTabTypeStrict, toNotificationTabTypeStrict, fetchNotificationView, fetchNotificationUnreadCount, fetchNotificationUnreadCountSuccess, updateNotificationViewAllNotificationsStatus, updateNotificationViewNotificationStatus, updateNotificationViewTabState, updateNotificationViewCurrentTabAndSubTab, updateNotificationViewSubTab, updateNotificationViewUIState, getNotificationView, getExternalNotificationsForSelectedSubTab, getNotificationsForSelectedSubTab, };
678
681
  export { fetchRegisteredInterests, notifyMeForFeature, getFeatureNotificationView, getRegisteredInterests, getRegisteredInterestsByFeature, isFeatureInterestRegistered, };
679
682
  export { pushToastNotification, getLastNotificationTime, getNotifications, };
680
- export { getEffectiveNotificationPreferences, getEffectiveNotificationPreferencesForDomain, getNotificationLocalOverrides, getNotificationLocalOverridesForDomain, getNotificationPreferencesSaveState, getNotificationRegistry, getNotificationRegistryForDomain, hasUnsavedNotificationPreferences, hasUnsavedNotificationPreferencesForDomain, NOTIFICATION_DOMAINS, DEFAULT_NOTIFICATION_DOMAIN, clearAllNotificationPreferencesView, clearNotificationPreferencesLocalOverrides, saveNotificationPreferences, setGroupChannelMaster, setGroupFrequency, toggleEventChannel, toNotificationChannel, toNotificationDomain, toNotificationFrequency, };
683
+ export { getEffectiveNotificationPreferences, getNotificationLocalOverrides, getNotificationPreferencesSaveState, getNotificationRegistry, hasUnsavedNotificationPreferences, clearAllNotificationPreferencesView, clearNotificationPreferencesLocalOverrides, saveNotificationPreferences, setGroupChannelMaster, setGroupFrequency, toggleEventChannel, toNotificationChannel, toNotificationFrequency, };
681
684
  export { getReferralListView, getInviteFormView, toReferralListViewSortKeyType, StatusTypes, AmountStatusTypes, DEFAULT_REFERRER_AMOUNT, fetchReferrals, sendReferralInvite, clearReferrals, saveReferralFormDataInLocalStore, updateReferralListSortUiState, resendReferralInvite, fetchRewardsPlan, getRewardsPlanCard, updateReferViewed, };
682
685
  export { ALL_WEEK_DAYS, SEMI_WEEKLY_REQUIRED_DAYS_COUNT, getMinAllowedEndDate, getRecurringEndDateFromCount, toDayOfWeek, toRecurringFrequency, };
683
686
  export { fetchCockpitContext, fetchCompanyTaskManagerView, fetchTaskManagerMetrics, getCompanyTaskManagerView, createTaskFromTaskGroupTemplate, };
@@ -863,3 +866,4 @@ export { getInvoicingOnboardingGateView } from './view/invoicing/invoicingConfig
863
866
  // Accrued JE schedules are not a discriminated union member, so consumers need this guard to
864
867
  // narrow a JEScheduleRow before reading baseTransaction / recurringAmount.
865
868
  export { getExpenseAutomationJEOneTimeAccrualDetailView, getJEScheduleRowType, isAccruedScheduleRow, isAiAccountantSchedule, isExistingTabRow, isOneTimeAccrualRow, isRenderableOneTimeAccrual, isPendingReviewRow, } from './view/expenseAutomationView/selectors/jeSchedulesViewSelector';
869
+ export { getActualMatchingAmount, getActualMatchingReversalDate, parseActualMatchingMatchId, getExpenseAutomationActualMatchingMatchView, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
@@ -42,6 +42,7 @@ import invoicingSubscription, { initialState as initialInvoicingSubscriptionStat
42
42
  import invoicingTransaction, { initialState as initialInvoicingTransactionState, } from './entity/invoicing/invoicingTransaction/invoicingTransactionReducer';
43
43
  import invoicingPlan, { initialState as initialInvoicingPlanState, } from './entity/invoicing/plan/planReducer';
44
44
  import invoicingProduct, { initialState as initialInvoicingProductState, } from './entity/invoicing/product/productReducer';
45
+ import actualMatching, { initialState as initialActualMatchingState, } from './entity/actualMatching/actualMatchingReducer';
45
46
  import jeSchedules, { initialState as initialJESchedulesState, } from './entity/jeSchedules/jeSchedulesReducer';
46
47
  import merchant, { initialState as initialMerchantState, } from './entity/merchant/merchantReducer';
47
48
  import monthEndCloseChecks, { initialState as initialMonthEndCloseChecksState, } from './entity/monthEndCloseChecks/monthEndCloseChecksReducer';
@@ -118,6 +119,7 @@ import creditAgentView, { initialState as initialCreditAgentViewState, } from '.
118
119
  import dashboard, { initialState as initialDashboardState, } from './view/dashboard/dashboardReducer';
119
120
  import dashboardLayout, { initialState as initialDashboardLayoutState, } from './view/dashboardLayout/dashboardLayoutReducer';
120
121
  import expenseAutomationView, { initialState as initialExpenseAutomationViewState, } from './view/expenseAutomationView/expenseAutomationViewReducer';
122
+ import expenseAutomationActualMatchingView, { initialState as initialExpenseAutomationActualMatchingViewState, } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
121
123
  import expenseAutomationFluxAnalysisView, { initialState as initialExpenseAutomationFluxAnalysisViewState, } from './view/expenseAutomationView/reducers/fluxAnalysisViewReducer';
122
124
  import expenseAutomationJESchedulesView, { initialState as initialExpenseAutomationJESchedulesViewState, } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
123
125
  import expenseAutomationMissingReceiptsView, { initialState as initialExpenseAutomationMissingReceiptsViewState, } from './view/expenseAutomationView/reducers/missingReceiptsViewReducer';
@@ -279,6 +281,7 @@ const initialEntitiesState = {
279
281
  accountingSummaryState: initialAccountingSummaryState,
280
282
  accountReconState: initialAccountReconState,
281
283
  accountState: initialAccountState,
284
+ actualMatchingState: initialActualMatchingState,
282
285
  addressState: initialAddressState,
283
286
  aiAccountantCustomerState: initialAiAccountantCustomerState,
284
287
  aiCfoState: initialAiCfoState,
@@ -421,6 +424,7 @@ const initialViewsState = {
421
424
  entityAutoCompleteState: initialEntityAutoCompleteState,
422
425
  entityRecommendationState: initialEntityRecommendationState,
423
426
  expenseAutomationFluxAnalysisViewState: initialExpenseAutomationFluxAnalysisViewState,
427
+ expenseAutomationActualMatchingViewState: initialExpenseAutomationActualMatchingViewState,
424
428
  expenseAutomationJESchedulesViewState: initialExpenseAutomationJESchedulesViewState,
425
429
  expenseAutomationMissingReceiptsViewState: initialExpenseAutomationMissingReceiptsViewState,
426
430
  expenseAutomationReconciliationViewState: initialExpenseAutomationReconciliationViewState,
@@ -563,6 +567,7 @@ const entityReducers = {
563
567
  accountReconState: accountRecon,
564
568
  accountingSummaryState: accountingSummary,
565
569
  accountState: account,
570
+ actualMatchingState: actualMatching,
566
571
  addressState: address,
567
572
  aiAccountantCustomerState: aiAccountantCustomer,
568
573
  aiCfoState: aiCfo,
@@ -705,6 +710,7 @@ const viewReducers = {
705
710
  entityAutoCompleteState: entityAutoComplete,
706
711
  entityRecommendationState: recommendation,
707
712
  expenseAutomationFluxAnalysisViewState: expenseAutomationFluxAnalysisView,
713
+ expenseAutomationActualMatchingViewState: expenseAutomationActualMatchingView,
708
714
  expenseAutomationJESchedulesViewState: expenseAutomationJESchedulesView,
709
715
  expenseAutomationMissingReceiptsViewState: expenseAutomationMissingReceiptsView,
710
716
  expenseAutomationReconciliationViewState: expenseAutomationReconciliationView,
@@ -835,8 +835,7 @@ const aiCfoView = createSlice({
835
835
  // The server has it. Nothing it sends from here on will contain this row,
836
836
  // so the tombstone has done its job and holding it any longer is what
837
837
  // makes a routine recreated under the same id invisible forever.
838
- draft.routines.deletedScheduleIds =
839
- draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
838
+ draft.routines.deletedScheduleIds = draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
840
839
  draft.routineMutation = {
841
840
  fetchState: 'Completed',
842
841
  error: undefined,
@@ -848,8 +847,7 @@ const aiCfoView = createSlice({
848
847
  // is what lets the refetch put the row back — leaving it hidden would
849
848
  // tell the user they had stopped something they had not, which is the
850
849
  // worst outcome this list can produce.
851
- draft.routines.deletedScheduleIds =
852
- draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
850
+ draft.routines.deletedScheduleIds = draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
853
851
  // Its own slice: the refetch that puts the row back would otherwise wipe
854
852
  // this error, leaving the row silently reappearing with no explanation.
855
853
  draft.routineMutation = {
@@ -27,9 +27,7 @@ export const fetchRoutineRunsEpic = (actions$, _state$, zeniAPI) => actions$.pip
27
27
  // Filtered, not trusted: one malformed row must not take the
28
28
  // whole history down, and a run without an id is not addressable
29
29
  // by anything the UI does with it.
30
- runs: (data.runs ?? [])
31
- .filter(isRoutineRunPayload)
32
- .map(toRoutineRun),
30
+ runs: (data.runs ?? []).filter(isRoutineRunPayload).map(toRoutineRun),
33
31
  scheduleId,
34
32
  sessionId: data.session_id ?? null,
35
33
  });