@zeniai/client-epic-state 5.2.14 → 5.2.16
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.
- package/lib/entity/accountRecon/accountReconReducer.d.ts +2 -1
- package/lib/entity/accountRecon/accountReconReducer.js +22 -10
- package/lib/entity/accountRecon/accountReconSelector.d.ts +1 -0
- package/lib/entity/accountRecon/accountReconSelector.js +1 -0
- package/lib/entity/approvalRule/approvalRuleConflict.d.ts +13 -0
- package/lib/entity/approvalRule/approvalRuleConflict.js +16 -1
- package/lib/entity/jeSchedules/jeScheduleHelper.d.ts +1 -0
- package/lib/entity/jeSchedules/jeScheduleHelper.js +7 -0
- package/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +78 -1
- package/lib/entity/jeSchedules/jeSchedulesPayload.js +183 -4
- package/lib/entity/jeSchedules/jeSchedulesReducer.d.ts +4 -2
- package/lib/entity/jeSchedules/jeSchedulesReducer.js +30 -2
- package/lib/entity/jeSchedules/jeSchedulesSelector.d.ts +11 -2
- package/lib/entity/jeSchedules/jeSchedulesSelector.js +38 -3
- package/lib/entity/jeSchedules/jeSchedulesState.d.ts +123 -1
- package/lib/entity/jeSchedules/jeSchedulesTypes.d.ts +24 -1
- package/lib/entity/jeSchedules/jeSchedulesTypes.js +96 -1
- package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.js +3 -0
- package/lib/entity/transaction/payloadTypes/scheduleTransactionPayload.d.ts +2 -0
- package/lib/entity/transaction/payloadTypes/scheduleTransactionPayload.js +2 -0
- package/lib/entity/transaction/stateTypes/scheduleTransaction.d.ts +2 -0
- package/lib/epic.d.ts +10 -1
- package/lib/epic.js +18 -0
- package/lib/esm/entity/accountRecon/accountReconReducer.js +22 -10
- package/lib/esm/entity/accountRecon/accountReconSelector.js +1 -0
- package/lib/esm/entity/approvalRule/approvalRuleConflict.js +16 -1
- package/lib/esm/entity/jeSchedules/jeScheduleHelper.js +6 -0
- package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +183 -5
- package/lib/esm/entity/jeSchedules/jeSchedulesReducer.js +30 -2
- package/lib/esm/entity/jeSchedules/jeSchedulesSelector.js +36 -2
- package/lib/esm/entity/jeSchedules/jeSchedulesTypes.js +86 -0
- package/lib/esm/entity/snackbar/snackbarTypes.js +3 -0
- package/lib/esm/entity/transaction/payloadTypes/scheduleTransactionPayload.js +2 -0
- package/lib/esm/epic.js +18 -0
- package/lib/esm/index.js +16 -10
- package/lib/esm/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +2 -2
- package/lib/esm/view/expenseAutomationView/epics/accountRecon/deleteCombinedStatementEpic.js +54 -0
- package/lib/esm/view/expenseAutomationView/epics/accountRecon/fetchReconciliationViewEpic.js +1 -1
- package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.js +3 -6
- package/lib/esm/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +6 -3
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulePageEpic.js +9 -1
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +41 -5
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchOneTimeAccrualEpic.js +45 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/ignoreRecommendedJeScheduleEpic.js +14 -2
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/createOneTimeAccrualEpic.js +104 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.js +25 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.js +138 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.js +79 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/oneTimeAccrualActionsEpic.js +180 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/revertJeScheduleEpic.js +111 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +28 -0
- package/lib/esm/view/expenseAutomationView/helpers/newScheduleLocalDataHelper.js +140 -0
- package/lib/esm/view/expenseAutomationView/helpers/reconciliationHelpers.js +12 -0
- package/lib/esm/view/expenseAutomationView/payload/jeSchedulesPayload.js +55 -0
- package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +319 -29
- package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +20 -2
- package/lib/esm/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.js +1 -0
- package/lib/esm/view/expenseAutomationView/selectors/jeAccountSettingsViewSelector.js +1 -0
- package/lib/esm/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.js +106 -0
- package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +327 -22
- package/lib/esm/view/expenseAutomationView/types/jeSchedulesViewState.js +5 -6
- package/lib/esm/view/scheduleView/scheduleListView/epics/fetchAccruedScheduleListEpic.js +1 -1
- package/lib/esm/view/scheduleView/scheduleListView/epics/fetchDownloadSchedulesEpic.js +7 -2
- package/lib/esm/view/scheduleView/scheduleListView/scheduleListReducer.js +5 -3
- package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/billPaySetupApproverViewSelector.js +20 -1
- package/lib/esm/view/spendManagement/reimbursement/remiSetupApproverView/remiSetupApproverViewSelector.js +20 -1
- package/lib/index.d.ts +18 -13
- package/lib/index.js +92 -47
- package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.d.ts +10 -2
- package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +1 -1
- package/lib/view/expenseAutomationView/epics/accountRecon/deleteCombinedStatementEpic.d.ts +9 -0
- package/lib/view/expenseAutomationView/epics/accountRecon/deleteCombinedStatementEpic.js +58 -0
- package/lib/view/expenseAutomationView/epics/accountRecon/fetchReconciliationViewEpic.js +1 -1
- package/lib/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.js +3 -6
- package/lib/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +6 -3
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulePageEpic.js +9 -1
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.d.ts +3 -2
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +39 -3
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchOneTimeAccrualEpic.d.ts +21 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchOneTimeAccrualEpic.js +49 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/ignoreRecommendedJeScheduleEpic.js +14 -2
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/createOneTimeAccrualEpic.d.ts +9 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/createOneTimeAccrualEpic.js +108 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.d.ts +8 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.js +29 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.d.ts +9 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.js +142 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.d.ts +8 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.js +83 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/oneTimeAccrualActionsEpic.d.ts +13 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/oneTimeAccrualActionsEpic.js +187 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/revertJeScheduleEpic.d.ts +65 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/revertJeScheduleEpic.js +115 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.d.ts +6 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +32 -0
- package/lib/view/expenseAutomationView/helpers/newScheduleLocalDataHelper.d.ts +36 -0
- package/lib/view/expenseAutomationView/helpers/newScheduleLocalDataHelper.js +145 -0
- package/lib/view/expenseAutomationView/helpers/reconciliationHelpers.d.ts +6 -0
- package/lib/view/expenseAutomationView/helpers/reconciliationHelpers.js +13 -0
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/expenseAutomationView/payload/jeSchedulesPayload.d.ts +86 -3
- package/lib/view/expenseAutomationView/payload/jeSchedulesPayload.js +58 -1
- package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +4 -0
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +93 -12
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +321 -29
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +1 -1
- package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +6 -1
- package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +22 -4
- package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +2 -2
- package/lib/view/expenseAutomationView/selectorTypes/jeAccountSettingsViewSelectorTypes.d.ts +1 -0
- package/lib/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.d.ts +42 -0
- package/lib/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.js +2 -0
- package/lib/view/expenseAutomationView/selectorTypes/jeSchedulesSelectorTypes.d.ts +41 -7
- package/lib/view/expenseAutomationView/selectors/jeAccountSettingsViewSelector.js +1 -0
- package/lib/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.d.ts +21 -0
- package/lib/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.js +112 -0
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.d.ts +34 -0
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +335 -21
- package/lib/view/expenseAutomationView/types/completedSubTab.d.ts +1 -1
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +83 -8
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.js +8 -8
- package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +1 -1
- package/lib/view/scheduleView/scheduleListView/epics/fetchAccruedScheduleListEpic.js +1 -1
- package/lib/view/scheduleView/scheduleListView/epics/fetchDownloadSchedulesEpic.js +7 -2
- package/lib/view/scheduleView/scheduleListView/scheduleListReducer.d.ts +4 -2
- package/lib/view/scheduleView/scheduleListView/scheduleListReducer.js +5 -3
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/billPaySetupApproverViewSelector.js +20 -1
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/billPaySetupApproverViewSelectorTypes.d.ts +3 -0
- package/lib/view/spendManagement/reimbursement/remiSetupApproverView/remiSetupApproverViewSelector.js +20 -1
- package/lib/view/spendManagement/reimbursement/remiSetupApproverView/remiSetupApproverViewSelectorTypes.d.ts +3 -0
- package/package.json +1 -1
|
@@ -2,9 +2,16 @@ import { createSlice } from '@reduxjs/toolkit';
|
|
|
2
2
|
import { geNestedAccountIDHierarchyForReport } from '../../../commonStateTypes/accountView/getNestedAccountIDHierarchyForReport';
|
|
3
3
|
import { toMonthYearPeriodId, } from '../../../commonStateTypes/timePeriod';
|
|
4
4
|
import { mapAccountBasePayloadToAccountBase, mapAccountMetadataPayloadToAccountMetadata, } from '../../../entity/account/accountPayload';
|
|
5
|
-
import {
|
|
5
|
+
import { generateJEOneTimeAccrualKey } from '../../../entity/jeSchedules/jeScheduleHelper';
|
|
6
|
+
import { getJEScheduleKey, getJEScheduleTransactionDetailKeyPayload, } from '../../../entity/jeSchedules/jeSchedulesPayload';
|
|
6
7
|
import { clearAll } from '../../../rootActions';
|
|
7
8
|
import { mapAccountTypeRecommendationPayloadToAccountRecommendationByType, } from '../../accountMappingView/accountTypeRecommendation/accountTypeRecommendationPayload';
|
|
9
|
+
import { MIN_NEW_SCHEDULE_SEARCH_LENGTH, getJESchedulePeriodTabKey, } from '../types/jeSchedulesViewState';
|
|
10
|
+
function removeKeyFromEveryTabSlot(keysByPeriodAndTab, keyToRemove) {
|
|
11
|
+
for (const periodTabKey of Object.keys(keysByPeriodAndTab)) {
|
|
12
|
+
keysByPeriodAndTab[periodTabKey] = keysByPeriodAndTab[periodTabKey].filter((jeScheduleKey) => jeScheduleKey !== keyToRemove);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
8
15
|
export const accountSettingsInitialState = {
|
|
9
16
|
localData: {
|
|
10
17
|
selectedPrepaidExpensesAccountIds: [],
|
|
@@ -18,6 +25,7 @@ export const accountSettingsInitialState = {
|
|
|
18
25
|
error: undefined,
|
|
19
26
|
fetchState: 'Not-Started',
|
|
20
27
|
},
|
|
28
|
+
hasLoadedAccountSettings: false,
|
|
21
29
|
recommendationFetchState: {
|
|
22
30
|
error: undefined,
|
|
23
31
|
fetchState: 'Not-Started',
|
|
@@ -36,16 +44,37 @@ export const accountSettingsInitialState = {
|
|
|
36
44
|
accruedExpensesNestedAccountListHierarchy: [],
|
|
37
45
|
accruedExpensesRecommendations: [],
|
|
38
46
|
};
|
|
47
|
+
export const getBaseNewScheduleLocalData = (scheduleType) => ({
|
|
48
|
+
scheduleType,
|
|
49
|
+
jeScheduleDetails: [],
|
|
50
|
+
});
|
|
51
|
+
export const newScheduleInitialState = {
|
|
52
|
+
fixed_assets: getBaseNewScheduleLocalData('fixed_assets'),
|
|
53
|
+
prepaid_expenses: getBaseNewScheduleLocalData('prepaid_expenses'),
|
|
54
|
+
};
|
|
55
|
+
export const searchTransactionsInitialState = {
|
|
56
|
+
searchResults: [],
|
|
57
|
+
fetchState: 'Not-Started',
|
|
58
|
+
error: undefined,
|
|
59
|
+
};
|
|
39
60
|
export const initialState = {
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
jeScheduleTransactionKeysByPeriodAndTab: {},
|
|
62
|
+
jeScheduleAccruedKeysByPeriodAndTab: {},
|
|
63
|
+
jeScheduleOneTimeAccrualKeysByPeriodAndTab: {},
|
|
64
|
+
failedJeScheduleTransactionKeysByPeriodAndTab: {},
|
|
42
65
|
postStatusById: {},
|
|
43
66
|
ignoreStatusById: {},
|
|
67
|
+
revertStatusById: {},
|
|
44
68
|
jeScheduleLocalDataById: {},
|
|
69
|
+
oneTimeAccrualActionStatusById: {},
|
|
70
|
+
oneTimeAccrualFetchStatusById: {},
|
|
45
71
|
uiState: {
|
|
46
|
-
|
|
72
|
+
createdGroupCollapsed: false,
|
|
73
|
+
pendingGroupCollapsed: false,
|
|
47
74
|
scrollPosition: { scrollTop: 0, scrollLeft: undefined },
|
|
48
|
-
|
|
75
|
+
searchString: '',
|
|
76
|
+
selectedJETypeFilter: null,
|
|
77
|
+
selectedPageTab: 'schedules',
|
|
49
78
|
sortKey: 'transactionDate',
|
|
50
79
|
sortOrder: 'descending',
|
|
51
80
|
totalCount: 0,
|
|
@@ -56,6 +85,14 @@ export const initialState = {
|
|
|
56
85
|
error: undefined,
|
|
57
86
|
},
|
|
58
87
|
accountSettings: accountSettingsInitialState,
|
|
88
|
+
newSchedule: {
|
|
89
|
+
createOneTimeAccrualStatus: { fetchState: 'Not-Started', error: undefined },
|
|
90
|
+
newScheduleState: newScheduleInitialState,
|
|
91
|
+
saveStatus: { fetchState: 'Not-Started', error: undefined },
|
|
92
|
+
searchTransactions: searchTransactionsInitialState,
|
|
93
|
+
fetchState: 'Not-Started',
|
|
94
|
+
error: undefined,
|
|
95
|
+
},
|
|
59
96
|
fetchState: 'Not-Started',
|
|
60
97
|
error: undefined,
|
|
61
98
|
hasValidState() {
|
|
@@ -100,9 +137,12 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
100
137
|
},
|
|
101
138
|
},
|
|
102
139
|
fetchJeSchedulesSuccess(draft, action) {
|
|
103
|
-
const { jeSchedules, selectedPeriod, failedJeSchedules, refreshViewInBackground, } = action.payload;
|
|
140
|
+
const { jeSchedules, selectedPeriod, selectedPageTab, failedJeSchedules, accruedJeSchedules, oneTimeAccruals, refreshViewInBackground, } = action.payload;
|
|
141
|
+
const periodTabKey = getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod));
|
|
104
142
|
const jeScheduleTransactionKeys = jeSchedules.map((schedules) => getJEScheduleTransactionDetailKeyPayload(schedules.base_transaction));
|
|
105
143
|
const failedJeScheduleTransactionKeys = failedJeSchedules.map((schedules) => getJEScheduleTransactionDetailKeyPayload(schedules.base_transaction));
|
|
144
|
+
const jeScheduleAccruedKeys = accruedJeSchedules.map((schedule) => getJEScheduleKey(schedule));
|
|
145
|
+
const jeScheduleOneTimeAccrualKeys = oneTimeAccruals.map((accrual) => generateJEOneTimeAccrualKey(accrual._id));
|
|
106
146
|
if (refreshViewInBackground === true &&
|
|
107
147
|
draft.refreshStatus.fetchState === 'In-Progress') {
|
|
108
148
|
draft.refreshStatus = { fetchState: 'Completed', error: undefined };
|
|
@@ -111,19 +151,31 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
111
151
|
draft.fetchState = 'Completed';
|
|
112
152
|
draft.error = undefined;
|
|
113
153
|
}
|
|
114
|
-
draft.
|
|
115
|
-
|
|
154
|
+
draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
|
|
155
|
+
jeScheduleTransactionKeys;
|
|
156
|
+
draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] =
|
|
157
|
+
jeScheduleAccruedKeys;
|
|
158
|
+
draft.jeScheduleOneTimeAccrualKeysByPeriodAndTab[periodTabKey] =
|
|
159
|
+
jeScheduleOneTimeAccrualKeys;
|
|
160
|
+
draft.failedJeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
|
|
161
|
+
failedJeScheduleTransactionKeys;
|
|
116
162
|
},
|
|
117
163
|
fetchJeSchedulesFailure(draft, action) {
|
|
118
|
-
const { status, selectedPeriod } = action.payload;
|
|
164
|
+
const { status, selectedPeriod, selectedPageTab } = action.payload;
|
|
165
|
+
const periodTabKey = getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod));
|
|
119
166
|
if (draft.refreshStatus.fetchState === 'In-Progress') {
|
|
120
167
|
draft.refreshStatus = { fetchState: 'Error', error: status };
|
|
121
168
|
}
|
|
122
169
|
else {
|
|
123
170
|
draft.fetchState = 'Error';
|
|
124
171
|
draft.error = status;
|
|
172
|
+
draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] = [];
|
|
173
|
+
draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] = [];
|
|
174
|
+
draft.jeScheduleOneTimeAccrualKeysByPeriodAndTab[periodTabKey] = [];
|
|
175
|
+
// Cleared with the rest: leaving it behind kept the previous fetch's resolve rows on an
|
|
176
|
+
// otherwise empty errored tab, which reads as "these are all the schedules there are".
|
|
177
|
+
draft.failedJeScheduleTransactionKeysByPeriodAndTab[periodTabKey] = [];
|
|
125
178
|
}
|
|
126
|
-
draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = [];
|
|
127
179
|
},
|
|
128
180
|
retryJeSchedule(draft, action) {
|
|
129
181
|
const { scheduledJournalEntryID } = action.payload;
|
|
@@ -159,11 +211,13 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
159
211
|
};
|
|
160
212
|
},
|
|
161
213
|
ignoreRecommendedJeSchedule: {
|
|
162
|
-
prepare(jeScheduleTransactionKey, scheduleType) {
|
|
214
|
+
prepare(jeScheduleTransactionKey, scheduleType, reason, note) {
|
|
163
215
|
return {
|
|
164
216
|
payload: {
|
|
165
217
|
jeScheduleTransactionKey,
|
|
166
218
|
scheduleType,
|
|
219
|
+
reason,
|
|
220
|
+
note,
|
|
167
221
|
},
|
|
168
222
|
};
|
|
169
223
|
},
|
|
@@ -179,6 +233,41 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
179
233
|
};
|
|
180
234
|
},
|
|
181
235
|
},
|
|
236
|
+
revertJeSchedule: {
|
|
237
|
+
// jeScheduleTransactionKey is a JEScheduleKey for an accrued schedule, which has no base
|
|
238
|
+
// transaction to derive a transaction key from. It is only ever used as an opaque row
|
|
239
|
+
// identifier here -- for the row's spinner and for dropping the row from the list -- so one
|
|
240
|
+
// action serves both shapes rather than two near-identical ones.
|
|
241
|
+
prepare(jeScheduleId, jeScheduleTransactionKey, scheduleType, reason, note) {
|
|
242
|
+
return {
|
|
243
|
+
payload: {
|
|
244
|
+
jeScheduleId,
|
|
245
|
+
jeScheduleTransactionKey,
|
|
246
|
+
scheduleType,
|
|
247
|
+
reason,
|
|
248
|
+
note,
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
},
|
|
252
|
+
reducer(draft, action) {
|
|
253
|
+
draft.revertStatusById[action.payload.jeScheduleTransactionKey] = {
|
|
254
|
+
fetchState: 'In-Progress',
|
|
255
|
+
error: undefined,
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
revertJeScheduleSuccess(draft, action) {
|
|
260
|
+
draft.revertStatusById[action.payload.jeScheduleTransactionKey] = {
|
|
261
|
+
fetchState: 'Completed',
|
|
262
|
+
error: undefined,
|
|
263
|
+
};
|
|
264
|
+
},
|
|
265
|
+
revertJeScheduleFailure(draft, action) {
|
|
266
|
+
draft.revertStatusById[action.payload.jeScheduleTransactionKey] = {
|
|
267
|
+
fetchState: 'Error',
|
|
268
|
+
error: action.payload.status,
|
|
269
|
+
};
|
|
270
|
+
},
|
|
182
271
|
ignoreRecommendedJeScheduleSuccess: {
|
|
183
272
|
reducer(draft, action) {
|
|
184
273
|
const { jeScheduleTransactionKey } = action.payload;
|
|
@@ -211,17 +300,18 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
211
300
|
};
|
|
212
301
|
},
|
|
213
302
|
updateJeScheduleTransactionKeys: {
|
|
214
|
-
prepare(jeScheduleKeys, selectedPeriod) {
|
|
303
|
+
prepare(jeScheduleKeys, selectedPeriod, selectedPageTab) {
|
|
215
304
|
return {
|
|
216
305
|
payload: {
|
|
217
306
|
jeScheduleKeys: jeScheduleKeys,
|
|
218
307
|
selectedPeriod: selectedPeriod,
|
|
308
|
+
selectedPageTab: selectedPageTab,
|
|
219
309
|
},
|
|
220
310
|
};
|
|
221
311
|
},
|
|
222
312
|
reducer(draft, action) {
|
|
223
|
-
const { selectedPeriod, jeScheduleKeys } = action.payload;
|
|
224
|
-
draft.
|
|
313
|
+
const { selectedPeriod, selectedPageTab, jeScheduleKeys } = action.payload;
|
|
314
|
+
draft.jeScheduleTransactionKeysByPeriodAndTab[getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod))] = jeScheduleKeys;
|
|
225
315
|
},
|
|
226
316
|
},
|
|
227
317
|
removeJeScheduleTransactionKey: {
|
|
@@ -234,12 +324,20 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
234
324
|
};
|
|
235
325
|
},
|
|
236
326
|
reducer(draft, action) {
|
|
237
|
-
const {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
327
|
+
const { jeScheduleKey } = action.payload;
|
|
328
|
+
// Dropped from every tab's slot, not just the visible one: once a schedule is ignored or
|
|
329
|
+
// resolved it must not reappear when the user switches tabs and hits a cached list.
|
|
330
|
+
removeKeyFromEveryTabSlot(draft.jeScheduleTransactionKeysByPeriodAndTab, jeScheduleKey);
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
removeJeAccruedScheduleKey: {
|
|
334
|
+
prepare(jeAccruedScheduleKey) {
|
|
335
|
+
return { payload: { jeAccruedScheduleKey } };
|
|
336
|
+
},
|
|
337
|
+
reducer(draft, action) {
|
|
338
|
+
// Accrued keys live in their own per-tab map, so removeJeScheduleTransactionKey cannot drop
|
|
339
|
+
// them -- a reverted accrued schedule stayed on the list until the next fetch.
|
|
340
|
+
removeKeyFromEveryTabSlot(draft.jeScheduleAccruedKeysByPeriodAndTab, action.payload.jeAccruedScheduleKey);
|
|
243
341
|
},
|
|
244
342
|
},
|
|
245
343
|
removeFailedJeScheduleTransactionKey: {
|
|
@@ -252,12 +350,8 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
252
350
|
};
|
|
253
351
|
},
|
|
254
352
|
reducer(draft, action) {
|
|
255
|
-
const {
|
|
256
|
-
|
|
257
|
-
...(draft.failedJeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] ?? []),
|
|
258
|
-
];
|
|
259
|
-
const filteredKeys = prevData.filter((jeKey) => jeKey !== failedJeScheduleKey);
|
|
260
|
-
draft.failedJeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = filteredKeys;
|
|
353
|
+
const { failedJeScheduleKey } = action.payload;
|
|
354
|
+
removeKeyFromEveryTabSlot(draft.failedJeScheduleTransactionKeysByPeriodAndTab, failedJeScheduleKey);
|
|
261
355
|
},
|
|
262
356
|
},
|
|
263
357
|
initializeJeScheduleLocalData: {
|
|
@@ -336,6 +430,9 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
336
430
|
error: status,
|
|
337
431
|
fetchState: 'Error',
|
|
338
432
|
};
|
|
433
|
+
// Set on failure too: a tenant whose account list errors must still reach the page rather
|
|
434
|
+
// than sit under a skeleton forever.
|
|
435
|
+
draft.accountSettings.hasLoadedAccountSettings = true;
|
|
339
436
|
},
|
|
340
437
|
updateAccountSettingsListForAccountTypes(draft, action) {
|
|
341
438
|
doUpdateAccountSettingsListForAccountTypes(draft.accountSettings, action.payload.accountPayload);
|
|
@@ -369,6 +466,187 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
369
466
|
clearJeAccountSettingsLocalData(draft) {
|
|
370
467
|
draft.accountSettings.localData = accountSettingsInitialState.localData;
|
|
371
468
|
},
|
|
469
|
+
initializeNewSchedule: {
|
|
470
|
+
prepare({ scheduleType, shouldResetEnteredData = true, }) {
|
|
471
|
+
return { payload: { scheduleType, shouldResetEnteredData } };
|
|
472
|
+
},
|
|
473
|
+
reducer() {
|
|
474
|
+
// Purely an epic-trigger action — the epic fans out the account/class
|
|
475
|
+
// list fetches, and clears entered data only when asked to.
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
resetNewScheduleLocalData: {
|
|
479
|
+
prepare({ scheduleType, }) {
|
|
480
|
+
return { payload: { scheduleType } };
|
|
481
|
+
},
|
|
482
|
+
reducer(draft, action) {
|
|
483
|
+
const { scheduleType } = action.payload;
|
|
484
|
+
draft.newSchedule.newScheduleState[scheduleType] =
|
|
485
|
+
getBaseNewScheduleLocalData(scheduleType);
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
updateNewScheduleLocalData(draft, action) {
|
|
489
|
+
const { scheduleType, localData } = action.payload;
|
|
490
|
+
draft.newSchedule.newScheduleState[scheduleType] = {
|
|
491
|
+
...draft.newSchedule.newScheduleState[scheduleType],
|
|
492
|
+
...localData,
|
|
493
|
+
};
|
|
494
|
+
},
|
|
495
|
+
searchTransactionsForNewSchedule: {
|
|
496
|
+
prepare({ query, scheduleType, }) {
|
|
497
|
+
return { payload: { query, scheduleType } };
|
|
498
|
+
},
|
|
499
|
+
reducer(draft, action) {
|
|
500
|
+
const trimmed = action.payload.query.trim();
|
|
501
|
+
// Cleared or too-short query: no API (see epic) — reset immediately.
|
|
502
|
+
if (trimmed.length < MIN_NEW_SCHEDULE_SEARCH_LENGTH) {
|
|
503
|
+
draft.newSchedule.searchTransactions = searchTransactionsInitialState;
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
draft.newSchedule.searchTransactions = {
|
|
507
|
+
...draft.newSchedule.searchTransactions,
|
|
508
|
+
searchString: action.payload.query,
|
|
509
|
+
fetchState: 'In-Progress',
|
|
510
|
+
};
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
searchTransactionsForNewScheduleSuccess(draft, action) {
|
|
514
|
+
draft.newSchedule.searchTransactions = {
|
|
515
|
+
...draft.newSchedule.searchTransactions,
|
|
516
|
+
searchResults: action.payload.searchResults,
|
|
517
|
+
fetchState: 'Completed',
|
|
518
|
+
error: undefined,
|
|
519
|
+
};
|
|
520
|
+
},
|
|
521
|
+
searchTransactionsForNewScheduleFailure(draft, action) {
|
|
522
|
+
draft.newSchedule.searchTransactions = {
|
|
523
|
+
...draft.newSchedule.searchTransactions,
|
|
524
|
+
fetchState: 'Error',
|
|
525
|
+
error: action.payload.status,
|
|
526
|
+
};
|
|
527
|
+
},
|
|
528
|
+
clearSearchTransactionsForNewSchedule(draft) {
|
|
529
|
+
draft.newSchedule.searchTransactions = searchTransactionsInitialState;
|
|
530
|
+
},
|
|
531
|
+
saveNewSchedule: {
|
|
532
|
+
prepare({ scheduleType, }) {
|
|
533
|
+
return { payload: { scheduleType } };
|
|
534
|
+
},
|
|
535
|
+
reducer(draft) {
|
|
536
|
+
draft.newSchedule.saveStatus = {
|
|
537
|
+
fetchState: 'In-Progress',
|
|
538
|
+
error: undefined,
|
|
539
|
+
};
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
saveNewScheduleSuccess(draft) {
|
|
543
|
+
draft.newSchedule.saveStatus = {
|
|
544
|
+
fetchState: 'Completed',
|
|
545
|
+
error: undefined,
|
|
546
|
+
};
|
|
547
|
+
},
|
|
548
|
+
saveNewScheduleFailure(draft, action) {
|
|
549
|
+
draft.newSchedule.saveStatus = {
|
|
550
|
+
fetchState: 'Error',
|
|
551
|
+
error: action.payload.status,
|
|
552
|
+
};
|
|
553
|
+
},
|
|
554
|
+
createOneTimeAccrual: {
|
|
555
|
+
prepare(localData) {
|
|
556
|
+
return { payload: { localData } };
|
|
557
|
+
},
|
|
558
|
+
reducer(draft) {
|
|
559
|
+
draft.newSchedule.createOneTimeAccrualStatus = {
|
|
560
|
+
fetchState: 'In-Progress',
|
|
561
|
+
error: undefined,
|
|
562
|
+
};
|
|
563
|
+
},
|
|
564
|
+
},
|
|
565
|
+
createOneTimeAccrualSuccess(draft) {
|
|
566
|
+
draft.newSchedule.createOneTimeAccrualStatus = {
|
|
567
|
+
fetchState: 'Completed',
|
|
568
|
+
error: undefined,
|
|
569
|
+
};
|
|
570
|
+
},
|
|
571
|
+
createOneTimeAccrualFailure(draft, action) {
|
|
572
|
+
draft.newSchedule.createOneTimeAccrualStatus = {
|
|
573
|
+
fetchState: 'Error',
|
|
574
|
+
error: action.payload.status,
|
|
575
|
+
};
|
|
576
|
+
},
|
|
577
|
+
/**
|
|
578
|
+
* Promote applies the body and posts in one step, so it carries whatever the user edited on the
|
|
579
|
+
* detail page. `edits` is absent when nothing was changed -- the epic then falls back to the
|
|
580
|
+
* stored accrual, which is what the list's inline Post does.
|
|
581
|
+
*/
|
|
582
|
+
promoteOneTimeAccrual: {
|
|
583
|
+
prepare(accrualId, amount, edits) {
|
|
584
|
+
return { payload: { accrualId, amount, edits } };
|
|
585
|
+
},
|
|
586
|
+
reducer(draft, action) {
|
|
587
|
+
draft.oneTimeAccrualActionStatusById[action.payload.accrualId] = {
|
|
588
|
+
fetchState: 'In-Progress',
|
|
589
|
+
error: undefined,
|
|
590
|
+
};
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
revertOneTimeAccrual: {
|
|
594
|
+
prepare(accrualId, reason, note) {
|
|
595
|
+
return { payload: { accrualId, reason, note } };
|
|
596
|
+
},
|
|
597
|
+
reducer(draft, action) {
|
|
598
|
+
draft.oneTimeAccrualActionStatusById[action.payload.accrualId] = {
|
|
599
|
+
fetchState: 'In-Progress',
|
|
600
|
+
error: undefined,
|
|
601
|
+
};
|
|
602
|
+
},
|
|
603
|
+
},
|
|
604
|
+
ignoreOneTimeAccrual: {
|
|
605
|
+
prepare(accrualId, reason, note) {
|
|
606
|
+
return { payload: { accrualId, reason, note } };
|
|
607
|
+
},
|
|
608
|
+
reducer(draft, action) {
|
|
609
|
+
draft.oneTimeAccrualActionStatusById[action.payload.accrualId] = {
|
|
610
|
+
fetchState: 'In-Progress',
|
|
611
|
+
error: undefined,
|
|
612
|
+
};
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
fetchOneTimeAccrual: {
|
|
616
|
+
prepare(accrualId) {
|
|
617
|
+
return { payload: { accrualId } };
|
|
618
|
+
},
|
|
619
|
+
reducer(draft, action) {
|
|
620
|
+
draft.oneTimeAccrualFetchStatusById[action.payload.accrualId] = {
|
|
621
|
+
fetchState: 'In-Progress',
|
|
622
|
+
error: undefined,
|
|
623
|
+
};
|
|
624
|
+
},
|
|
625
|
+
},
|
|
626
|
+
fetchOneTimeAccrualSuccess(draft, action) {
|
|
627
|
+
draft.oneTimeAccrualFetchStatusById[action.payload.accrualId] = {
|
|
628
|
+
fetchState: 'Completed',
|
|
629
|
+
error: undefined,
|
|
630
|
+
};
|
|
631
|
+
},
|
|
632
|
+
fetchOneTimeAccrualFailure(draft, action) {
|
|
633
|
+
draft.oneTimeAccrualFetchStatusById[action.payload.accrualId] = {
|
|
634
|
+
fetchState: 'Error',
|
|
635
|
+
error: action.payload.status,
|
|
636
|
+
};
|
|
637
|
+
},
|
|
638
|
+
oneTimeAccrualActionSuccess(draft, action) {
|
|
639
|
+
draft.oneTimeAccrualActionStatusById[action.payload.accrualId] = {
|
|
640
|
+
fetchState: 'Completed',
|
|
641
|
+
error: undefined,
|
|
642
|
+
};
|
|
643
|
+
},
|
|
644
|
+
oneTimeAccrualActionFailure(draft, action) {
|
|
645
|
+
draft.oneTimeAccrualActionStatusById[action.payload.accrualId] = {
|
|
646
|
+
fetchState: 'Error',
|
|
647
|
+
error: action.payload.status,
|
|
648
|
+
};
|
|
649
|
+
},
|
|
372
650
|
updateJESchedulesUIState(draft, action) {
|
|
373
651
|
if (action.payload.sortKey != null) {
|
|
374
652
|
draft.uiState.sortKey = action.payload.sortKey;
|
|
@@ -382,10 +660,21 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
382
660
|
if (action.payload.scrollPosition != null) {
|
|
383
661
|
draft.uiState.scrollPosition = action.payload.scrollPosition;
|
|
384
662
|
}
|
|
385
|
-
if (action.payload.
|
|
386
|
-
draft.uiState.
|
|
663
|
+
if (action.payload.selectedPageTab != null) {
|
|
664
|
+
draft.uiState.selectedPageTab = action.payload.selectedPageTab;
|
|
387
665
|
}
|
|
388
666
|
},
|
|
667
|
+
updateJEScheduleTypeFilter(draft, action) {
|
|
668
|
+
draft.uiState.selectedJETypeFilter = action.payload;
|
|
669
|
+
},
|
|
670
|
+
toggleJEPendingGroupCollapsed(draft) {
|
|
671
|
+
draft.uiState.pendingGroupCollapsed =
|
|
672
|
+
!draft.uiState.pendingGroupCollapsed;
|
|
673
|
+
},
|
|
674
|
+
toggleJECreatedGroupCollapsed(draft) {
|
|
675
|
+
draft.uiState.createdGroupCollapsed =
|
|
676
|
+
!draft.uiState.createdGroupCollapsed;
|
|
677
|
+
},
|
|
389
678
|
clearExpenseAutomationJESchedulesView(draft) {
|
|
390
679
|
Object.assign(draft, initialState);
|
|
391
680
|
},
|
|
@@ -396,7 +685,7 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
396
685
|
});
|
|
397
686
|
},
|
|
398
687
|
});
|
|
399
|
-
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;
|
|
688
|
+
export const { clearExpenseAutomationJESchedulesView, clearJeAccountSettingsLocalData, clearJeScheduleLocalData, clearSearchTransactionsForNewSchedule, createOneTimeAccrual, createOneTimeAccrualFailure, createOneTimeAccrualSuccess, ignoreOneTimeAccrual, oneTimeAccrualActionFailure, oneTimeAccrualActionSuccess, promoteOneTimeAccrual, revertJeSchedule, revertJeScheduleFailure, revertJeScheduleSuccess, revertOneTimeAccrual, fetchAccountSettingsListForAccountTypes, fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesPage, fetchJeSchedulesSuccess, fetchOneTimeAccrual, fetchOneTimeAccrualFailure, fetchOneTimeAccrualSuccess, fetchRecommendationForAccountSettings, ignoreRecommendedJeSchedule, ignoreRecommendedJeScheduleFailure, ignoreRecommendedJeScheduleSuccess, initializeAccountSettingsView, initializeJeScheduleLocalData, initializeNewSchedule, removeFailedJeScheduleTransactionKey, removeJeScheduleLocalDataById, removeJeAccruedScheduleKey, removeJeScheduleTransactionKey, resetNewScheduleLocalData, retryJeSchedule, retryJeScheduleFailure, retryJeScheduleSuccess, saveAccountSettings, saveAccountSettingsFailure, saveAccountSettingsLocalData, saveAccountSettingsSuccess, saveNewSchedule, saveNewScheduleFailure, saveNewScheduleSuccess, searchTransactionsForNewSchedule, searchTransactionsForNewScheduleFailure, searchTransactionsForNewScheduleSuccess, toggleJECreatedGroupCollapsed, toggleJEPendingGroupCollapsed, updateAccountSettingsListForAccountTypes, updateAccountSettingsListForAccountTypesFailure, updateJESchedulesUIState, updateJEScheduleTypeFilter, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, updateNewScheduleLocalData, updateRecommendationForAccountSettings, updateRecommendationForAccountSettingsFailure, } = expenseAutomationJESchedulesView.actions;
|
|
400
689
|
export default expenseAutomationJESchedulesView.reducer;
|
|
401
690
|
const doUpdateRecommendationForAccountSettings = (draft, payload) => {
|
|
402
691
|
const { prepaidExpensesRecommendations, fixedAssetsRecommendations, accruedExpensesRecommendations, } = mapAccountTypeRecommendationPayloadToAccountRecommendationByType(payload);
|
|
@@ -464,4 +753,5 @@ const doUpdateAccountSettingsListForAccountTypes = (draft, accountPayloadList) =
|
|
|
464
753
|
error: undefined,
|
|
465
754
|
fetchState: 'Completed',
|
|
466
755
|
};
|
|
756
|
+
draft.hasLoadedAccountSettings = true;
|
|
467
757
|
};
|
|
@@ -502,6 +502,18 @@ const expenseAutomationReconciliationView = createSlice({
|
|
|
502
502
|
// Drop sticky parse latch on discard so the drawer shows empty upload UI.
|
|
503
503
|
accountRecon.statementParseInProgress = false;
|
|
504
504
|
},
|
|
505
|
+
deleteCombinedStatement: (draft, action) => {
|
|
506
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
507
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
508
|
+
if (accountRecon == null) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
accountRecon.statementDeleteStatus = {
|
|
512
|
+
fetchState: 'In-Progress',
|
|
513
|
+
error: undefined,
|
|
514
|
+
};
|
|
515
|
+
accountRecon.statementParseInProgress = false;
|
|
516
|
+
},
|
|
505
517
|
deleteAccountStatementSuccess: (draft, action) => {
|
|
506
518
|
const { accountId, selectedPeriod } = action.payload;
|
|
507
519
|
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
@@ -912,7 +924,7 @@ const expenseAutomationReconciliationView = createSlice({
|
|
|
912
924
|
},
|
|
913
925
|
});
|
|
914
926
|
// Export actions
|
|
915
|
-
export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, setStatementProcessingDismissedToBackground, updateStatementProcessingBackgroundCompletedSteps, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateStatementProcessingFailed, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, excludeAccountFromReconciliation, excludeAccountFromReconciliationSuccess, excludeAccountFromReconciliationFailure, includeAccountInReconciliation, includeAccountInReconciliationSuccess, includeAccountInReconciliationFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, parseStatement, parseCombinedStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateStatementUpdateLocalData, submitStatementUpdate, submitCombinedStatementUpdate, submitStatementUpdateSuccess, submitStatementUpdateFailure, clearStatementDateConflict, confirmStatementMapping, confirmStatementMappingSuccess, confirmStatementMappingFailure, updateStatementUploadChosen, updateNodeCollapseState, } = expenseAutomationReconciliationView.actions;
|
|
927
|
+
export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, setStatementProcessingDismissedToBackground, updateStatementProcessingBackgroundCompletedSteps, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateStatementProcessingFailed, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteCombinedStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, excludeAccountFromReconciliation, excludeAccountFromReconciliationSuccess, excludeAccountFromReconciliationFailure, includeAccountInReconciliation, includeAccountInReconciliationSuccess, includeAccountInReconciliationFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, parseStatement, parseCombinedStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateStatementUpdateLocalData, submitStatementUpdate, submitCombinedStatementUpdate, submitStatementUpdateSuccess, submitStatementUpdateFailure, clearStatementDateConflict, confirmStatementMapping, confirmStatementMappingSuccess, confirmStatementMappingFailure, updateStatementUploadChosen, updateNodeCollapseState, } = expenseAutomationReconciliationView.actions;
|
|
916
928
|
// Export reducer
|
|
917
929
|
export default expenseAutomationReconciliationView.reducer;
|
|
918
930
|
function isEntityStatementParsing(reconciliation) {
|
|
@@ -1039,7 +1051,13 @@ function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliation
|
|
|
1039
1051
|
accountReconciliationRecords.reconciliationByAccountID[reconciliation.account_id] = {
|
|
1040
1052
|
accountId: reconciliation.account_id,
|
|
1041
1053
|
reconciliationId: reconciliation.reconciliation_id ?? undefined,
|
|
1042
|
-
|
|
1054
|
+
// Full list fetch does not load transactions; keep per-account detail
|
|
1055
|
+
// fetch status so an in-flight/completed review load is not reset to
|
|
1056
|
+
// Not-Started (review UI treats that as loading).
|
|
1057
|
+
transactionFetchState: oldRecord?.transactionFetchState ?? {
|
|
1058
|
+
fetchState: 'Not-Started',
|
|
1059
|
+
error: undefined,
|
|
1060
|
+
},
|
|
1043
1061
|
refreshStatus: { fetchState: 'Not-Started', error: undefined },
|
|
1044
1062
|
statementDeleteStatus: { fetchState: 'Not-Started', error: undefined },
|
|
1045
1063
|
statementUploadStatus: preserveStatementUploadStatusAfterFetch(oldRecord),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -22,6 +22,7 @@ export const getJEAccountSettingsView = createSelector((state) => state.expenseA
|
|
|
22
22
|
fixedAssetsAccountHierarchy: jeAccountMappingState.fixedAssetsNestedAccountListHierarchy,
|
|
23
23
|
accruedExpensesAccountHierarchy: jeAccountMappingState.accruedExpensesNestedAccountListHierarchy,
|
|
24
24
|
fetchState: fetchState.fetchState,
|
|
25
|
+
hasLoaded: jeAccountMappingState.hasLoadedAccountSettings,
|
|
25
26
|
saveState,
|
|
26
27
|
};
|
|
27
28
|
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { getAccountIdsForLabels, getAccountIdsForTypes, } from '../../../entity/account/accountSelector';
|
|
2
|
+
import { getScheduleTransactionById } from '../../../entity/transaction/transactionSelector';
|
|
3
|
+
import { getAccountIdsForLabel, getAccountList, getNestedAccountListHierarchy, } from '../../accountList/accountListSelector';
|
|
4
|
+
import { getClassList, getNestedClassListHierarchy, } from '../../classList/classListSelector';
|
|
5
|
+
import { getAccountsTypesForScheduleDetails } from '../../scheduleView/scheduleDetailView/scheduleDetailLocalDataHelper';
|
|
6
|
+
import { filterNestedAccountHierarchyById } from '../../scheduleView/scheduleDetailView/scheduleDetailSelector';
|
|
7
|
+
import { getAccountLabelForScheduleType, getAccountsTypesForScheduleEpics, } from '../../scheduleView/scheduleListView/scheduleListHelper';
|
|
8
|
+
/**
|
|
9
|
+
* The Base Transaction search is shared across schedule types (one search
|
|
10
|
+
* box, not one per prepaid_expenses/fixed_assets) — split out from
|
|
11
|
+
* getNewScheduleView so a consumer can read it without supplying an
|
|
12
|
+
* otherwise-irrelevant scheduleType.
|
|
13
|
+
*/
|
|
14
|
+
export const getNewScheduleSearchTransactionsView = (state) => {
|
|
15
|
+
const { searchTransactions } = state.expenseAutomationJESchedulesViewState.newSchedule;
|
|
16
|
+
const searchTransactionsResults = searchTransactions.searchResults
|
|
17
|
+
.map((key) => getScheduleTransactionById(state.transactionState, key))
|
|
18
|
+
.filter((transaction) => transaction != null);
|
|
19
|
+
return {
|
|
20
|
+
searchTransactionsResults,
|
|
21
|
+
searchTransactionsFetchState: {
|
|
22
|
+
fetchState: searchTransactions.fetchState,
|
|
23
|
+
error: searchTransactions.error,
|
|
24
|
+
},
|
|
25
|
+
searchTransactionsString: searchTransactions.searchString,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const ACCRUED_EXPENSE_ACCOUNT_LABELS = ['accrued_expenses'];
|
|
29
|
+
/**
|
|
30
|
+
* Account + class options and request status shared by both accrual creation forms — the one-time
|
|
31
|
+
* accrual and the recurring accrued schedule.
|
|
32
|
+
*
|
|
33
|
+
* getAccountsTypesForScheduleDetails('accrued_expenses') deliberately includes
|
|
34
|
+
* other_current_liabilities, because the accrued liability accounts live there —
|
|
35
|
+
* so the debit list has to subtract them back out, and the credit list keeps only
|
|
36
|
+
* them. Mirrors getScheduleAccruedDetailView, which is the form this one is
|
|
37
|
+
* modelled on.
|
|
38
|
+
*/
|
|
39
|
+
export const getNewAccrualAccountsView = (state) => {
|
|
40
|
+
const { accountState, accountListState, classState, classListState } = state;
|
|
41
|
+
const { newSchedule } = state.expenseAutomationJESchedulesViewState;
|
|
42
|
+
const accountType = getAccountsTypesForScheduleEpics();
|
|
43
|
+
const accrualAccountIds = getAccountIdsForTypes(accountState, getAccountsTypesForScheduleDetails('accrued_expenses'));
|
|
44
|
+
const accruedCategoryIds = getAccountIdsForLabels(accountState, ACCRUED_EXPENSE_ACCOUNT_LABELS);
|
|
45
|
+
const allAccountList = getAccountList(accountState, accountListState, accountType.accountListKey);
|
|
46
|
+
const nestedAccountHierarchy = getNestedAccountListHierarchy(accountListState, accountType.accountListKey);
|
|
47
|
+
const debitAccounts = allAccountList.accounts.filter((account) => accrualAccountIds.includes(account.accountId) &&
|
|
48
|
+
!accruedCategoryIds.includes(account.accountId));
|
|
49
|
+
const creditAccounts = allAccountList.accounts.filter((account) => accruedCategoryIds.includes(account.accountId));
|
|
50
|
+
const allClassList = getClassList(classState, classListState);
|
|
51
|
+
return {
|
|
52
|
+
accountListNestedAccountHierarchy: filterNestedAccountHierarchyById(nestedAccountHierarchy, debitAccounts.map((account) => account.accountId)),
|
|
53
|
+
accruedAccountListNestedAccountHierarchy: filterNestedAccountHierarchyById(nestedAccountHierarchy, creditAccounts.map((account) => account.accountId)),
|
|
54
|
+
allAccountList: debitAccounts,
|
|
55
|
+
allAccruedExpenseList: creditAccounts,
|
|
56
|
+
allClassList: allClassList.classes,
|
|
57
|
+
classListNestedAccountHierarchy: getNestedClassListHierarchy(classListState),
|
|
58
|
+
createStatus: newSchedule.createOneTimeAccrualStatus,
|
|
59
|
+
// The recurring accrued schedule saves through the accrued detail epics that the Vendor tab
|
|
60
|
+
// already uses, so its status is that slice's updateStatus rather than anything new here.
|
|
61
|
+
accruedScheduleSaveStatus: state.scheduleAccruedDetailState.updateStatus,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
export const getNewScheduleView = (state, scheduleType) => {
|
|
65
|
+
const { accountState, accountListState, classState, classListState } = state;
|
|
66
|
+
const { newSchedule } = state.expenseAutomationJESchedulesViewState;
|
|
67
|
+
const searchTransactionsView = getNewScheduleSearchTransactionsView(state);
|
|
68
|
+
const accountType = getAccountsTypesForScheduleEpics();
|
|
69
|
+
const newScheduleAccountTypes = getAccountsTypesForScheduleDetails(scheduleType);
|
|
70
|
+
const newScheduleAccountIds = getAccountIdsForTypes(accountState, newScheduleAccountTypes);
|
|
71
|
+
const allAccountList = getAccountList(accountState, accountListState, accountType.accountListKey);
|
|
72
|
+
const filteredAccounts = allAccountList.accounts.filter((account) => newScheduleAccountIds.includes(account.accountId));
|
|
73
|
+
const accountListNestedAccountHierarchy = filterNestedAccountHierarchyById(getNestedAccountListHierarchy(accountListState, accountType.accountListKey), filteredAccounts.map((account) => account.accountId));
|
|
74
|
+
const allClassList = getClassList(classState, classListState);
|
|
75
|
+
const classListNestedAccountHierarchy = getNestedClassListHierarchy(classListState);
|
|
76
|
+
let allDepreciationAccountList;
|
|
77
|
+
let allDepreciationAccountListNestedAccountHierarchy;
|
|
78
|
+
if (scheduleType === 'fixed_assets') {
|
|
79
|
+
const depreciationCategoryIds = getAccountIdsForTypes(accountState, [
|
|
80
|
+
'fixed_assets',
|
|
81
|
+
'other_assets',
|
|
82
|
+
]);
|
|
83
|
+
const accountLabel = getAccountLabelForScheduleType('fixed_assets');
|
|
84
|
+
const fixedAssetLabelAccountIds = accountLabel != null
|
|
85
|
+
? getAccountIdsForLabel(accountListState, accountType.accountListKey, accountLabel)
|
|
86
|
+
: [];
|
|
87
|
+
allDepreciationAccountList = allAccountList.accounts.filter((account) => depreciationCategoryIds.includes(account.accountId) &&
|
|
88
|
+
!fixedAssetLabelAccountIds.includes(account.accountId));
|
|
89
|
+
allDepreciationAccountListNestedAccountHierarchy =
|
|
90
|
+
filterNestedAccountHierarchyById(getNestedAccountListHierarchy(accountListState, accountType.accountListKey), allDepreciationAccountList.map((account) => account.accountId));
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
scheduleType,
|
|
94
|
+
accountListNestedAccountHierarchy,
|
|
95
|
+
allAccountList: filteredAccounts,
|
|
96
|
+
allClassList: allClassList.classes,
|
|
97
|
+
allDepreciationAccountList,
|
|
98
|
+
allDepreciationAccountListNestedAccountHierarchy,
|
|
99
|
+
classListNestedAccountHierarchy,
|
|
100
|
+
newScheduleLocalData: newSchedule.newScheduleState[scheduleType],
|
|
101
|
+
saveStatus: newSchedule.saveStatus,
|
|
102
|
+
...searchTransactionsView,
|
|
103
|
+
fetchState: newSchedule.fetchState,
|
|
104
|
+
error: newSchedule.error,
|
|
105
|
+
};
|
|
106
|
+
};
|