@zeniai/client-epic-state 4.20.3-betaRD11 → 4.20.3-betaRD21

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 (124) hide show
  1. package/lib/commonStateTypes/viewAndReport/viewAndReport.d.ts +2 -2
  2. package/lib/commonStateTypes/viewAndReport/viewAndReport.js +1 -0
  3. package/lib/entity/account/accountPayload.d.ts +2 -0
  4. package/lib/entity/account/accountReducer.d.ts +5 -2
  5. package/lib/entity/account/accountReducer.js +7 -2
  6. package/lib/entity/account/accountState.d.ts +1 -1
  7. package/lib/entity/accountGroup/accountGroupState.d.ts +1 -1
  8. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerPayload.d.ts +44 -0
  9. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerPayload.js +55 -0
  10. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerReducer.d.ts +10 -0
  11. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerReducer.js +51 -0
  12. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerSelector.d.ts +48 -0
  13. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerSelector.js +66 -0
  14. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerState.d.ts +52 -0
  15. package/lib/entity/aiAccountantCustomer/aiAccountantCustomerState.js +37 -0
  16. package/lib/entity/billPay/billTransaction/billTransactionState.d.ts +2 -2
  17. package/lib/entity/chargeCard/chargeCard.d.ts +1 -1
  18. package/lib/entity/class/classReducer.d.ts +4 -4
  19. package/lib/entity/class/classState.d.ts +1 -1
  20. package/lib/entity/depositAccountTransaction/depositAccountTransaction.d.ts +1 -1
  21. package/lib/entity/entityApprovalStatus/entityApprovalStatusState.d.ts +2 -2
  22. package/lib/entity/forecast/forecastState.d.ts +1 -1
  23. package/lib/entity/jeSchedules/jeSchedulesTypes.d.ts +1 -1
  24. package/lib/entity/sectionAccountsView/sectionAccountsView.d.ts +1 -1
  25. package/lib/entity/sectionClassesViewV2/sectionClassesView.d.ts +1 -1
  26. package/lib/entity/sectionClassesViewV2/sectionClassesViewReducer.d.ts +2 -2
  27. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  28. package/lib/entity/tenant/clearAllEpic.d.ts +3 -1
  29. package/lib/entity/tenant/clearAllEpic.js +4 -0
  30. package/lib/entity/transaction/payloadTypes/transactionPayload.js +1 -0
  31. package/lib/entity/userRole/userRoleType.d.ts +2 -2
  32. package/lib/epic.d.ts +9 -7
  33. package/lib/epic.js +9 -7
  34. package/lib/esm/commonStateTypes/viewAndReport/viewAndReport.js +1 -0
  35. package/lib/esm/entity/account/accountReducer.js +6 -1
  36. package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerPayload.js +49 -0
  37. package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerReducer.js +47 -0
  38. package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerSelector.js +62 -0
  39. package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerState.js +31 -0
  40. package/lib/esm/entity/tenant/clearAllEpic.js +4 -0
  41. package/lib/esm/entity/transaction/payloadTypes/transactionPayload.js +1 -0
  42. package/lib/esm/epic.js +9 -7
  43. package/lib/esm/index.js +11 -4
  44. package/lib/esm/reducer.js +6 -0
  45. package/lib/esm/view/aiAccountantView/aiAccountantViewPayload.js +2 -0
  46. package/lib/esm/view/aiAccountantView/aiAccountantViewReducer.js +149 -0
  47. package/lib/esm/view/aiAccountantView/aiAccountantViewSelector.js +72 -0
  48. package/lib/esm/view/aiAccountantView/aiAccountantViewState.js +11 -0
  49. package/lib/esm/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.js +46 -0
  50. package/lib/esm/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.js +27 -0
  51. package/lib/esm/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.js +47 -0
  52. package/lib/esm/view/aiAccountantView/epics/triggerAiAccountantJobEpic.js +52 -0
  53. package/lib/esm/view/expenseAutomationView/epics/accountRecon/excludeAccountFromReconciliationEpic.js +44 -0
  54. package/lib/esm/view/expenseAutomationView/epics/accountRecon/fetchReconciliationViewEpic.js +4 -9
  55. package/lib/esm/view/expenseAutomationView/epics/accountRecon/includeAccountInReconciliationEpic.js +44 -0
  56. package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +5 -1
  57. package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +163 -3
  58. package/lib/esm/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.js +1 -2
  59. package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +112 -0
  60. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +1 -2
  61. package/lib/esm/view/expenseAutomationView/types/jeSchedulesViewState.js +6 -0
  62. package/lib/index.d.ts +12 -4
  63. package/lib/index.js +64 -32
  64. package/lib/reducer.d.ts +6 -0
  65. package/lib/reducer.js +6 -0
  66. package/lib/tsconfig.typecheck.tsbuildinfo +1 -1
  67. package/lib/view/aiAccountantView/aiAccountantViewPayload.d.ts +31 -0
  68. package/lib/view/aiAccountantView/aiAccountantViewPayload.js +8 -0
  69. package/lib/view/aiAccountantView/aiAccountantViewReducer.d.ts +29 -0
  70. package/lib/view/aiAccountantView/aiAccountantViewReducer.js +153 -0
  71. package/lib/view/aiAccountantView/aiAccountantViewSelector.d.ts +14 -0
  72. package/lib/view/aiAccountantView/aiAccountantViewSelector.js +78 -0
  73. package/lib/view/aiAccountantView/aiAccountantViewState.d.ts +27 -0
  74. package/lib/view/aiAccountantView/aiAccountantViewState.js +13 -0
  75. package/lib/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.d.ts +33 -0
  76. package/lib/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.js +50 -0
  77. package/lib/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.d.ts +23 -0
  78. package/lib/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.js +31 -0
  79. package/lib/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.d.ts +33 -0
  80. package/lib/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.js +51 -0
  81. package/lib/view/aiAccountantView/epics/triggerAiAccountantJobEpic.d.ts +28 -0
  82. package/lib/view/aiAccountantView/epics/triggerAiAccountantJobEpic.js +56 -0
  83. package/lib/view/auditReportView/auditReportViewState.d.ts +1 -1
  84. package/lib/view/billPayCard/billPayCardSelector.d.ts +1 -1
  85. package/lib/view/cardBalance/cardBalanceSelector.d.ts +1 -1
  86. package/lib/view/cashBalance/cashBalanceSelector.d.ts +1 -1
  87. package/lib/view/cashInCashOut/cashInCashOutSelector.d.ts +1 -1
  88. package/lib/view/cashPosition/cashPositionSelector.d.ts +1 -1
  89. package/lib/view/companyView/types/cockpitTypes.d.ts +6 -5
  90. package/lib/view/dashboard/dashboardReducer.d.ts +2 -2
  91. package/lib/view/expenseAutomationView/epics/accountRecon/excludeAccountFromReconciliationEpic.d.ts +8 -0
  92. package/lib/view/expenseAutomationView/epics/accountRecon/excludeAccountFromReconciliationEpic.js +48 -0
  93. package/lib/view/expenseAutomationView/epics/accountRecon/fetchReconciliationViewEpic.js +4 -9
  94. package/lib/view/expenseAutomationView/epics/accountRecon/includeAccountInReconciliationEpic.d.ts +9 -0
  95. package/lib/view/expenseAutomationView/epics/accountRecon/includeAccountInReconciliationEpic.js +48 -0
  96. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  97. package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +33 -0
  98. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +5 -1
  99. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +18 -4
  100. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +164 -4
  101. package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.d.ts +6 -2
  102. package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.js +2 -2
  103. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +112 -0
  104. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +1 -2
  105. package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +3 -0
  106. package/lib/view/expenseAutomationView/types/jeSchedulesViewState.js +8 -1
  107. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +1 -1
  108. package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +13 -0
  109. package/lib/view/financeStatement/financeStatementReducer.d.ts +1 -1
  110. package/lib/view/globalMerchantView/globalMerchantViewReducer.d.ts +2 -2
  111. package/lib/view/onboardingView/cockpitView/types/onboardingCockpitViewTypes.d.ts +1 -1
  112. package/lib/view/reimbursementCard/reimbursementCardSelector.d.ts +1 -1
  113. package/lib/view/reportsResync/reportsResyncReducer.d.ts +2 -2
  114. package/lib/view/reviewCompanyView/reviewCompanyViewState.d.ts +1 -1
  115. package/lib/view/spendManagement/billPay/billList/billListReducer.d.ts +1 -1
  116. package/lib/view/spendManagement/billPay/billList/billListState.d.ts +1 -1
  117. package/lib/view/spendManagement/chargeCards/chargeCardDetail/chargeCardDetail.d.ts +1 -1
  118. package/lib/view/spendManagement/chargeCards/chargeCardDetail/chargeCardDetailReducer.d.ts +4 -4
  119. package/lib/view/spendManagement/reimbursement/remiListView/remiListReducer.d.ts +1 -1
  120. package/lib/view/spendManagement/reimbursement/remiListView/remiListState.d.ts +3 -3
  121. package/lib/view/subscriptionView/types/subscriptionTypes.d.ts +1 -1
  122. package/lib/view/tasksCard/tasksCardSelector.d.ts +1 -1
  123. package/lib/view/topEx/topExSelector.d.ts +1 -1
  124. package/package.json +1 -1
@@ -0,0 +1,46 @@
1
+ import { from } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
4
+ import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
5
+ import { cancelAiAccountantOnboarding, cancelAiAccountantOnboardingFailure, cancelAiAccountantOnboardingSuccess, fetchAiAccountantCustomers, } from '../aiAccountantViewReducer';
6
+ export const cancelAiAccountantOnboardingEpic = (actions$, _, zeniAPI) => actions$.pipe(filter(cancelAiAccountantOnboarding.match), mergeMap((action) => {
7
+ const { tenantId, companyId } = action.payload;
8
+ const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
9
+ const url = `${base}/ai-accountant/cancel-onboarding`;
10
+ return zeniAPI
11
+ .postAndGetJSON(url, {
12
+ tenant_id: tenantId,
13
+ company_id: companyId,
14
+ })
15
+ .pipe(mergeMap((response) => {
16
+ if (isSuccessResponse(response)) {
17
+ return from([
18
+ cancelAiAccountantOnboardingSuccess(tenantId),
19
+ fetchAiAccountantCustomers(),
20
+ openSnackbar({
21
+ messageSection: 'common',
22
+ messageText: 'success',
23
+ type: 'success',
24
+ }),
25
+ ]);
26
+ }
27
+ else {
28
+ return from([
29
+ cancelAiAccountantOnboardingFailure(tenantId, response.status),
30
+ openSnackbar({
31
+ messageSection: 'common',
32
+ messageText: 'failed',
33
+ type: 'error',
34
+ }),
35
+ ]);
36
+ }
37
+ }), catchError((error) => from([
38
+ cancelAiAccountantOnboardingFailure(tenantId, createZeniAPIStatus('Unexpected error', 'AI Accountant cancel onboarding failed: ' +
39
+ JSON.stringify(error))),
40
+ openSnackbar({
41
+ messageSection: 'common',
42
+ messageText: 'failed',
43
+ type: 'error',
44
+ }),
45
+ ])));
46
+ }));
@@ -0,0 +1,27 @@
1
+ import { from, of } from 'rxjs';
2
+ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
+ import { updateAiAccountantCustomers as updateAiAccountantCustomerEntities } from '../../../entity/aiAccountantCustomer/aiAccountantCustomerReducer';
4
+ import { updateAllUsers } from '../../../entity/user/userReducer';
5
+ import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
6
+ import { fetchAiAccountantCustomers, updateAiAccountantCustomers, updateAiAccountantCustomersFailure, } from '../aiAccountantViewReducer';
7
+ export const fetchAiAccountantCustomersEpic = (actions$, _, zeniAPI) => actions$.pipe(filter(fetchAiAccountantCustomers.match), switchMap(() => {
8
+ const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
9
+ const url = `${base}/ai-accountant/customers`;
10
+ return zeniAPI
11
+ .getJSON(url)
12
+ .pipe(mergeMap((response) => {
13
+ if (isSuccessResponse(response)) {
14
+ const customers = response.data?.customers ?? [];
15
+ const users = response.data?.users ?? [];
16
+ return from([
17
+ updateAiAccountantCustomerEntities(customers),
18
+ updateAllUsers({ users }),
19
+ updateAiAccountantCustomers(customers),
20
+ ]);
21
+ }
22
+ else {
23
+ return of(updateAiAccountantCustomersFailure(response.status));
24
+ }
25
+ }), catchError((error) => of(updateAiAccountantCustomersFailure(createZeniAPIStatus('Unexpected error', 'AI Accountant customers fetch failed: ' +
26
+ JSON.stringify(error))))));
27
+ }));
@@ -0,0 +1,47 @@
1
+ import { from, of } from 'rxjs';
2
+ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
+ import { updateAiAccountantJobs as updateAiAccountantJobEntities } from '../../../entity/aiAccountantCustomer/aiAccountantCustomerReducer';
4
+ import { updateAllUsers } from '../../../entity/user/userReducer';
5
+ import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
6
+ import { fetchAiAccountantJobs, updateAiAccountantJobs, updateAiAccountantJobsFailure, } from '../aiAccountantViewReducer';
7
+ export const fetchAiAccountantJobsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchAiAccountantJobs.match), switchMap((action) => {
8
+ const { tenantId, fetchNextPage } = action.payload;
9
+ const rootState = state$.value;
10
+ const customerView = rootState.aiAccountantViewState.customersByTenantId[tenantId];
11
+ const pageToken = fetchNextPage && customerView?.jobsPageToken != null
12
+ ? customerView.jobsPageToken
13
+ : null;
14
+ const params = new URLSearchParams({
15
+ page_size: '50',
16
+ tenant_id: tenantId,
17
+ });
18
+ if (pageToken != null) {
19
+ params.set('page_token', pageToken);
20
+ }
21
+ const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
22
+ const url = `${base}/ai-accountant/jobs?${params.toString()}`;
23
+ return zeniAPI
24
+ .getJSON(url)
25
+ .pipe(mergeMap((response) => {
26
+ if (isSuccessResponse(response)) {
27
+ const jobs = response.data?.jobs ?? [];
28
+ const users = response.data?.users ?? [];
29
+ const nextPageToken = response.data?.next_page_token ?? null;
30
+ return from([
31
+ updateAllUsers({ users }),
32
+ updateAiAccountantJobEntities(tenantId, jobs, fetchNextPage),
33
+ updateAiAccountantJobs(tenantId, nextPageToken),
34
+ ]);
35
+ }
36
+ else {
37
+ return of(updateAiAccountantJobsFailure({
38
+ tenantId,
39
+ error: response.status,
40
+ }));
41
+ }
42
+ }), catchError((error) => of(updateAiAccountantJobsFailure({
43
+ tenantId,
44
+ error: createZeniAPIStatus('Unexpected error', 'AI Accountant jobs fetch failed: ' +
45
+ JSON.stringify(error)),
46
+ }))));
47
+ }));
@@ -0,0 +1,52 @@
1
+ import { from } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
4
+ import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
5
+ import { fetchAiAccountantCustomers, triggerAiAccountantJob, triggerAiAccountantJobFailure, triggerAiAccountantJobSuccess, } from '../aiAccountantViewReducer';
6
+ export const triggerAiAccountantJobEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(triggerAiAccountantJob.match), mergeMap((action) => {
7
+ const { operationType, startDate, endDate } = action.payload;
8
+ const rootState = state$.value;
9
+ const selectedTenantIds = rootState.aiAccountantViewState.selectedTenantIdsForJobTrigger;
10
+ const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
11
+ const url = `${base}/ai-accountant/jobs`;
12
+ return zeniAPI
13
+ .postAndGetJSON(url, {
14
+ tenant_ids: selectedTenantIds,
15
+ operation_type: operationType,
16
+ params: {
17
+ start_date: startDate,
18
+ end_date: endDate,
19
+ },
20
+ })
21
+ .pipe(mergeMap((response) => {
22
+ if (isSuccessResponse(response)) {
23
+ return from([
24
+ triggerAiAccountantJobSuccess(),
25
+ fetchAiAccountantCustomers(),
26
+ openSnackbar({
27
+ messageSection: 'common',
28
+ messageText: 'success',
29
+ type: 'success',
30
+ }),
31
+ ]);
32
+ }
33
+ else {
34
+ return from([
35
+ triggerAiAccountantJobFailure(response.status),
36
+ openSnackbar({
37
+ messageSection: 'common',
38
+ messageText: 'failed',
39
+ type: 'error',
40
+ }),
41
+ ]);
42
+ }
43
+ }), catchError((error) => from([
44
+ triggerAiAccountantJobFailure(createZeniAPIStatus('Unexpected error', 'AI Accountant trigger job failed: ' +
45
+ JSON.stringify(error))),
46
+ openSnackbar({
47
+ messageSection: 'common',
48
+ messageText: 'failed',
49
+ type: 'error',
50
+ }),
51
+ ])));
52
+ }));
@@ -0,0 +1,44 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { changeAccountKey } from '../../../../entity/account/accountReducer';
4
+ import { getAccountKey } from '../../../../entity/account/accountState';
5
+ import { getAccountReconByAccountIdAndSelectedPeriod } from '../../../../entity/accountRecon/accountReconSelector';
6
+ import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
7
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
8
+ import { excludeAccountFromReconciliation, excludeAccountFromReconciliationFailure, excludeAccountFromReconciliationSuccess, } from '../../reducers/reconciliationViewReducer';
9
+ export const excludeAccountFromReconciliationEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(excludeAccountFromReconciliation.match), mergeMap((action) => {
10
+ const { accountId } = action.payload;
11
+ const state = state$.value;
12
+ const currentTenant = getCurrentTenant(state);
13
+ const selectedPeriod = state.expenseAutomationViewState.selectedPeriodByTenantId[currentTenant.tenantId];
14
+ const reconciliationData = getAccountReconByAccountIdAndSelectedPeriod(state, accountId, selectedPeriod);
15
+ const payload = {
16
+ account_id: accountId,
17
+ bank_balance: reconciliationData?.balance?.amount ?? null,
18
+ cleared_balance: reconciliationData?.clearedBalance?.amount ?? null,
19
+ variance: reconciliationData?.variance?.amount ?? null,
20
+ };
21
+ const apiUrl = `${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/1.0/reconciliation/excluded-accounts`;
22
+ return zeniAPI
23
+ .postAndGetJSON(apiUrl, payload)
24
+ .pipe(mergeMap((response) => {
25
+ if (isSuccessResponse(response)) {
26
+ const newAccountKey = getAccountKey('excluded_account_reconciliation', accountId);
27
+ const oldAccountKey = getAccountKey('account_reconciliation', accountId);
28
+ return of(excludeAccountFromReconciliationSuccess({
29
+ account: response.data?.excluded_account ?? undefined,
30
+ selectedPeriod,
31
+ }), changeAccountKey({
32
+ oldKey: oldAccountKey,
33
+ newKey: newAccountKey,
34
+ }));
35
+ }
36
+ else {
37
+ return of(excludeAccountFromReconciliationFailure({
38
+ error: response.status,
39
+ }));
40
+ }
41
+ }), catchError((error) => of(excludeAccountFromReconciliationFailure({
42
+ error: createZeniAPIStatus('Unexpected Error', `Exclude account from reconciliation REST API call errored out ${JSON.stringify(error)}`),
43
+ }))));
44
+ }));
@@ -53,22 +53,17 @@ export const fetchReconciliationViewEpic = (actions$, state$, zeniAPI) => action
53
53
  return zeniAPI.getJSON(apiUrl).pipe(mergeMap((response) => {
54
54
  if (isSuccessResponse(response) && response.data != null) {
55
55
  const updateActions = [];
56
- updateActions.push(updateAccounts(response.data.accounts, 'account_reconciliation'));
57
- updateActions.push(updateAllUsers({
56
+ const allTransactionsPerRecon = getAllReviewTransactionsFromReconcilePayload(response.data.reconciliation);
57
+ updateActions.push(updateAccounts(response.data.accounts, 'account_reconciliation'), updateAccounts(response.data.excluded_accounts ?? [], 'excluded_account_reconciliation'), updateAllUsers({
58
58
  users: response.data.users ?? [],
59
59
  updateType: 'merge',
60
- }));
61
- updateActions.push(updateFiles({ files: response.data.files ?? [] }));
62
- const allTransactionsPerRecon = getAllReviewTransactionsFromReconcilePayload(response.data.reconciliation);
63
- updateActions.push(updateMultipleReconcileTransactions(allTransactionsPerRecon, 'merge'));
64
- updateActions.push(updateAccountRecon(selectedPeriod, response.data.reconciliation));
60
+ }), updateFiles({ files: response.data.files ?? [] }), updateMultipleReconcileTransactions(allTransactionsPerRecon, 'merge'), updateAccountRecon(selectedPeriod, response.data.reconciliation));
65
61
  const reviewTabLocalData = prepareReviewTabLocalData(response.data.reconciliation[0]?.transactions?.review ?? []);
66
62
  if (accountId != null) {
67
63
  const selectedTransactionIds = getTransactionIdFromCheckedMatchedTransactionPayload(response.data.reconciliation[0].transactions.reconcile);
68
64
  updateActions.push(updateReconcileTabLocalData({
69
65
  selectedTransactionIds: selectedTransactionIds,
70
- }));
71
- updateActions.push(initializeReconciliationReviewTabLocalData(reviewTabLocalData));
66
+ }), initializeReconciliationReviewTabLocalData(reviewTabLocalData));
72
67
  }
73
68
  updateActions.push(fetchReconciliationSuccess(selectedPeriod, response.data, refreshViewInBackground, accountId));
74
69
  return from(updateActions);
@@ -0,0 +1,44 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { convertToPeriod } from '../../../../commonStateTypes/timePeriod';
4
+ import { changeAccountKey } from '../../../../entity/account/accountReducer';
5
+ import { getAccountKey } from '../../../../entity/account/accountState';
6
+ import { updateAccountRecon } from '../../../../entity/accountRecon/accountReconReducer';
7
+ import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
8
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
9
+ import { includeAccountInReconciliation, includeAccountInReconciliationFailure, includeAccountInReconciliationSuccess, } from '../../reducers/reconciliationViewReducer';
10
+ export const includeAccountInReconciliationEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(includeAccountInReconciliation.match), mergeMap((action) => {
11
+ const { accountId } = action.payload;
12
+ const state = state$.value;
13
+ const currentTenant = getCurrentTenant(state);
14
+ const selectedPeriod = state.expenseAutomationViewState.selectedPeriodByTenantId[currentTenant.tenantId];
15
+ const period = convertToPeriod(selectedPeriod, true);
16
+ const query = JSON.stringify({
17
+ start_date: period.start,
18
+ end_date: period.end,
19
+ });
20
+ const apiUrl = `${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/1.0/reconciliation/excluded-accounts/${accountId}?query=${encodeURIComponent(query)}`;
21
+ return zeniAPI
22
+ .deleteAndGetJSON(apiUrl)
23
+ .pipe(mergeMap((response) => {
24
+ if (isSuccessResponse(response) && response.data != null) {
25
+ const reconciliation = response.data.reconciliation;
26
+ const oldAccountKey = getAccountKey('excluded_account_reconciliation', reconciliation.account_id);
27
+ const newAccountKey = getAccountKey('account_reconciliation', reconciliation.account_id);
28
+ return of(updateAccountRecon(selectedPeriod, [reconciliation]), includeAccountInReconciliationSuccess({
29
+ reconciliation,
30
+ selectedPeriod,
31
+ }), changeAccountKey({
32
+ oldKey: oldAccountKey,
33
+ newKey: newAccountKey,
34
+ }));
35
+ }
36
+ else {
37
+ return of(includeAccountInReconciliationFailure({
38
+ error: response.status,
39
+ }));
40
+ }
41
+ }), catchError((error) => of(includeAccountInReconciliationFailure({
42
+ error: createZeniAPIStatus('Unexpected Error', `Include account in reconciliation REST API call errored out ${JSON.stringify(error)}`),
43
+ }))));
44
+ }));
@@ -44,7 +44,8 @@ export const initialState = {
44
44
  uiState: {
45
45
  searchString: '',
46
46
  scrollPosition: { scrollTop: 0, scrollLeft: undefined },
47
- sortKey: 'startMonth',
47
+ selectedMainTab: 'pending_review',
48
+ sortKey: 'transactionDate',
48
49
  sortOrder: 'descending',
49
50
  totalCount: 0,
50
51
  limit: 10,
@@ -380,6 +381,9 @@ const expenseAutomationJESchedulesView = createSlice({
380
381
  if (action.payload.scrollPosition != null) {
381
382
  draft.uiState.scrollPosition = action.payload.scrollPosition;
382
383
  }
384
+ if (action.payload.selectedMainTab != null) {
385
+ draft.uiState.selectedMainTab = action.payload.selectedMainTab;
386
+ }
383
387
  },
384
388
  clearExpenseAutomationJESchedulesView(draft) {
385
389
  Object.assign(draft, initialState);
@@ -37,7 +37,15 @@ export const initialReconciliationTabsState = {
37
37
  },
38
38
  };
39
39
  export const initialActionFetchState = {
40
+ excludeAccountFetch: {
41
+ fetchState: 'Not-Started',
42
+ error: undefined,
43
+ },
40
44
  excludeFetchById: {},
45
+ includeAccountFetch: {
46
+ fetchState: 'Not-Started',
47
+ error: undefined,
48
+ },
41
49
  reconcileFetch: {
42
50
  fetchState: 'Not-Started',
43
51
  error: undefined,
@@ -51,6 +59,7 @@ export const initialActionFetchState = {
51
59
  export const initialState = {
52
60
  accountReconciliationRecordsBySelectedPeriod: {},
53
61
  accountConnectionStatusByAccountID: {},
62
+ excludedAccountExclusionInfo: {},
54
63
  fetchState: 'Not-Started',
55
64
  error: undefined,
56
65
  selectedTab: 'review',
@@ -60,10 +69,12 @@ export const initialState = {
60
69
  selectedAccountId: undefined,
61
70
  statementUploadChosen: false,
62
71
  reconListUIState: {
72
+ nodeCollapseState: {},
63
73
  scrollPosition: {
64
74
  scrollTop: 0,
65
75
  },
66
76
  },
77
+ excludedAccountIDs: [],
67
78
  };
68
79
  // Create slice with reducers
69
80
  const expenseAutomationReconciliationView = createSlice({
@@ -132,7 +143,7 @@ const expenseAutomationReconciliationView = createSlice({
132
143
  fetchReconciliationSuccess: {
133
144
  reducer(draft, action) {
134
145
  if (action.payload.accountId == null) {
135
- updateAllReconciliation(draft, action.payload.reconciliation.accounts, action.payload.selectedPeriod, action.payload.reconciliation.reconciliation, action.payload.refreshViewInBackground);
146
+ updateAllReconciliation(draft, action.payload.reconciliation.accounts, action.payload.selectedPeriod, action.payload.reconciliation.reconciliation, action.payload.refreshViewInBackground, action.payload.reconciliation.excluded_accounts ?? []);
136
147
  }
137
148
  else if (action.payload.reconciliation.reconciliation.length > 0 &&
138
149
  action.payload.reconciliation.accounts.length > 0) {
@@ -344,6 +355,10 @@ const expenseAutomationReconciliationView = createSlice({
344
355
  updateReconListScrollPosition: (draft, action) => {
345
356
  draft.reconListUIState.scrollPosition = action.payload.scrollPosition;
346
357
  },
358
+ updateNodeCollapseState: (draft, action) => {
359
+ draft.reconListUIState.nodeCollapseState[action.payload.nodeId] =
360
+ action.payload.collapsed;
361
+ },
347
362
  setConnectionInProgressForAccount: (draft, action) => {
348
363
  if (draft.accountConnectionStatusByAccountID[action.payload.accountId] ==
349
364
  null) {
@@ -421,6 +436,85 @@ const expenseAutomationReconciliationView = createSlice({
421
436
  ...localData,
422
437
  };
423
438
  },
439
+ excludeAccountFromReconciliation: {
440
+ reducer(draft) {
441
+ draft.actionFetchState.excludeAccountFetch = {
442
+ fetchState: 'In-Progress',
443
+ error: undefined,
444
+ };
445
+ },
446
+ prepare(payload) {
447
+ return { payload };
448
+ },
449
+ },
450
+ excludeAccountFromReconciliationSuccess: (draft, action) => {
451
+ draft.actionFetchState.excludeAccountFetch = {
452
+ fetchState: 'Completed',
453
+ error: undefined,
454
+ };
455
+ const { account, selectedPeriod } = action.payload;
456
+ if (account != null) {
457
+ if (!draft.excludedAccountIDs.includes(account.account_id)) {
458
+ draft.excludedAccountIDs.push(account.account_id);
459
+ }
460
+ updateExcludedAccountExclusionInfo(draft, account);
461
+ const monthYearPeriodId = toMonthYearPeriodId(selectedPeriod);
462
+ if (draft.accountReconciliationRecordsBySelectedPeriod[monthYearPeriodId]
463
+ ?.accountIDs != null) {
464
+ draft.accountReconciliationRecordsBySelectedPeriod[monthYearPeriodId].accountIDs = draft.accountReconciliationRecordsBySelectedPeriod[monthYearPeriodId].accountIDs.filter((id) => id !== account.account_id);
465
+ }
466
+ }
467
+ },
468
+ excludeAccountFromReconciliationFailure: (draft, action) => {
469
+ draft.actionFetchState.excludeAccountFetch = {
470
+ fetchState: 'Error',
471
+ error: action.payload.error,
472
+ };
473
+ },
474
+ includeAccountInReconciliation: {
475
+ reducer(draft) {
476
+ draft.actionFetchState.includeAccountFetch = {
477
+ fetchState: 'In-Progress',
478
+ error: undefined,
479
+ };
480
+ },
481
+ prepare(payload) {
482
+ return { payload };
483
+ },
484
+ },
485
+ includeAccountInReconciliationSuccess: (draft, action) => {
486
+ draft.actionFetchState.includeAccountFetch = {
487
+ fetchState: 'Completed',
488
+ error: undefined,
489
+ };
490
+ const { reconciliation, selectedPeriod } = action.payload;
491
+ if (reconciliation == null) {
492
+ return;
493
+ }
494
+ const accountId = reconciliation.account_id;
495
+ draft.excludedAccountIDs = draft.excludedAccountIDs.filter((id) => id !== accountId);
496
+ delete draft.excludedAccountExclusionInfo[accountId];
497
+ const monthYearPeriodId = toMonthYearPeriodId(selectedPeriod);
498
+ const accountReconciliationRecords = draft.accountReconciliationRecordsBySelectedPeriod[monthYearPeriodId];
499
+ if (accountReconciliationRecords != null) {
500
+ if (!accountReconciliationRecords.accountIDs.includes(accountId)) {
501
+ accountReconciliationRecords.accountIDs.push(accountId);
502
+ }
503
+ // put this in a function
504
+ updateReconciliationByAccountIDOnIncludeAccount(draft, accountId, reconciliation, monthYearPeriodId);
505
+ }
506
+ draft.accountConnectionStatusByAccountID[accountId] = {
507
+ status: toBankStatusCodeType(reconciliation.bank_status.code),
508
+ connectionInProgress: false,
509
+ paymentAccountId: undefined,
510
+ };
511
+ },
512
+ includeAccountInReconciliationFailure: (draft, action) => {
513
+ draft.actionFetchState.includeAccountFetch = {
514
+ fetchState: 'Error',
515
+ error: action.payload.error,
516
+ };
517
+ },
424
518
  updateStatementUploadChosen: (draft, action) => {
425
519
  draft.statementUploadChosen = action.payload.statementUploadChosen;
426
520
  },
@@ -430,10 +524,38 @@ const expenseAutomationReconciliationView = createSlice({
430
524
  },
431
525
  });
432
526
  // Export actions
433
- export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, updateStatementUploadChosen, } = expenseAutomationReconciliationView.actions;
527
+ export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, excludeAccountFromReconciliation, excludeAccountFromReconciliationSuccess, excludeAccountFromReconciliationFailure, includeAccountInReconciliation, includeAccountInReconciliationSuccess, includeAccountInReconciliationFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, updateStatementUploadChosen, updateNodeCollapseState, } = expenseAutomationReconciliationView.actions;
434
528
  // Export reducer
435
529
  export default expenseAutomationReconciliationView.reducer;
436
- function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliationData, refreshViewInBackground) {
530
+ function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliationData, refreshViewInBackground, excludedAccounts) {
531
+ draft.excludedAccountIDs = excludedAccounts.map((ea) => ea.account_id);
532
+ draft.excludedAccountExclusionInfo = {};
533
+ excludedAccounts.forEach((ea) => {
534
+ const { exclusion_info } = ea;
535
+ draft.excludedAccountExclusionInfo[ea.account_id] = {
536
+ bankBalance: exclusion_info.bank_balance != null
537
+ ? {
538
+ amount: exclusion_info.bank_balance,
539
+ currencyCode: ea.currency_code ?? 'USD',
540
+ currencySymbol: ea.currency_symbol ?? '$',
541
+ }
542
+ : undefined,
543
+ clearedBalance: exclusion_info.cleared_balance != null
544
+ ? {
545
+ amount: exclusion_info.cleared_balance,
546
+ currencyCode: ea.currency_code ?? 'USD',
547
+ currencySymbol: ea.currency_symbol ?? '$',
548
+ }
549
+ : undefined,
550
+ variance: exclusion_info.variance != null
551
+ ? {
552
+ amount: exclusion_info.variance,
553
+ currencyCode: ea.currency_code ?? 'USD',
554
+ currencySymbol: ea.currency_symbol ?? '$',
555
+ }
556
+ : undefined,
557
+ };
558
+ });
437
559
  draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)] = {
438
560
  accountIDs: [],
439
561
  reconciliationByAccountID: {},
@@ -516,3 +638,41 @@ function updateReconciliationByAccountID(draft, accounts, selectedPeriod, accoun
516
638
  };
517
639
  }
518
640
  }
641
+ const updateExcludedAccountExclusionInfo = (draft, account) => {
642
+ draft.excludedAccountExclusionInfo[account.account_id] = {
643
+ bankBalance: account.bank_balance != null
644
+ ? {
645
+ amount: account.bank_balance,
646
+ currencyCode: account.currency_code ?? 'USD',
647
+ currencySymbol: account.currency_symbol ?? '$',
648
+ }
649
+ : undefined,
650
+ clearedBalance: account.cleared_balance != null
651
+ ? {
652
+ amount: account.cleared_balance,
653
+ currencyCode: account.currency_code ?? 'USD',
654
+ currencySymbol: account.currency_symbol ?? '$',
655
+ }
656
+ : undefined,
657
+ variance: account.variance != null
658
+ ? {
659
+ amount: account.variance,
660
+ currencyCode: account.currency_code ?? 'USD',
661
+ currencySymbol: account.currency_symbol ?? '$',
662
+ }
663
+ : undefined,
664
+ };
665
+ };
666
+ const updateReconciliationByAccountIDOnIncludeAccount = (draft, accountId, reconciliation, monthYearPeriodId) => {
667
+ draft.accountReconciliationRecordsBySelectedPeriod[monthYearPeriodId].reconciliationByAccountID[accountId] = {
668
+ accountId,
669
+ reconciliationId: reconciliation.reconciliation_id ?? undefined,
670
+ transactionFetchState: { fetchState: 'Not-Started', error: undefined },
671
+ refreshStatus: { fetchState: 'Not-Started', error: undefined },
672
+ statementDeleteStatus: { fetchState: 'Not-Started', error: undefined },
673
+ statementUploadStatus: { fetchState: 'Not-Started', error: undefined },
674
+ statementUpdateStatus: { fetchState: 'Not-Started', error: undefined },
675
+ statementParseInProgress: reconciliation.bank_status.code === 'parsing',
676
+ localData: {},
677
+ };
678
+ };
@@ -1,4 +1,3 @@
1
1
  import { stringToUnion } from '../../../commonStateTypes/stringToUnion';
2
2
  export const ALL_ACCOUNT_RECON_SECTION_IDS = ['assets', 'liabilities'];
3
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4
- const toAccountReconSectionID = (v) => stringToUnion(v, ALL_ACCOUNT_RECON_SECTION_IDS);
3
+ export const toAccountReconSectionID = (v) => stringToUnion(v, ALL_ACCOUNT_RECON_SECTION_IDS);