@zeniai/client-epic-state 4.20.1 → 4.20.2-beta0ND

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 (128) hide show
  1. package/lib/common/aiCfo/aiCfoSuggestedQuestionsPageContext.d.ts +19 -0
  2. package/lib/common/aiCfo/aiCfoSuggestedQuestionsPageContext.js +2 -0
  3. package/lib/commonStateTypes/animations.d.ts +1 -1
  4. package/lib/entity/aiCfo/aiCfoSelector.d.ts +1 -2
  5. package/lib/entity/billPay/billTransaction/billTransactionState.d.ts +2 -2
  6. package/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +38 -0
  7. package/lib/entity/jeSchedules/jeSchedulesPayload.js +78 -0
  8. package/lib/entity/jeSchedules/jeSchedulesSelector.d.ts +4 -1
  9. package/lib/entity/jeSchedules/jeSchedulesSelector.js +5 -1
  10. package/lib/entity/jeSchedules/jeSchedulesState.d.ts +37 -0
  11. package/lib/entity/tenant/tenantPayload.d.ts +1 -0
  12. package/lib/entity/tenant/tenantReducer.js +1 -0
  13. package/lib/entity/tenant/tenantSelector.d.ts +1 -0
  14. package/lib/entity/tenant/tenantSelector.js +9 -1
  15. package/lib/entity/tenant/tenantState.d.ts +1 -0
  16. package/lib/entity/transaction/payloadTypes/scheduleTransactionPayload.d.ts +4 -1
  17. package/lib/entity/transaction/payloadTypes/scheduleTransactionPayload.js +1 -0
  18. package/lib/entity/transaction/payloadTypes/transactionPayload.d.ts +3 -0
  19. package/lib/entity/transaction/payloadTypes/transactionPayload.js +17 -1
  20. package/lib/entity/transaction/stateTypes/scheduleTransaction.d.ts +1 -0
  21. package/lib/entity/transaction/stateTypes/transaction.d.ts +5 -0
  22. package/lib/entity/transaction/stateTypes/transactionLine.d.ts +1 -1
  23. package/lib/epic.d.ts +2 -1
  24. package/lib/epic.js +2 -1
  25. package/lib/esm/common/aiCfo/aiCfoSuggestedQuestionsPageContext.js +1 -0
  26. package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +78 -0
  27. package/lib/esm/entity/jeSchedules/jeSchedulesSelector.js +5 -1
  28. package/lib/esm/entity/tenant/tenantReducer.js +1 -0
  29. package/lib/esm/entity/tenant/tenantSelector.js +7 -0
  30. package/lib/esm/entity/transaction/payloadTypes/scheduleTransactionPayload.js +1 -0
  31. package/lib/esm/entity/transaction/payloadTypes/transactionPayload.js +17 -1
  32. package/lib/esm/epic.js +2 -1
  33. package/lib/esm/index.js +10 -8
  34. package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +82 -1
  35. package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +8 -2
  36. package/lib/esm/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.js +29 -0
  37. package/lib/esm/view/classList/fetchClassListEpic.js +9 -2
  38. package/lib/esm/view/commonVendorView/vendorView/vendorViewSelector.js +18 -5
  39. package/lib/esm/view/commonVendorView/vendorsTabVendorView/vendorsTabVendorViewSelector.js +6 -2
  40. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +2 -2
  41. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +2 -2
  42. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +4 -3
  43. package/lib/esm/view/expenseAutomationView/expenseAutomationViewSelector.js +0 -1
  44. package/lib/esm/view/expenseAutomationView/helpers/saveTransactionHelper.js +2 -2
  45. package/lib/esm/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.js +2 -2
  46. package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +17 -1
  47. package/lib/esm/view/expenseAutomationView/selectors/fluxAnalysisViewSelector.js +10 -2
  48. package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +63 -6
  49. package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +12 -4
  50. package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +22 -9
  51. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +12 -6
  52. package/lib/esm/view/expenseAutomationView/types/jeSchedulesViewState.js +18 -1
  53. package/lib/esm/view/profitAndLossClassesView/horizontalSectionEmptyBalancesSlice.js +17 -0
  54. package/lib/esm/view/profitAndLossClassesView/profitAndLossClassesByClassHorizontalSelector.js +3 -0
  55. package/lib/esm/view/profitAndLossClassesView/profitAndLossHorizontalEnrichment.js +20 -29
  56. package/lib/esm/view/spendManagement/billPay/billList/billListSelector.js +10 -0
  57. package/lib/esm/view/spendManagement/billPay/billList/billListState.js +1 -0
  58. package/lib/esm/view/spendManagement/billPay/billPayReview/billPayReviewSelector.js +7 -3
  59. package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/billPaySetupApproverViewSelector.js +5 -5
  60. package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/epic/fetchBillPayApproversDetailsEpic.js +7 -2
  61. package/lib/esm/view/spendManagement/billPay/editBillView/editBillViewSelector.js +13 -6
  62. package/lib/esm/view/spendManagement/chargeCards/chargeCardList/chargeCardList.js +1 -0
  63. package/lib/esm/view/spendManagement/chargeCards/chargeCardList/chargeCardListSelector.js +2 -0
  64. package/lib/esm/view/spendManagement/reimbursement/editRemiView/editRemiViewSelector.js +7 -4
  65. package/lib/esm/view/spendManagement/reimbursement/remiListView/remiListSelector.js +12 -0
  66. package/lib/esm/view/spendManagement/reimbursement/remiListView/remiListState.js +1 -0
  67. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +2 -2
  68. package/lib/esm/view/transactionDetail/epics/saveTransactionHelper.js +2 -2
  69. package/lib/esm/view/transactionDetail/transactionDetailLocalDataHelper.js +16 -14
  70. package/lib/index.d.ts +15 -11
  71. package/lib/index.js +44 -32
  72. package/lib/tsconfig.typecheck.tsbuildinfo +1 -1
  73. package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +7 -0
  74. package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +15 -1
  75. package/lib/view/aiCfoView/aiCfoViewReducer.js +83 -2
  76. package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +4 -1
  77. package/lib/view/aiCfoView/aiCfoViewSelector.js +9 -2
  78. package/lib/view/aiCfoView/aiCfoViewState.d.ts +15 -1
  79. package/lib/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.d.ts +8 -0
  80. package/lib/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.js +33 -0
  81. package/lib/view/auditReportView/auditReportViewState.d.ts +1 -1
  82. package/lib/view/classList/fetchClassListEpic.d.ts +1 -1
  83. package/lib/view/classList/fetchClassListEpic.js +8 -1
  84. package/lib/view/commonVendorView/vendorView/vendorViewSelector.d.ts +1 -0
  85. package/lib/view/commonVendorView/vendorView/vendorViewSelector.js +18 -5
  86. package/lib/view/commonVendorView/vendorsTabVendorView/vendorsTabVendorViewSelector.d.ts +1 -0
  87. package/lib/view/commonVendorView/vendorsTabVendorView/vendorsTabVendorViewSelector.js +6 -2
  88. package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +2 -2
  89. package/lib/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +1 -1
  90. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +4 -3
  91. package/lib/view/expenseAutomationView/expenseAutomationViewSelector.js +0 -1
  92. package/lib/view/expenseAutomationView/helpers/saveTransactionHelper.js +2 -2
  93. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.js +2 -2
  94. package/lib/view/expenseAutomationView/payload/jeSchedulesPayload.d.ts +1 -1
  95. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +2 -2
  96. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +18 -2
  97. package/lib/view/expenseAutomationView/selectorTypes/jeSchedulesSelectorTypes.d.ts +2 -0
  98. package/lib/view/expenseAutomationView/selectors/fluxAnalysisViewSelector.js +10 -2
  99. package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +63 -6
  100. package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +12 -4
  101. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +22 -9
  102. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +11 -5
  103. package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +5 -0
  104. package/lib/view/expenseAutomationView/types/jeSchedulesViewState.js +20 -0
  105. package/lib/view/profitAndLossClassesView/horizontalSectionEmptyBalancesSlice.d.ts +9 -0
  106. package/lib/view/profitAndLossClassesView/horizontalSectionEmptyBalancesSlice.js +20 -0
  107. package/lib/view/profitAndLossClassesView/profitAndLossClassesByClassHorizontalSelector.js +3 -0
  108. package/lib/view/profitAndLossClassesView/profitAndLossHorizontalEnrichment.js +20 -29
  109. package/lib/view/scheduleView/scheduleListView/scheduleListTypes.d.ts +1 -1
  110. package/lib/view/spendManagement/billPay/billList/billListSelector.js +10 -0
  111. package/lib/view/spendManagement/billPay/billList/billListState.d.ts +1 -1
  112. package/lib/view/spendManagement/billPay/billList/billListState.js +1 -0
  113. package/lib/view/spendManagement/billPay/billPayReview/billPayReviewSelector.js +7 -3
  114. package/lib/view/spendManagement/billPay/billPaySetupApproverView/billPaySetupApproverViewSelector.js +5 -5
  115. package/lib/view/spendManagement/billPay/billPaySetupApproverView/epic/fetchBillPayApproversDetailsEpic.js +7 -2
  116. package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.js +13 -6
  117. package/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardList.d.ts +1 -1
  118. package/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardList.js +1 -0
  119. package/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardListSelector.js +2 -0
  120. package/lib/view/spendManagement/reimbursement/editRemiView/editRemiViewSelector.js +6 -3
  121. package/lib/view/spendManagement/reimbursement/remiListView/remiListSelector.d.ts +1 -0
  122. package/lib/view/spendManagement/reimbursement/remiListView/remiListSelector.js +12 -0
  123. package/lib/view/spendManagement/reimbursement/remiListView/remiListState.d.ts +1 -1
  124. package/lib/view/spendManagement/reimbursement/remiListView/remiListState.js +1 -0
  125. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +2 -2
  126. package/lib/view/transactionDetail/epics/saveTransactionHelper.js +2 -2
  127. package/lib/view/transactionDetail/transactionDetailLocalDataHelper.js +16 -14
  128. package/package.json +1 -1
@@ -1,4 +1,19 @@
1
1
  import { createSlice } from '@reduxjs/toolkit';
2
+ function removeSessionIdFromPageKeyMap(draft, sessionId) {
3
+ const map = draft.uiState.chatSessionIdByPageKey;
4
+ for (const key of Object.keys(map)) {
5
+ if (map[key] === sessionId) {
6
+ delete map[key];
7
+ }
8
+ }
9
+ }
10
+ function mirrorCurrentSessionToPageKeyMapIfActive(draft) {
11
+ const key = draft.uiState.aiCfoSidePanelHostPageKey;
12
+ const sessionId = draft.uiState.currentChatSessionId;
13
+ if (key != null && sessionId != null) {
14
+ draft.uiState.chatSessionIdByPageKey[key] = sessionId;
15
+ }
16
+ }
2
17
  export const initialAiCfoViewState = {
3
18
  fetchState: 'Not-Started',
4
19
  error: undefined,
@@ -6,6 +21,8 @@ export const initialAiCfoViewState = {
6
21
  currentInput: '',
7
22
  scrollPositionByChatSessionId: {},
8
23
  currentChatSessionId: undefined,
24
+ aiCfoSidePanelHostPageKey: undefined,
25
+ chatSessionIdByPageKey: {},
9
26
  agentId: undefined,
10
27
  chatHistoryNextPageToken: {},
11
28
  chatSessionsNextPageToken: { nextPageToken: null, hasMore: false },
@@ -29,6 +46,7 @@ export const initialAiCfoViewState = {
29
46
  fetchChatSessionHistoryByChatSessionId: {},
30
47
  responseStateByChatSessionId: {},
31
48
  stopSubmitStateByChatSessionId: {},
49
+ suggestedQuestionsByPageContext: {},
32
50
  };
33
51
  const aiCfoView = createSlice({
34
52
  name: 'aiCfoView',
@@ -162,6 +180,7 @@ const aiCfoView = createSlice({
162
180
  setSession(draft, action) {
163
181
  draft.uiState.currentChatSessionId = action.payload.sessionId;
164
182
  draft.uiState.agentId = action.payload.agentId;
183
+ mirrorCurrentSessionToPageKeyMapIfActive(draft);
165
184
  },
166
185
  createSession: {
167
186
  reducer(draft, action) {
@@ -185,6 +204,7 @@ const aiCfoView = createSlice({
185
204
  nextPageToken: null,
186
205
  hasMore: false,
187
206
  };
207
+ mirrorCurrentSessionToPageKeyMapIfActive(draft);
188
208
  },
189
209
  createSessionFailure(draft, action) {
190
210
  draft.createSessionState.fetchState = 'Error';
@@ -222,6 +242,7 @@ const aiCfoView = createSlice({
222
242
  nextPageToken: null,
223
243
  hasMore: false,
224
244
  };
245
+ mirrorCurrentSessionToPageKeyMapIfActive(draft);
225
246
  },
226
247
  createSessionAndSubmitSuccess(draft) {
227
248
  // Note: currentChatSessionId, agentId, and chatHistoryNextPageToken are set by initializeNewSessionState
@@ -338,6 +359,7 @@ const aiCfoView = createSlice({
338
359
  draft.uiState.currentChatSessionId = undefined;
339
360
  draft.uiState.agentId = undefined;
340
361
  }
362
+ removeSessionIdFromPageKeyMap(draft, chatSessionId);
341
363
  delete draft.uiState.chatHistoryNextPageToken[chatSessionId];
342
364
  delete draft.uiState.scrollPositionByChatSessionId[chatSessionId];
343
365
  delete draft.fetchChatSessionHistoryByChatSessionId[chatSessionId];
@@ -360,6 +382,65 @@ const aiCfoView = createSlice({
360
382
  },
361
383
  clearCurrentSessionId(draft) {
362
384
  draft.uiState.currentChatSessionId = undefined;
385
+ const key = draft.uiState.aiCfoSidePanelHostPageKey;
386
+ if (key != null) {
387
+ delete draft.uiState.chatSessionIdByPageKey[key];
388
+ }
389
+ },
390
+ applyAiCfoSidePanelHostPageTransition(draft, action) {
391
+ const { newAiCfoSidePanelHostPageKey, nextCurrentChatSessionId } = action.payload;
392
+ const prevKey = draft.uiState.aiCfoSidePanelHostPageKey;
393
+ const curId = draft.uiState.currentChatSessionId;
394
+ if (prevKey != null &&
395
+ prevKey !== newAiCfoSidePanelHostPageKey &&
396
+ curId != null) {
397
+ draft.uiState.chatSessionIdByPageKey[prevKey] = curId;
398
+ }
399
+ draft.uiState.aiCfoSidePanelHostPageKey = newAiCfoSidePanelHostPageKey;
400
+ draft.uiState.currentChatSessionId =
401
+ nextCurrentChatSessionId != null ? nextCurrentChatSessionId : undefined;
402
+ draft.uiState.currentInput = '';
403
+ mirrorCurrentSessionToPageKeyMapIfActive(draft);
404
+ },
405
+ clearAiCfoSidePanelHostPageContext(draft) {
406
+ const key = draft.uiState.aiCfoSidePanelHostPageKey;
407
+ const curId = draft.uiState.currentChatSessionId;
408
+ if (key != null && curId != null) {
409
+ draft.uiState.chatSessionIdByPageKey[key] = curId;
410
+ }
411
+ draft.uiState.aiCfoSidePanelHostPageKey = undefined;
412
+ },
413
+ fetchSuggestedQuestions(draft, action) {
414
+ const { pageContext } = action.payload;
415
+ const prev = draft.suggestedQuestionsByPageContext[pageContext];
416
+ draft.suggestedQuestionsByPageContext[pageContext] = {
417
+ fetchState: 'In-Progress',
418
+ pageContext,
419
+ suggestedQuestions: prev?.suggestedQuestions ?? [],
420
+ generatedAt: prev?.generatedAt,
421
+ error: undefined,
422
+ };
423
+ },
424
+ fetchSuggestedQuestionsSuccess(draft, action) {
425
+ const { pageContext, generatedAt, suggestedQuestions } = action.payload;
426
+ draft.suggestedQuestionsByPageContext[pageContext] = {
427
+ fetchState: 'Completed',
428
+ pageContext,
429
+ generatedAt,
430
+ suggestedQuestions,
431
+ error: undefined,
432
+ };
433
+ },
434
+ fetchSuggestedQuestionsFailure(draft, action) {
435
+ const { pageContext, error } = action.payload;
436
+ const prev = draft.suggestedQuestionsByPageContext[pageContext];
437
+ draft.suggestedQuestionsByPageContext[pageContext] = {
438
+ fetchState: 'Error',
439
+ pageContext,
440
+ suggestedQuestions: prev?.suggestedQuestions ?? [],
441
+ generatedAt: prev?.generatedAt,
442
+ error,
443
+ };
363
444
  },
364
445
  clearAiCfoView(draft) {
365
446
  Object.assign(draft, initialAiCfoViewState);
@@ -371,5 +452,5 @@ const aiCfoView = createSlice({
371
452
  },
372
453
  },
373
454
  });
374
- export const { submitQuestion, submitQuestionSuccess, submitQuestionFailure, updateResponseState, updateAiCfoViewScrollPosition, updateCurrentInput, clearInput, setSession, createSession, createSessionSuccess, createSessionFailure, createSessionAndSubmit, initializeNewSessionState, createSessionAndSubmitSuccess, createSessionAndSubmitFailure, fetchChatSessionsForUser, fetchChatSessionsForUserSuccess, fetchChatSessionsForUserFailure, fetchChatHistory, fetchChatHistorySuccess, fetchChatHistoryFailure, clearCurrentSessionId, clearLastContextMessage, stopSubmit, stopSubmitSuccess, stopSubmitFailure, stopSubmitQuestion, stopSubmitQuestionSuccess, stopSubmitQuestionFailure, acceptMasterTOS, acceptMasterTOSSuccess, acceptMasterTOSFailure, deleteChatSession, deleteChatSessionSuccess, deleteChatSessionFailure, clearDeleteChatSessionStatus, clearAiCfoView, updateCotCollapsedState, } = aiCfoView.actions;
455
+ export const { submitQuestion, submitQuestionSuccess, submitQuestionFailure, updateResponseState, updateAiCfoViewScrollPosition, updateCurrentInput, clearInput, setSession, createSession, createSessionSuccess, createSessionFailure, createSessionAndSubmit, initializeNewSessionState, createSessionAndSubmitSuccess, createSessionAndSubmitFailure, fetchChatSessionsForUser, fetchChatSessionsForUserSuccess, fetchChatSessionsForUserFailure, fetchChatHistory, fetchChatHistorySuccess, fetchChatHistoryFailure, clearCurrentSessionId, clearLastContextMessage, stopSubmit, stopSubmitSuccess, stopSubmitFailure, stopSubmitQuestion, stopSubmitQuestionSuccess, stopSubmitQuestionFailure, acceptMasterTOS, acceptMasterTOSSuccess, acceptMasterTOSFailure, deleteChatSession, deleteChatSessionSuccess, deleteChatSessionFailure, clearDeleteChatSessionStatus, clearAiCfoView, updateCotCollapsedState, fetchSuggestedQuestions, fetchSuggestedQuestionsSuccess, fetchSuggestedQuestionsFailure, applyAiCfoSidePanelHostPageTransition, clearAiCfoSidePanelHostPageContext, } = aiCfoView.actions;
375
456
  export default aiCfoView.reducer;
@@ -1,6 +1,8 @@
1
+ import { initialAiCfoState } from '../../entity/aiCfo/aiCfoReducer';
1
2
  import { getAiCfoSelectorView, } from '../../entity/aiCfo/aiCfoSelector';
3
+ import { initialAiCfoViewState } from './aiCfoViewReducer';
2
4
  export const getAiCfoView = (state) => {
3
- const { fetchState, error, uiState, createSessionState, createSessionAndSubmitState, deleteChatSessionStateByChatSessionId, stopSubmitStateByChatSessionId, responseStateByChatSessionId, fetchChatSessionHistoryByChatSessionId, masterTOSAcceptanceState, } = state.aiCfoViewState;
5
+ const { fetchState, error, uiState, createSessionState, createSessionAndSubmitState, deleteChatSessionStateByChatSessionId, stopSubmitStateByChatSessionId, responseStateByChatSessionId, fetchChatSessionHistoryByChatSessionId, masterTOSAcceptanceState, suggestedQuestionsByPageContext, } = state.aiCfoViewState ?? initialAiCfoViewState;
4
6
  return {
5
7
  fetchState,
6
8
  error,
@@ -12,7 +14,11 @@ export const getAiCfoView = (state) => {
12
14
  uiState,
13
15
  fetchChatSessionHistoryByChatSessionId,
14
16
  masterTOSAcceptanceState,
15
- ...getAiCfoSelectorView(state.aiCfoState),
17
+ suggestedQuestionsByPageContext,
18
+ ...getAiCfoSelectorView(state.aiCfoState ?? initialAiCfoState),
16
19
  version: 1,
17
20
  };
18
21
  };
22
+ export function getSuggestedQuestionsForPageContext(state, pageContext) {
23
+ return state.aiCfoViewState?.suggestedQuestionsByPageContext?.[pageContext];
24
+ }
@@ -0,0 +1,29 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
4
+ import { fetchSuggestedQuestions, fetchSuggestedQuestionsFailure, fetchSuggestedQuestionsSuccess, } from '../aiCfoViewReducer';
5
+ /** GET {aiCfoMicroServiceBaseUrl}/1.0/suggested-questions?page_context=... */
6
+ export const fetchSuggestedQuestionsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchSuggestedQuestions.match),
7
+ // mergeMap (not switchMap): each page_context is keyed separately in Redux; switchMap
8
+ // would cancel in-flight HTTP for context A when B is requested, leaving A stuck In-Progress.
9
+ mergeMap((action) => {
10
+ const { pageContext } = action.payload;
11
+ const query = new URLSearchParams({ page_context: pageContext });
12
+ const url = `${zeniAPI.apiEndPoints.aiCfoMicroServiceBaseUrl}/1.0/suggested-questions?${query.toString()}`;
13
+ return zeniAPI.getJSON(url).pipe(mergeMap((response) => {
14
+ if (isSuccessResponse(response) && response.data != null) {
15
+ return of(fetchSuggestedQuestionsSuccess({
16
+ pageContext: response.data.page_context,
17
+ generatedAt: response.data.generated_at,
18
+ suggestedQuestions: response.data.suggested_questions,
19
+ }));
20
+ }
21
+ return of(fetchSuggestedQuestionsFailure({
22
+ pageContext,
23
+ error: response.status,
24
+ }));
25
+ }), catchError((error) => of(fetchSuggestedQuestionsFailure({
26
+ pageContext,
27
+ error: createZeniAPIStatus('Unexpected Error', 'Fetch suggested questions REST API call failed', error instanceof Error ? { message: error.message } : undefined),
28
+ }))));
29
+ }));
@@ -1,9 +1,16 @@
1
1
  import { of } from 'rxjs';
2
- import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
2
+ import { catchError, filter, mergeMap, switchMap, withLatestFrom, } from 'rxjs/operators';
3
3
  import { updateClasses } from '../../entity/class/classReducer';
4
+ import { getIsAccountingClassesEnabled } from '../../entity/tenant/tenantSelector';
4
5
  import { createZeniAPIStatus, isSuccessResponse } from '../../responsePayload';
5
6
  import { fetchClassList, updateClassList, updateClassListFailure, } from './classListReducer';
6
- export const fetchClassListEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchClassList.match), switchMap((action) => {
7
+ export const fetchClassListEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchClassList.match), withLatestFrom(state$), switchMap(([action, state]) => {
8
+ if (!getIsAccountingClassesEnabled(state)) {
9
+ return of(updateClassList({
10
+ status: createZeniAPIStatus('Success', ''),
11
+ data: { accounting_classes: [] },
12
+ }));
13
+ }
7
14
  const { isIncludeDeleted } = action.payload;
8
15
  const queryParams = isIncludeDeleted === true
9
16
  ? `?query=${encodeURIComponent(JSON.stringify({ is_include_deleted: true }))}`
@@ -6,6 +6,7 @@ import { getContactsByIds } from '../../../entity/billPay/contact/contactSelecto
6
6
  import { getClassById } from '../../../entity/class/classSelector';
7
7
  import { getFilesByFileIds } from '../../../entity/file/fileSelector';
8
8
  import { getPaymentInstrumentsByIds } from '../../../entity/paymentInstrument/paymentInstrumentSelector';
9
+ import { getIsAccountingClassesEnabled } from '../../../entity/tenant/tenantSelector';
9
10
  import { getUserByUserId, getUsersByUserIds, } from '../../../entity/user/userSelector';
10
11
  import { getVendorByVendorId } from '../../../entity/vendor/vendorSelector';
11
12
  import { getAccountList, getNestedAccountListHierarchy, } from '../../accountList/accountListSelector';
@@ -60,13 +61,17 @@ export const getVendorView = (state, vendorIdFromUrl) => {
60
61
  ?.vendorDetailLocalData,
61
62
  supportedCountries: billPayConfigState.vendor.supportedCountries,
62
63
  };
63
- fetchState = reduceFetchState([
64
+ const isAccountingClassesEnabled = getIsAccountingClassesEnabled(state);
65
+ const editFetchStateList = [
64
66
  accountList,
65
- classList,
66
67
  vendorTypeListState,
67
68
  vendorViewState.editVendorStateById[vendorIdFromUrl]?.fetchStatus ??
68
69
  vendorViewInitialState.newVendorState.fetchStatus,
69
- ]);
70
+ ];
71
+ if (isAccountingClassesEnabled) {
72
+ editFetchStateList.push(classList);
73
+ }
74
+ fetchState = reduceFetchState(editFetchStateList);
70
75
  }
71
76
  else {
72
77
  const basicVendorDetails = getBasicVendorDetailsForNewVendor(state, vendorViewState.newVendorState);
@@ -95,11 +100,17 @@ export const getVendorView = (state, vendorIdFromUrl) => {
95
100
  if (tentativeName != null) {
96
101
  entityRecommendations = getRecommendationsForEntity(state, tentativeName, 'vendor');
97
102
  }
103
+ const isAccountingClassesEnabled = getIsAccountingClassesEnabled(state);
98
104
  const fetchStateList = [
99
105
  { fetchState: accountList.fetchState, error: accountList.error },
100
- { fetchState: classList.fetchState, error: classList.error },
101
106
  vendorTypeListState,
102
107
  ];
108
+ if (isAccountingClassesEnabled) {
109
+ fetchStateList.push({
110
+ fetchState: classList.fetchState,
111
+ error: classList.error,
112
+ });
113
+ }
103
114
  if (entityRecommendations != null &&
104
115
  entityRecommendations.recommendations != null &&
105
116
  entityRecommendations.recommendations.length > 0) {
@@ -144,6 +155,7 @@ export const getVendorView = (state, vendorIdFromUrl) => {
144
155
  fetchState: fetchState.fetchState,
145
156
  hasWireTransfer,
146
157
  hasInternationalWireTransfer,
158
+ isAccountingClassesEnabled: getIsAccountingClassesEnabled(state),
147
159
  deleteFileStatusById,
148
160
  updateFileStatusById,
149
161
  loggedInUserVerification,
@@ -219,9 +231,10 @@ const getBasicVendorDetailsForNewVendor = (state, newVendor) => {
219
231
  };
220
232
  export const getVendorDetailPageView = (state, vendorId, entity) => {
221
233
  const trendWithTransactions = getTrendWithTransactions(state, entity, 'EntityDetail');
234
+ const isAccountingClassesEnabled = getIsAccountingClassesEnabled(state);
222
235
  const reducedFetchState = reduceAnyFetchState([
223
236
  state.accountListState.byReportId.accountList,
224
- state.classListState,
237
+ ...(isAccountingClassesEnabled ? [state.classListState] : []),
225
238
  state.vendorTypeListState,
226
239
  state.ownerListState,
227
240
  state.vendorViewState.editVendorStateById[vendorId]?.fetchStatus ?? {
@@ -6,6 +6,7 @@ import { getAccountBase } from '../../../entity/account/accountSelector';
6
6
  import { getAddressByAddressId } from '../../../entity/address/addressSelector';
7
7
  import { getContactsByIds } from '../../../entity/billPay/contact/contactSelector';
8
8
  import { getClassById } from '../../../entity/class/classSelector';
9
+ import { getIsAccountingClassesEnabled } from '../../../entity/tenant/tenantSelector';
9
10
  import { getUserByUserId, getUsersByUserIds, } from '../../../entity/user/userSelector';
10
11
  import { getVendorByVendorId } from '../../../entity/vendor/vendorSelector';
11
12
  import { dateNow } from '../../../zeniDayJS';
@@ -20,6 +21,7 @@ const ALL_VENDOR_DETAIL_TABS_TYPES = [
20
21
  export const toVendorDetailTabsType = (v) => stringToUnion(v, ALL_VENDOR_DETAIL_TABS_TYPES);
21
22
  export const getVendorsTabVendorView = (state, vendorIdFromUrl) => {
22
23
  const { accountListState, accountState, classListState, classState, vendorState, userState, vendorsTabVendorViewState, vendorTypeListState, addressState, addressViewState, contactState, } = state;
24
+ const isAccountingClassesEnabled = getIsAccountingClassesEnabled(state);
23
25
  const accountList = getAccountList(accountState, accountListState, 'accountList');
24
26
  const classList = getClassList(classState, classListState);
25
27
  const ownerList = getUsersByUserIds(state.userState, state.ownerListState.ownerIds);
@@ -51,7 +53,7 @@ export const getVendorsTabVendorView = (state, vendorIdFromUrl) => {
51
53
  }
52
54
  fetchState = reduceFetchState([
53
55
  accountList,
54
- classList,
56
+ ...(isAccountingClassesEnabled ? [classList] : []),
55
57
  vendorTypeListState,
56
58
  vendorsTabVendorViewState.vendorStateById[vendorIdFromUrl]?.fetchStatus ?? {
57
59
  fetchState: 'Not-Started',
@@ -62,6 +64,7 @@ export const getVendorsTabVendorView = (state, vendorIdFromUrl) => {
62
64
  return {
63
65
  accountList: accountList,
64
66
  classList: classList,
67
+ isAccountingClassesEnabled,
65
68
  vendorTypeList: vendorTypeList,
66
69
  accountsHierarchyList,
67
70
  classHierarchyList,
@@ -102,9 +105,10 @@ export const getVendorsTabDetailPageView = (state, vendorId, entity) => {
102
105
  ? getTransactionListByEntityForSinglePeriod(state, entity, state.vendorsTabVendorViewState.allTransactionsTabData
103
106
  .numberOfQuartersFetched)
104
107
  : undefined;
108
+ const isAccountingClassesEnabled = getIsAccountingClassesEnabled(state);
105
109
  const reducedFetchState = reduceAnyFetchState([
106
110
  state.accountListState.byReportId.accountList,
107
- state.classListState,
111
+ ...(isAccountingClassesEnabled ? [state.classListState] : []),
108
112
  state.ownerListState,
109
113
  state.vendorTypeListState,
110
114
  state.vendorsTabVendorViewState.vendorStateById[vendorId]?.fetchStatus ?? {
@@ -21,13 +21,13 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
21
21
  if (isSuccessResponse(response) && response.data != null) {
22
22
  const updateActions = [];
23
23
  updateActions.push(updateJESchedules([
24
- ...response.data.draft_je_schedules,
24
+ ...response.data.je_schedules,
25
25
  ...response.data.failed_je_postings.je_schedules,
26
26
  ]), updateJESchedulesDetails([...response.data.failed_je_postings.je_schedules], response.data.failed_je_postings.scheduled_journal_entries), initializeJeScheduleLocalData([
27
27
  ...response.data.failed_je_postings.je_schedules,
28
28
  ]));
29
29
  updateActions.push(fetchJeSchedulesSuccess({
30
- jeSchedules: [...response.data.draft_je_schedules],
30
+ jeSchedules: [...response.data.je_schedules],
31
31
  failedJeSchedules: [
32
32
  ...response.data.failed_je_postings.je_schedules,
33
33
  ],
@@ -1,9 +1,9 @@
1
1
  import { concat, of, timer } from 'rxjs';
2
- import { catchError, filter, mergeMap } from 'rxjs/operators';
2
+ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
3
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
4
  import { BULK_UPLOAD_BAR_COMPLETE_HOLD_MS } from '../../bulkUploadTiming';
5
5
  import { bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, updateBulkUploadProgress, } from '../../reducers/missingReceiptsViewReducer';
6
- export const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceipts.match), mergeMap((action) => {
6
+ export const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceipts.match), switchMap((action) => {
7
7
  const { files } = action.payload;
8
8
  const formData = new FormData();
9
9
  for (const file of files) {
@@ -25,7 +25,7 @@ export const pusherBatchStatusCompletionEpic = (actions$) => actions$.pipe(filte
25
25
  * force `phase` to `completed` (dismiss automatching banner) and refresh the batch list.
26
26
  * Cancels when the batch completes normally, bulk state is cleared, or another upload supersedes.
27
27
  */
28
- export const bulkUploadAutomatchingTimeoutEpic = (actions$, state$) => actions$.pipe(filter(bulkUploadReceiptsSuccess.match), mergeMap((action) => {
28
+ export const bulkUploadAutomatchingTimeoutEpic = (actions$, state$) => actions$.pipe(filter(bulkUploadReceiptsSuccess.match), switchMap((action) => {
29
29
  const { batchId } = action.payload;
30
30
  return timer(BULK_UPLOAD_AUTOMATCHING_TIMEOUT_MS).pipe(mergeMap(() => {
31
31
  const bulk = state$.value.expenseAutomationMissingReceiptsViewState.bulkUpload;
@@ -44,10 +44,11 @@ export const bulkUploadAutomatchingTimeoutEpic = (actions$, state$) => actions$.
44
44
  * error snackbar per upload session (first failure only) so the user is not spammed every
45
45
  * interval; Pusher or a later successful poll still completes the flow.
46
46
  */
47
- export const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceiptsSuccess.match), mergeMap((action) => {
47
+ export const pollBulkUploadBatchStatusEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceiptsSuccess.match), switchMap((action) => {
48
48
  const { batchId } = action.payload;
49
49
  let pollErrorNotified = false;
50
- return timer(FALLBACK_FIRST_DELAY_MS, FALLBACK_POLL_INTERVAL_MS).pipe(takeUntil(merge(actions$.pipe(filter(clearBulkUpload.match)), actions$.pipe(filter(pusherBatchStatusUpdate.match), filter((action) => action.payload.batchId === batchId)), actions$.pipe(filter(fetchBulkUploadBatchDetailsSuccess.match), filter((action) => action.payload.batchId === batchId)), actions$.pipe(filter(bulkUploadAutomatchingTimedOut.match), filter((action) => action.payload.batchId === batchId)))), switchMap(() => zeniAPI
50
+ return timer(FALLBACK_FIRST_DELAY_MS, FALLBACK_POLL_INTERVAL_MS).pipe(takeUntil(merge(actions$.pipe(filter(clearBulkUpload.match)), actions$.pipe(filter(pusherBatchStatusUpdate.match), filter((action) => action.payload.batchId === batchId &&
51
+ action.payload.status === 'completed')), actions$.pipe(filter(fetchBulkUploadBatchDetailsSuccess.match), filter((action) => action.payload.batchId === batchId)), actions$.pipe(filter(bulkUploadAutomatchingTimedOut.match), filter((action) => action.payload.batchId === batchId)))), switchMap(() => zeniAPI
51
52
  .getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/batches/${batchId}`)
52
53
  .pipe(mergeMap((response) => {
53
54
  /** Same batch-details URL; polls until `status` is completed (Pusher may win first). */
@@ -91,7 +91,6 @@ export function getExpenseAutomationView(state) {
91
91
  const fetchStateVariables = [
92
92
  expenseAutomationMissingReceiptsViewState,
93
93
  expenseAutomationJESchedulesViewState,
94
- monthEndCloseChecksView,
95
94
  expenseAutomationTransactionsView,
96
95
  expenseAutomationReconciliationViewState,
97
96
  ];
@@ -64,8 +64,8 @@ export const toTransactionUpdatesFromTransactionCategorizationLocalData = (trans
64
64
  lineItem.account?.qboId !== accountLine.account.qboId &&
65
65
  Boolean(lineItem.account?.qboId);
66
66
  hasClassChanged =
67
- Boolean(lineItem.class?.qboId) &&
68
- lineItem.class?.qboId !== accountLine.class.qboId;
67
+ (lineItem.class?.qboId != null || accountLine.class?.qboId != null) &&
68
+ lineItem.class?.qboId !== accountLine.class?.qboId;
69
69
  const recommendedAccountBase = toRecommendedAccountBase(lineItem.amount.amount, lineItem.account);
70
70
  const recommendedClassBase = toRecommendedClassBase(lineItem.amount.amount, lineItem.class);
71
71
  if (entityDetails != null &&
@@ -234,7 +234,7 @@ const buildLineItemById = (transaction, uncategorizedIncomeExpense, recommendati
234
234
  isPreFilled: true,
235
235
  };
236
236
  }
237
- if (accountLine.class.classId === '' &&
237
+ if (Boolean(accountLine.class?.classId) === false &&
238
238
  higherPreferenceRecommendation?.class != null) {
239
239
  record.class = {
240
240
  ...higherPreferenceRecommendation.class,
@@ -464,7 +464,7 @@ export const setEntityRecommendationForLineIdInLocalData = (draft, transaction,
464
464
  }
465
465
  : accountLine.account;
466
466
  record.class =
467
- accountLine.class.classId !== ''
467
+ Boolean(accountLine.class?.classId) !== false
468
468
  ? accountLine.class
469
469
  : recommendations?.[0]?.class
470
470
  ? {
@@ -44,6 +44,8 @@ export const initialState = {
44
44
  uiState: {
45
45
  searchString: '',
46
46
  scrollPosition: { scrollTop: 0, scrollLeft: undefined },
47
+ sortKey: 'startMonth',
48
+ sortOrder: 'descending',
47
49
  totalCount: 0,
48
50
  limit: 10,
49
51
  },
@@ -365,12 +367,26 @@ const expenseAutomationJESchedulesView = createSlice({
365
367
  clearJeAccountSettingsLocalData(draft) {
366
368
  draft.accountSettings.localData = accountSettingsInitialState.localData;
367
369
  },
370
+ updateJESchedulesUIState(draft, action) {
371
+ if (action.payload.sortKey != null) {
372
+ draft.uiState.sortKey = action.payload.sortKey;
373
+ }
374
+ if (action.payload.sortOrder != null) {
375
+ draft.uiState.sortOrder = action.payload.sortOrder;
376
+ }
377
+ if (action.payload.searchString != null) {
378
+ draft.uiState.searchString = action.payload.searchString;
379
+ }
380
+ if (action.payload.scrollPosition != null) {
381
+ draft.uiState.scrollPosition = action.payload.scrollPosition;
382
+ }
383
+ },
368
384
  clearExpenseAutomationJESchedulesView(draft) {
369
385
  Object.assign(draft, initialState);
370
386
  },
371
387
  },
372
388
  });
373
- export const { clearExpenseAutomationJESchedulesView, clearJeAccountSettingsLocalData, clearJeScheduleLocalData, fetchAccountSettingsListForAccountTypes, fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesPage, fetchJeSchedulesSuccess, fetchRecommendationForAccountSettings, ignoreRecommendedJeSchedule, ignoreRecommendedJeScheduleFailure, ignoreRecommendedJeScheduleSuccess, initializeAccountSettingsView, initializeJeScheduleLocalData, removeFailedJeScheduleTransactionKey, removeJeScheduleLocalDataById, removeJeScheduleTransactionKey, retryJeSchedule, retryJeScheduleFailure, retryJeScheduleSuccess, saveAccountSettings, saveAccountSettingsFailure, saveAccountSettingsLocalData, saveAccountSettingsSuccess, updateAccountSettingsListForAccountTypes, updateAccountSettingsListForAccountTypesFailure, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, updateRecommendationForAccountSettings, updateRecommendationForAccountSettingsFailure, } = expenseAutomationJESchedulesView.actions;
389
+ export const { clearExpenseAutomationJESchedulesView, clearJeAccountSettingsLocalData, clearJeScheduleLocalData, fetchAccountSettingsListForAccountTypes, fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesPage, fetchJeSchedulesSuccess, fetchRecommendationForAccountSettings, ignoreRecommendedJeSchedule, ignoreRecommendedJeScheduleFailure, ignoreRecommendedJeScheduleSuccess, initializeAccountSettingsView, initializeJeScheduleLocalData, removeFailedJeScheduleTransactionKey, removeJeScheduleLocalDataById, removeJeScheduleTransactionKey, retryJeSchedule, retryJeScheduleFailure, retryJeScheduleSuccess, saveAccountSettings, saveAccountSettingsFailure, saveAccountSettingsLocalData, saveAccountSettingsSuccess, updateAccountSettingsListForAccountTypes, updateAccountSettingsListForAccountTypesFailure, updateJESchedulesUIState, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, updateRecommendationForAccountSettings, updateRecommendationForAccountSettingsFailure, } = expenseAutomationJESchedulesView.actions;
374
390
  export default expenseAutomationJESchedulesView.reducer;
375
391
  const doUpdateRecommendationForAccountSettings = (draft, payload) => {
376
392
  const { prepaidExpensesRecommendations, fixedAssetsRecommendations, accruedExpensesRecommendations, } = mapAccountTypeRecommendationPayloadToAccountRecommendationByType(payload);
@@ -1,3 +1,4 @@
1
+ import { reduceAnyFetchState } from '../../../commonStateTypes/reduceFetchState';
1
2
  import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
2
3
  import { getAccountBase } from '../../../entity/account/accountSelector';
3
4
  import { getClassById } from '../../../entity/class/classSelector';
@@ -6,7 +7,7 @@ import { getUserByUserId } from '../../../entity/user/userSelector';
6
7
  import { getVendorByVendorId } from '../../../entity/vendor/vendorSelector';
7
8
  import { getAllSteps } from '../selectorTypes/expenseAutomationViewSelectorTypes';
8
9
  export function getExpenseAutomationFluxAnalysisView(state) {
9
- const { expenseAutomationFluxAnalysisViewState, monthEndCloseChecksState } = state;
10
+ const { expenseAutomationFluxAnalysisViewState, monthEndCloseChecksState, monthEndCloseChecksViewState, } = state;
10
11
  const { fetchState, error, refreshStatus, uiState, reviewOperatingExpenseIdsByPeriod, selectedSectionIdsByPeriod, groupsBySelectedPeriod, fluxAnalysisEntities, bulkReviewStatus, currency, totalBalancesAndVariance, } = expenseAutomationFluxAnalysisViewState;
11
12
  const fetchStateAndError = {
12
13
  fetchState,
@@ -91,10 +92,17 @@ export function getExpenseAutomationFluxAnalysisView(state) {
91
92
  },
92
93
  };
93
94
  const completionStatus = fluxCompletionStatus != null ? fluxCompletionStatus : 'incomplete';
95
+ const monthEndFetchState = monthYearPeriodId != null
96
+ ? (monthEndCloseChecksViewState.monthEndCloseChecksViewByTenantId[currentTenant.tenantId]?.[monthYearPeriodId] ?? { fetchState: 'Not-Started', error: undefined })
97
+ : { fetchState: 'Not-Started', error: undefined };
98
+ const reducedFetchStatus = reduceAnyFetchState([
99
+ fetchStateAndError,
100
+ monthEndFetchState,
101
+ ]);
94
102
  return {
95
103
  sections,
96
104
  totalBalancesAndVariance,
97
- fetchStatus: fetchStateAndError,
105
+ fetchStatus: reducedFetchStatus,
98
106
  bulkReviewStatus,
99
107
  reviewOperatingExpensesIds,
100
108
  selectedSectionIds,
@@ -1,4 +1,6 @@
1
1
  import omit from 'lodash/omit';
2
+ import orderBy from 'lodash/orderBy';
3
+ import { reduceAnyFetchState } from '../../../commonStateTypes/reduceFetchState';
2
4
  import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
3
5
  import { getAccountIdsForTypes } from '../../../entity/account/accountSelector';
4
6
  import { getJEScheduledTransactionByJEScheduleTransactionKey, } from '../../../entity/jeSchedules/jeSchedulesSelector';
@@ -10,10 +12,48 @@ import { filterNestedAccountHierarchyById } from '../../scheduleView/scheduleDet
10
12
  import { getAccountLabelForScheduleType, getAccountsTypesForScheduleList, } from '../../scheduleView/scheduleListView/scheduleListHelper';
11
13
  import { getAllSteps } from '../selectorTypes/expenseAutomationViewSelectorTypes';
12
14
  import { getJEAccountSettingsView } from './jeAccountSettingsViewSelector';
15
+ function getJEScheduleSortAccessor(sortKey) {
16
+ switch (sortKey) {
17
+ case 'vendor':
18
+ return (s) => s.vendor.name?.toLowerCase();
19
+ case 'category':
20
+ return (s) => s.jeDebit.account?.accountName?.toLowerCase();
21
+ case 'class':
22
+ return (s) => s.jeDebit.accountingClass?.className?.toLowerCase();
23
+ case 'depCategory':
24
+ return (s) => s.jeCredit.account?.accountName?.toLowerCase();
25
+ case 'scheduleCategory':
26
+ return (s) => s.jeScheduleType;
27
+ case 'startMonth':
28
+ return (s) => s.startDate?.valueOf();
29
+ case 'type':
30
+ return (s) => s.baseTransaction.typeOfTransaction;
31
+ case 'amortizationPeriod':
32
+ return (s) => s.period;
33
+ case 'jePostingDate':
34
+ return (s) => s.dayOfPostingDate;
35
+ case 'remainingMonths':
36
+ return (s) => s.period;
37
+ case 'runningBalance':
38
+ return (s) => s.balanceAsOfToday?.amount;
39
+ case 'totalAmount':
40
+ return (s) => s.baseTransaction.amount.amount;
41
+ case 'transactionDate':
42
+ return (s) => s.baseTransaction.date.valueOf();
43
+ case 'memo':
44
+ return (s) => s.baseTransaction.memo?.toLowerCase();
45
+ default:
46
+ return (s) => s.startDate?.valueOf();
47
+ }
48
+ }
49
+ function sortJEScheduledTransactions(transactions, sortKey, sortOrder) {
50
+ const accessor = getJEScheduleSortAccessor(sortKey);
51
+ return orderBy(transactions, [accessor], [sortOrder === 'ascending' ? 'asc' : 'desc']);
52
+ }
13
53
  export function getExpenseAutomationJESchedulesView(state) {
14
54
  const jeScheduledTransaction = [];
15
55
  const failedJeScheduledTransaction = [];
16
- const { accountState, accountListState, classState, classListState, expenseAutomationJESchedulesViewState, expenseAutomationViewState, monthEndCloseChecksState, } = state;
56
+ const { accountState, accountListState, classState, classListState, expenseAutomationJESchedulesViewState, expenseAutomationViewState, monthEndCloseChecksState, monthEndCloseChecksViewState, } = state;
17
57
  const { jeScheduleTransactionKeysByPeriod, failedJeScheduleTransactionKeysByPeriod, jeScheduleLocalDataById, postStatusById, ignoreStatusById, uiState, error, fetchState, refreshStatus, } = expenseAutomationJESchedulesViewState;
18
58
  const accountSettingsView = getJEAccountSettingsView(state);
19
59
  const currentTenant = getCurrentTenant(state);
@@ -59,18 +99,33 @@ export function getExpenseAutomationJESchedulesView(state) {
59
99
  const jeScheduleDetails = getJEScheduledTransactionByJEScheduleTransactionKey(jeScheduleKey, state);
60
100
  failedJeScheduledTransaction.push(jeScheduleDetails);
61
101
  });
62
- const draftSchedules = jeScheduledTransaction.filter((schedule) => schedule.status.code === 'draft');
63
- const resolveSchedules = [];
102
+ const { sortKey, sortOrder } = uiState;
103
+ const draftSchedules = sortJEScheduledTransactions(jeScheduledTransaction.filter((schedule) => schedule.status.code === 'draft'), sortKey, sortOrder);
104
+ const ongoingSchedules = sortJEScheduledTransactions(jeScheduledTransaction.filter((schedule) => schedule.status.code === 'ongoing'), sortKey, sortOrder);
105
+ const completedSchedules = sortJEScheduledTransactions(jeScheduledTransaction.filter((schedule) => schedule.status.code === 'completed' ||
106
+ schedule.status.code === 'marked_as_completed'), sortKey, sortOrder);
107
+ const unsortedResolveSchedules = [];
64
108
  failedJeScheduledTransaction.forEach((schedule) => {
65
109
  schedule.scheduledJournalEntry.forEach((journalEntry) => {
66
- resolveSchedules.push({ ...schedule, scheduledJournalEntry: journalEntry });
110
+ unsortedResolveSchedules.push({
111
+ ...schedule,
112
+ scheduledJournalEntry: journalEntry,
113
+ });
67
114
  });
68
115
  });
116
+ const resolveSchedules = sortJEScheduledTransactions(unsortedResolveSchedules, sortKey, sortOrder);
69
117
  const allSteps = monthYearPeriodId != null
70
118
  ? getAllSteps(monthEndCloseChecksState, monthYearPeriodId, currentTenant.tenantId)
71
119
  : [];
72
120
  const jeCompletionStatus = allSteps.find((step) => step.step === 'je_schedules')?.completionStatus;
73
121
  const completionStatus = jeCompletionStatus != null ? jeCompletionStatus : 'incomplete';
122
+ const monthEndFetchState = monthYearPeriodId != null
123
+ ? (monthEndCloseChecksViewState.monthEndCloseChecksViewByTenantId[currentTenant.tenantId]?.[monthYearPeriodId] ?? { fetchState: 'Not-Started', error: undefined })
124
+ : { fetchState: 'Not-Started', error: undefined };
125
+ const reducedFetchStatus = reduceAnyFetchState([
126
+ { fetchState, error },
127
+ monthEndFetchState,
128
+ ]);
74
129
  return {
75
130
  uncategorizedAccounts,
76
131
  allDepreciationAccountList: filteredDepAccounts,
@@ -79,15 +134,17 @@ export function getExpenseAutomationJESchedulesView(state) {
79
134
  allAccountList: filteredAccounts,
80
135
  accountListNestedAccountHierarchy,
81
136
  allClassList: allClasses,
137
+ completedSchedules,
82
138
  draftSchedules,
139
+ ongoingSchedules,
83
140
  resolveSchedules: resolveSchedules,
84
141
  accountSettingsView,
85
142
  postStatusById: postStatusById,
86
143
  ignoreStatusById: ignoreStatusById,
87
- fetchState: fetchState,
144
+ fetchState: reducedFetchStatus.fetchState,
88
145
  jeScheduleLocalDataById: jeScheduleLocalDataById,
89
146
  uiState: uiState,
90
- error: error,
147
+ error: reducedFetchStatus.error,
91
148
  refreshStatus,
92
149
  completionStatus,
93
150
  };