@zeniai/client-epic-state 5.1.82 → 5.1.83-betaRD2
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/jeSchedules/jeScheduleHelper.d.ts +2 -0
- package/lib/entity/jeSchedules/jeScheduleHelper.js +7 -0
- package/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +34 -1
- package/lib/entity/jeSchedules/jeSchedulesPayload.js +68 -0
- package/lib/entity/jeSchedules/jeSchedulesReducer.d.ts +4 -2
- package/lib/entity/jeSchedules/jeSchedulesReducer.js +26 -2
- package/lib/entity/jeSchedules/jeSchedulesSelector.d.ts +10 -2
- package/lib/entity/jeSchedules/jeSchedulesSelector.js +28 -3
- package/lib/entity/jeSchedules/jeSchedulesState.d.ts +41 -1
- package/lib/entity/jeSchedules/jeSchedulesTypes.d.ts +12 -1
- package/lib/entity/jeSchedules/jeSchedulesTypes.js +40 -1
- package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.js +29 -0
- package/lib/entity/tenant/clearAllEpic.d.ts +2 -2
- package/lib/entity/tenant/clearAllEpic.js +1 -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 +5 -1
- package/lib/epic.js +5 -1
- package/lib/esm/entity/jeSchedules/jeScheduleHelper.js +6 -0
- package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +68 -1
- package/lib/esm/entity/jeSchedules/jeSchedulesReducer.js +26 -2
- package/lib/esm/entity/jeSchedules/jeSchedulesSelector.js +26 -2
- package/lib/esm/entity/jeSchedules/jeSchedulesTypes.js +34 -0
- package/lib/esm/entity/snackbar/snackbarTypes.js +29 -0
- package/lib/esm/entity/tenant/clearAllEpic.js +2 -1
- package/lib/esm/entity/transaction/payloadTypes/scheduleTransactionPayload.js +2 -0
- package/lib/esm/epic.js +5 -1
- package/lib/esm/index.js +11 -5
- package/lib/esm/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +6 -3
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +34 -3
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.js +21 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.js +110 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.js +73 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +22 -0
- package/lib/esm/view/expenseAutomationView/helpers/newScheduleLocalDataHelper.js +140 -0
- package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +163 -28
- package/lib/esm/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.js +1 -0
- package/lib/esm/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.js +70 -0
- package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +260 -22
- package/lib/esm/view/expenseAutomationView/types/jeSchedulesViewState.js +5 -6
- package/lib/esm/view/invoicing/createCreditNote/createCreditNoteEpic.js +24 -4
- package/lib/esm/view/invoicing/createInvoice/createInvoiceEpic.js +24 -4
- package/lib/esm/view/invoicing/createInvoice/createInvoiceSelector.js +37 -10
- package/lib/esm/view/invoicing/discountAction/discountActionEpic.js +33 -9
- package/lib/esm/view/invoicing/dunningAction/dunningActionEpic.js +35 -9
- package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/catalogDetailEditPayload.js +5 -1
- package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +32 -5
- package/lib/esm/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +23 -3
- package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +24 -4
- package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +24 -4
- package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/syncInvoicingSubscriptionCouponsEpic.js +20 -3
- package/lib/esm/view/invoicing/invoiceAction/invoiceActionEpic.js +60 -17
- package/lib/esm/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +30 -0
- package/lib/esm/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.js +4 -29
- package/lib/esm/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +29 -10
- package/lib/esm/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +28 -5
- package/lib/esm/view/invoicing/issueCreditNote/issueCreditNoteEpic.js +24 -4
- package/lib/esm/view/invoicing/issueCreditNote/issueCreditNoteSelector.js +22 -14
- package/lib/esm/view/invoicing/recordPayment/recordPaymentEpic.js +46 -7
- package/lib/esm/view/invoicing/settingsView/settingsViewEpics.js +26 -8
- package/lib/esm/view/invoicing/settingsView/settingsViewReducer.js +1 -1
- package/lib/esm/view/invoicing/settingsView/settingsViewSelector.js +4 -1
- package/lib/esm/view/invoicing/subscriptionAction/subscriptionActionEpic.js +41 -9
- package/lib/index.d.ts +18 -13
- package/lib/index.js +72 -50
- package/lib/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +6 -3
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.d.ts +2 -2
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +32 -1
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.d.ts +8 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.js +25 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.d.ts +45 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.js +114 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.d.ts +8 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.js +77 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.d.ts +6 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +26 -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/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/expenseAutomationView/payload/jeSchedulesPayload.d.ts +8 -1
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +45 -10
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +164 -28
- package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +1 -1
- package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +2 -2
- package/lib/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.d.ts +25 -0
- package/lib/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.js +2 -0
- package/lib/view/expenseAutomationView/selectorTypes/jeSchedulesSelectorTypes.d.ts +34 -8
- package/lib/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.d.ts +10 -0
- package/lib/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.js +75 -0
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.d.ts +10 -1
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +266 -21
- package/lib/view/expenseAutomationView/types/completedSubTab.d.ts +1 -1
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +59 -8
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.js +8 -8
- package/lib/view/invoicing/createCreditNote/createCreditNoteEpic.d.ts +2 -1
- package/lib/view/invoicing/createCreditNote/createCreditNoteEpic.js +23 -3
- package/lib/view/invoicing/createInvoice/createInvoiceEpic.d.ts +2 -1
- package/lib/view/invoicing/createInvoice/createInvoiceEpic.js +23 -3
- package/lib/view/invoicing/createInvoice/createInvoiceSelector.d.ts +22 -8
- package/lib/view/invoicing/createInvoice/createInvoiceSelector.js +37 -10
- package/lib/view/invoicing/discountAction/discountActionEpic.d.ts +2 -1
- package/lib/view/invoicing/discountAction/discountActionEpic.js +32 -8
- package/lib/view/invoicing/dunningAction/dunningActionEpic.d.ts +2 -1
- package/lib/view/invoicing/dunningAction/dunningActionEpic.js +34 -8
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/catalogDetailEditPayload.d.ts +3 -1
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/catalogDetailEditPayload.js +5 -1
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.d.ts +2 -1
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +31 -4
- package/lib/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.d.ts +2 -1
- package/lib/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +22 -2
- package/lib/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.d.ts +2 -1
- package/lib/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +23 -3
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.d.ts +2 -1
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +23 -3
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/syncInvoicingSubscriptionCouponsEpic.d.ts +2 -1
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/syncInvoicingSubscriptionCouponsEpic.js +19 -2
- package/lib/view/invoicing/invoiceAction/invoiceActionEpic.d.ts +2 -1
- package/lib/view/invoicing/invoiceAction/invoiceActionEpic.js +59 -16
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewPayload.d.ts +13 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +30 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.d.ts +11 -31
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.js +4 -29
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewState.d.ts +15 -0
- package/lib/view/invoicing/invoicingQboView/epics/invoicingQboViewActionType.d.ts +2 -1
- package/lib/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +28 -9
- package/lib/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +27 -4
- package/lib/view/invoicing/issueCreditNote/issueCreditNoteEpic.d.ts +2 -1
- package/lib/view/invoicing/issueCreditNote/issueCreditNoteEpic.js +23 -3
- package/lib/view/invoicing/issueCreditNote/issueCreditNoteSelector.d.ts +24 -7
- package/lib/view/invoicing/issueCreditNote/issueCreditNoteSelector.js +23 -16
- package/lib/view/invoicing/recordPayment/recordPaymentEpic.d.ts +2 -1
- package/lib/view/invoicing/recordPayment/recordPaymentEpic.js +45 -6
- package/lib/view/invoicing/settingsView/settingsViewEpics.d.ts +2 -1
- package/lib/view/invoicing/settingsView/settingsViewEpics.js +25 -7
- package/lib/view/invoicing/settingsView/settingsViewReducer.d.ts +10 -1
- package/lib/view/invoicing/settingsView/settingsViewReducer.js +1 -1
- package/lib/view/invoicing/settingsView/settingsViewSelector.d.ts +4 -2
- package/lib/view/invoicing/settingsView/settingsViewSelector.js +4 -1
- package/lib/view/invoicing/subscriptionAction/subscriptionActionEpic.d.ts +2 -1
- package/lib/view/invoicing/subscriptionAction/subscriptionActionEpic.js +40 -8
- package/package.json +1 -1
package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { from } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
+
import { updateJESchedules, updateJESchedulesDetails, } from '../../../../../entity/jeSchedules/jeSchedulesReducer';
|
|
4
|
+
import { getJEScheduleTransactionKey } from '../../../../../entity/jeSchedules/jeSchedulesTypes';
|
|
5
|
+
import { openSnackbar } from '../../../../../entity/snackbar/snackbarReducer';
|
|
6
|
+
import { getScheduleTransactionById } from '../../../../../entity/transaction/transactionSelector';
|
|
7
|
+
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
|
|
8
|
+
import { prepareNewSchedulePayload, } from '../../../helpers/newScheduleLocalDataHelper';
|
|
9
|
+
import { resetNewScheduleLocalData, saveNewSchedule, saveNewScheduleFailure, saveNewScheduleSuccess, } from '../../../reducers/jeSchedulesViewReducer';
|
|
10
|
+
const FAILURE_REASON_MESSAGES = {
|
|
11
|
+
missing_third_party_id: 'This transaction is missing a QuickBooks reference and cannot be scheduled.',
|
|
12
|
+
missing_vendor: 'Select a vendor before saving this schedule.',
|
|
13
|
+
};
|
|
14
|
+
export const saveNewScheduleEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(saveNewSchedule.match), mergeMap((action) => {
|
|
15
|
+
const { scheduleType } = action.payload;
|
|
16
|
+
const state = state$.value;
|
|
17
|
+
const localData = state.expenseAutomationJESchedulesViewState.newSchedule
|
|
18
|
+
.newScheduleState[scheduleType];
|
|
19
|
+
const { selectedBaseTransactionId } = localData;
|
|
20
|
+
const transaction = selectedBaseTransactionId != null
|
|
21
|
+
? getScheduleTransactionById(state.transactionState, getJEScheduleTransactionKey(selectedBaseTransactionId))
|
|
22
|
+
: undefined;
|
|
23
|
+
if (transaction == null) {
|
|
24
|
+
return from([
|
|
25
|
+
saveNewScheduleFailure({
|
|
26
|
+
status: createZeniAPIStatus('Unexpected Error', 'No base transaction selected for this schedule.'),
|
|
27
|
+
}),
|
|
28
|
+
openSnackbar({
|
|
29
|
+
messageSection: 'create_schedule',
|
|
30
|
+
messageText: 'failed',
|
|
31
|
+
type: 'error',
|
|
32
|
+
variables: [
|
|
33
|
+
{
|
|
34
|
+
variableName: '_api-error_',
|
|
35
|
+
variableValue: 'No base transaction selected.',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
}),
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
const result = prepareNewSchedulePayload(transaction, localData, scheduleType);
|
|
42
|
+
if (!result.ok) {
|
|
43
|
+
const message = FAILURE_REASON_MESSAGES[result.reason];
|
|
44
|
+
return from([
|
|
45
|
+
saveNewScheduleFailure({
|
|
46
|
+
status: createZeniAPIStatus('Unexpected Error', message),
|
|
47
|
+
}),
|
|
48
|
+
openSnackbar({
|
|
49
|
+
messageSection: 'create_schedule',
|
|
50
|
+
messageText: 'failed',
|
|
51
|
+
type: 'error',
|
|
52
|
+
variables: [{ variableName: '_api-error_', variableValue: message }],
|
|
53
|
+
}),
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
const vendorName = localData.selectedVendor?.name ?? transaction.vendorName ?? '';
|
|
57
|
+
const queryParam = {
|
|
58
|
+
je_schedule_type: scheduleType,
|
|
59
|
+
};
|
|
60
|
+
const payload = { ...result.payload };
|
|
61
|
+
return zeniAPI
|
|
62
|
+
.postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/schedules?query=${encodeURIComponent(JSON.stringify(queryParam))}`, payload)
|
|
63
|
+
.pipe(mergeMap((response) => {
|
|
64
|
+
if (isSuccessResponse(response) && response.data != null) {
|
|
65
|
+
return from([
|
|
66
|
+
updateJESchedules(response.data.je_schedules),
|
|
67
|
+
updateJESchedulesDetails(response.data.je_schedules, response.data.scheduled_journal_entries),
|
|
68
|
+
resetNewScheduleLocalData({ scheduleType }),
|
|
69
|
+
saveNewScheduleSuccess(),
|
|
70
|
+
openSnackbar({
|
|
71
|
+
messageSection: 'create_schedule',
|
|
72
|
+
messageText: 'success',
|
|
73
|
+
type: 'success',
|
|
74
|
+
variables: [
|
|
75
|
+
{ variableName: '_vendor_name_', variableValue: vendorName },
|
|
76
|
+
],
|
|
77
|
+
}),
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
return from([
|
|
81
|
+
saveNewScheduleFailure({ status: response.status }),
|
|
82
|
+
openSnackbar({
|
|
83
|
+
messageSection: 'create_schedule',
|
|
84
|
+
messageText: 'failed',
|
|
85
|
+
type: 'error',
|
|
86
|
+
variables: [
|
|
87
|
+
{
|
|
88
|
+
variableName: '_api-error_',
|
|
89
|
+
variableValue: response.status.message,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
}),
|
|
93
|
+
]);
|
|
94
|
+
}), catchError((error) => from([
|
|
95
|
+
openSnackbar({
|
|
96
|
+
messageSection: 'create_schedule',
|
|
97
|
+
messageText: 'failed',
|
|
98
|
+
type: 'error',
|
|
99
|
+
variables: [
|
|
100
|
+
{
|
|
101
|
+
variableName: '_api-error_',
|
|
102
|
+
variableValue: JSON.stringify(error),
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
}),
|
|
106
|
+
saveNewScheduleFailure({
|
|
107
|
+
status: createZeniAPIStatus('Unexpected Error', `Save New Schedule REST API call errored out ${JSON.stringify(error)}`),
|
|
108
|
+
}),
|
|
109
|
+
])));
|
|
110
|
+
}));
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { EMPTY, from, merge, of } from 'rxjs';
|
|
2
|
+
import { catchError, debounceTime, filter, mergeMap, switchMap, } from 'rxjs/operators';
|
|
3
|
+
import { getJEScheduleTransactionKey } from '../../../../../entity/jeSchedules/jeSchedulesTypes';
|
|
4
|
+
import { toTransactionType } from '../../../../../entity/transaction/stateTypes/transactionType';
|
|
5
|
+
import { updateScheduleTransactions } from '../../../../../entity/transaction/transactionReducer';
|
|
6
|
+
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
|
|
7
|
+
import { searchTransactionsForNewSchedule, searchTransactionsForNewScheduleFailure, searchTransactionsForNewScheduleSuccess, } from '../../../reducers/jeSchedulesViewReducer';
|
|
8
|
+
import { MIN_NEW_SCHEDULE_SEARCH_LENGTH } from '../../../types/jeSchedulesViewState';
|
|
9
|
+
/** Dropdown-sized result set — no pagination for Base Transaction search. */
|
|
10
|
+
const NEW_SCHEDULE_SEARCH_PAGE_SIZE = 10;
|
|
11
|
+
/** Fallback when the backend sends a null currency for a search result. */
|
|
12
|
+
const DEFAULT_CURRENCY_CODE = 'USD';
|
|
13
|
+
const DEFAULT_CURRENCY_SYMBOL = '$';
|
|
14
|
+
export const searchTransactionsForNewScheduleEpic = (actions$, _state$, zeniAPI) => {
|
|
15
|
+
const searchActions$ = actions$.pipe(filter(searchTransactionsForNewSchedule.match));
|
|
16
|
+
/** No API for empty or 1-char queries; immediate merge so switchMap cancels any in-flight HTTP. */
|
|
17
|
+
const newSearchTooShortOrClear$ = searchActions$.pipe(filter((action) => action.payload.query.trim().length < MIN_NEW_SCHEDULE_SEARCH_LENGTH));
|
|
18
|
+
const newSearchDebounced$ = searchActions$.pipe(filter((action) => action.payload.query.trim().length >= MIN_NEW_SCHEDULE_SEARCH_LENGTH), debounceTime(300));
|
|
19
|
+
return merge(newSearchTooShortOrClear$, newSearchDebounced$).pipe(switchMap((action) => {
|
|
20
|
+
const query = action.payload.query.trim();
|
|
21
|
+
if (query.length < MIN_NEW_SCHEDULE_SEARCH_LENGTH) {
|
|
22
|
+
return EMPTY;
|
|
23
|
+
}
|
|
24
|
+
const queryParam = {
|
|
25
|
+
page_size: NEW_SCHEDULE_SEARCH_PAGE_SIZE,
|
|
26
|
+
search_text: query,
|
|
27
|
+
je_schedule_type: action.payload.scheduleType,
|
|
28
|
+
};
|
|
29
|
+
return zeniAPI
|
|
30
|
+
.getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/schedules/base_transaction_search?query=${encodeURIComponent(JSON.stringify(queryParam))}`)
|
|
31
|
+
.pipe(mergeMap((response) => {
|
|
32
|
+
if (isSuccessResponse(response) && response.data != null) {
|
|
33
|
+
const { transactions } = response.data;
|
|
34
|
+
const transactionsPerCurrency = {};
|
|
35
|
+
transactions.forEach((transaction) => {
|
|
36
|
+
const { currency_code, currency_symbol } = transaction;
|
|
37
|
+
const currencyCode = currency_code ?? DEFAULT_CURRENCY_CODE;
|
|
38
|
+
const existing = transactionsPerCurrency[currencyCode];
|
|
39
|
+
transactionsPerCurrency[currencyCode] =
|
|
40
|
+
existing != null
|
|
41
|
+
? {
|
|
42
|
+
currencySymbol: existing.currencySymbol,
|
|
43
|
+
transactions: [...existing.transactions, transaction],
|
|
44
|
+
}
|
|
45
|
+
: {
|
|
46
|
+
currencySymbol: currency_code == null
|
|
47
|
+
? DEFAULT_CURRENCY_SYMBOL
|
|
48
|
+
: currency_symbol,
|
|
49
|
+
transactions: [transaction],
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
const actionsOut = Object.keys(transactionsPerCurrency).map((currencyCode) => {
|
|
53
|
+
const perCurrency = transactionsPerCurrency[currencyCode];
|
|
54
|
+
return updateScheduleTransactions(perCurrency.transactions, currencyCode, perCurrency.currencySymbol, 'merge');
|
|
55
|
+
});
|
|
56
|
+
actionsOut.push(searchTransactionsForNewScheduleSuccess({
|
|
57
|
+
searchResults: transactions.map((transaction) => getJEScheduleTransactionKey({
|
|
58
|
+
id: transaction.transaction_id,
|
|
59
|
+
type: toTransactionType(transaction.transaction_type),
|
|
60
|
+
lineId: transaction.line_id,
|
|
61
|
+
})),
|
|
62
|
+
}));
|
|
63
|
+
return from(actionsOut);
|
|
64
|
+
}
|
|
65
|
+
return of(searchTransactionsForNewScheduleFailure({
|
|
66
|
+
status: response.status,
|
|
67
|
+
}));
|
|
68
|
+
}), catchError((error) => of(searchTransactionsForNewScheduleFailure({
|
|
69
|
+
status: createZeniAPIStatus('Unexpected Error', 'Search transactions for new schedule errored: ' +
|
|
70
|
+
JSON.stringify(error)),
|
|
71
|
+
}))));
|
|
72
|
+
}));
|
|
73
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EMPTY, of } from 'rxjs';
|
|
2
|
+
import { filter, mergeMap } from 'rxjs/operators';
|
|
3
|
+
import { convertToPeriod, toAbsoluteDay, } from '../../../../commonStateTypes/timePeriod';
|
|
4
|
+
import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
|
|
5
|
+
import { fetchJeSchedulesPage, updateJESchedulesUIState, } from '../../reducers/jeSchedulesViewReducer';
|
|
6
|
+
export const switchJESchedulesTabEpic = (actions$, state$) => actions$.pipe(filter(updateJESchedulesUIState.match), filter((action) => action.payload.selectedPageTab != null), mergeMap(() => {
|
|
7
|
+
const state = state$.value;
|
|
8
|
+
const { fetchState, refreshStatus } = state.expenseAutomationJESchedulesViewState;
|
|
9
|
+
if (fetchState === 'In-Progress' ||
|
|
10
|
+
refreshStatus.fetchState === 'In-Progress') {
|
|
11
|
+
return EMPTY;
|
|
12
|
+
}
|
|
13
|
+
const currentTenant = getCurrentTenant(state);
|
|
14
|
+
const selectedPeriod = state.expenseAutomationViewState.selectedPeriodByTenantId[currentTenant.tenantId];
|
|
15
|
+
const period = convertToPeriod(selectedPeriod);
|
|
16
|
+
const timePeriodStart = toAbsoluteDay(period.start);
|
|
17
|
+
const timePeriodEnd = toAbsoluteDay(period.end);
|
|
18
|
+
if (timePeriodStart == null || timePeriodEnd == null) {
|
|
19
|
+
return EMPTY;
|
|
20
|
+
}
|
|
21
|
+
return of(fetchJeSchedulesPage({ start: timePeriodStart, end: timePeriodEnd }, true));
|
|
22
|
+
}));
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { toAmount } from '../../../commonStateTypes/amount';
|
|
2
|
+
import { DEFAULT_DATE_FORMAT } from '../../../commonStateTypes/fiscalYearHelpers/formatZeniDateFY';
|
|
3
|
+
import { MONTH_YEAR_FORMAT } from '../../../commonStateTypes/fiscalYearHelpers/formatZeniDateFY';
|
|
4
|
+
import { LAST_SCHEDULE_DAY_OF_MONTH } from '../../../commonStateTypes/timePeriod';
|
|
5
|
+
import { getPostingDateAndStatusForIndex } from '../../scheduleView/scheduleDetailView/scheduleDetailLocalDataHelper';
|
|
6
|
+
import { mapScheduleTransactionToBaseScheduleTransactionPayload, } from '../../scheduleView/scheduleDetailView/scheduleDetailPayload';
|
|
7
|
+
const getNewScheduleMemo = (vendorName, schedulePostingDate, currentPeriod, totalPeriod, assetId) => {
|
|
8
|
+
const addAsset = assetId != null && assetId !== '' ? ` - ${assetId}` : '';
|
|
9
|
+
return `${vendorName} - ${schedulePostingDate.format(MONTH_YEAR_FORMAT)} (${currentPeriod} of ${totalPeriod})${addAsset}`;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Computes the month-by-month JE schedule breakdown for a brand-new schedule
|
|
13
|
+
* (no linked transaction yet) — replicates createNewSchedulesHelper's math
|
|
14
|
+
* (scheduleDetailLocalDataHelper.ts) exactly: lump-sum total split evenly
|
|
15
|
+
* across months with the rounding remainder absorbed by the last month, and a
|
|
16
|
+
* running balance that decrements each month and is forced to exactly 0 on
|
|
17
|
+
* the last row.
|
|
18
|
+
*/
|
|
19
|
+
export const computeNewScheduleJeDetails = (localData, totalAmount, vendorName) => {
|
|
20
|
+
const period = localData.selectedMonths;
|
|
21
|
+
const startingMonth = localData.selectedDate;
|
|
22
|
+
if (startingMonth == null || period == null) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
const assetId = 'assetId' in localData ? localData.assetId : undefined;
|
|
26
|
+
const averageAmount = Math.abs(Math.round((totalAmount.amount / period) * 100) / 100);
|
|
27
|
+
const lastMonthAmount = Math.abs(Math.round((Math.abs(totalAmount.amount) - averageAmount * (period - 1)) * 100) / 100);
|
|
28
|
+
let runningBalance = Math.abs(totalAmount.amount);
|
|
29
|
+
const negativeNumbers = totalAmount.amount < 0 || runningBalance < 0;
|
|
30
|
+
const newJeDetails = [];
|
|
31
|
+
for (let index = 0; index < period; index++) {
|
|
32
|
+
if (runningBalance > averageAmount) {
|
|
33
|
+
runningBalance = Math.round((runningBalance - averageAmount) * 100) / 100;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
runningBalance = 0;
|
|
37
|
+
}
|
|
38
|
+
const amount = index === period - 1 ? lastMonthAmount : averageAmount;
|
|
39
|
+
runningBalance = index === period - 1 ? 0 : runningBalance;
|
|
40
|
+
const schedulePostingDate = startingMonth.add(index, 'month');
|
|
41
|
+
const { postingDate, postingStatus } = getPostingDateAndStatusForIndex(schedulePostingDate.month(), schedulePostingDate.year(), localData.lastDayOfMonth === true
|
|
42
|
+
? undefined
|
|
43
|
+
: localData.selectedDayOfMonth);
|
|
44
|
+
newJeDetails.push({
|
|
45
|
+
postingDate,
|
|
46
|
+
amount: toAmount(negativeNumbers ? -amount : amount, totalAmount.currencyCode, totalAmount.currencySymbol),
|
|
47
|
+
runningBalance: toAmount(negativeNumbers ? -runningBalance : runningBalance, totalAmount.currencyCode, totalAmount.currencySymbol),
|
|
48
|
+
postingStatus,
|
|
49
|
+
memo: getNewScheduleMemo(vendorName, schedulePostingDate, index + 1, period, assetId),
|
|
50
|
+
jeLink: { type: 'unknown' },
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return newJeDetails;
|
|
54
|
+
};
|
|
55
|
+
const mapNewJeDetailsToScheduledJournalEntryPayload = (jeScheduleDetails) => jeScheduleDetails.map((journalEntry) => ({
|
|
56
|
+
status: {
|
|
57
|
+
code: journalEntry.postingStatus,
|
|
58
|
+
label: journalEntry.postingStatus,
|
|
59
|
+
},
|
|
60
|
+
transaction_memo: journalEntry.memo,
|
|
61
|
+
third_party_id: journalEntry.jeLink.thirdPartyTransactionId ?? null,
|
|
62
|
+
expected_post_date: journalEntry.postingDate.format(DEFAULT_DATE_FORMAT),
|
|
63
|
+
amount: journalEntry.amount.amount,
|
|
64
|
+
balance: journalEntry.runningBalance.amount,
|
|
65
|
+
// Brand-new schedule — there is no prior scheduled-journal-entry history
|
|
66
|
+
// to cross-reference (unlike the legacy edit flow's equivalent mapper).
|
|
67
|
+
scheduled_journal_entry_id: null,
|
|
68
|
+
actual_post_date: null,
|
|
69
|
+
is_platform_generated: null,
|
|
70
|
+
je_schedule_id: null,
|
|
71
|
+
update_time: null,
|
|
72
|
+
create_time: null,
|
|
73
|
+
}));
|
|
74
|
+
/**
|
|
75
|
+
* Builds a savable schedule payload directly from a Base Transaction search
|
|
76
|
+
* result and the New Schedule form's local data — bypassing the legacy
|
|
77
|
+
* getJEScheduledTransactionByJEScheduleTransactionKey selector entirely,
|
|
78
|
+
* since that selector throws unless the entity has already round-tripped
|
|
79
|
+
* through a real GET /1.0/schedules/:id. A brand-new schedule has no such
|
|
80
|
+
* history, so this reads only from data already in hand (the selected
|
|
81
|
+
* transaction/line plus what the user filled into the form).
|
|
82
|
+
*/
|
|
83
|
+
export const prepareNewSchedulePayload = (transaction, localData, scheduleType) => {
|
|
84
|
+
if (transaction.thirdPartyTransactionId == null ||
|
|
85
|
+
transaction.thirdPartyTransactionId === '') {
|
|
86
|
+
return { ok: false, reason: 'missing_third_party_id' };
|
|
87
|
+
}
|
|
88
|
+
const scheduleTransaction = transaction;
|
|
89
|
+
const vendorId = localData.selectedVendor?.id ?? transaction.vendorId ?? '';
|
|
90
|
+
const vendorName = localData.selectedVendor?.name ?? transaction.vendorName ?? '';
|
|
91
|
+
if (vendorId === '' || vendorName === '') {
|
|
92
|
+
return { ok: false, reason: 'missing_vendor' };
|
|
93
|
+
}
|
|
94
|
+
const vendor = {
|
|
95
|
+
vendor_id: vendorId,
|
|
96
|
+
vendor_name: vendorName,
|
|
97
|
+
};
|
|
98
|
+
const jeScheduleDetails = computeNewScheduleJeDetails(localData, scheduleTransaction.amount, vendorName);
|
|
99
|
+
const postingDate = localData.selectedDayOfMonth ??
|
|
100
|
+
(localData.lastDayOfMonth === true ? LAST_SCHEDULE_DAY_OF_MONTH : null);
|
|
101
|
+
const firstJEScheduleDate = jeScheduleDetails.length > 0
|
|
102
|
+
? jeScheduleDetails[0].postingDate.format(DEFAULT_DATE_FORMAT)
|
|
103
|
+
: null;
|
|
104
|
+
const lastJEScheduleDate = jeScheduleDetails.length > 0
|
|
105
|
+
? jeScheduleDetails[jeScheduleDetails.length - 1].postingDate.format(DEFAULT_DATE_FORMAT)
|
|
106
|
+
: null;
|
|
107
|
+
const isFixedAssets = scheduleType === 'fixed_assets';
|
|
108
|
+
const assetId = 'assetId' in localData ? localData.assetId : undefined;
|
|
109
|
+
const selectedAccumulatedDepreciationCategory = 'selectedAccumulatedDepreciationCategory' in localData
|
|
110
|
+
? localData.selectedAccumulatedDepreciationCategory
|
|
111
|
+
: undefined;
|
|
112
|
+
const status = { code: 'new', label: 'New' };
|
|
113
|
+
const jeSchedulePayload = {
|
|
114
|
+
status,
|
|
115
|
+
vendor,
|
|
116
|
+
currency_code: scheduleTransaction.currency.currencyCode,
|
|
117
|
+
currency_symbol: scheduleTransaction.currency.currencySymbol,
|
|
118
|
+
period: localData.selectedMonths ?? null,
|
|
119
|
+
je_schedule_type: scheduleType,
|
|
120
|
+
posting_date: postingDate,
|
|
121
|
+
balance: scheduleTransaction.amount.amount,
|
|
122
|
+
start_date: firstJEScheduleDate,
|
|
123
|
+
end_date: lastJEScheduleDate,
|
|
124
|
+
je_credit_accounting_class_id: scheduleTransaction.classBase?.classId ?? null,
|
|
125
|
+
je_credit_account_id: isFixedAssets
|
|
126
|
+
? (selectedAccumulatedDepreciationCategory ?? null)
|
|
127
|
+
: scheduleTransaction.account.accountId,
|
|
128
|
+
je_debit_account_id: localData.selectedAccount ?? null,
|
|
129
|
+
je_debit_accounting_class_id: localData.selectedClass ?? null,
|
|
130
|
+
other_attributes: assetId != null ? { asset_id: assetId } : {},
|
|
131
|
+
base_transaction: mapScheduleTransactionToBaseScheduleTransactionPayload(scheduleTransaction),
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
ok: true,
|
|
135
|
+
payload: {
|
|
136
|
+
je_schedules: [jeSchedulePayload],
|
|
137
|
+
scheduled_journal_entries: mapNewJeDetailsToScheduledJournalEntryPayload(jeScheduleDetails),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
};
|
|
@@ -2,8 +2,15 @@ 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 { mapAccountTypeRecommendationPayloadToAccountRecommendationByType, } from '../../accountMappingView/accountTypeRecommendation/accountTypeRecommendationPayload';
|
|
8
|
+
import { MIN_NEW_SCHEDULE_SEARCH_LENGTH, getJESchedulePeriodTabKey, } from '../types/jeSchedulesViewState';
|
|
9
|
+
function removeKeyFromEveryTabSlot(keysByPeriodAndTab, keyToRemove) {
|
|
10
|
+
for (const periodTabKey of Object.keys(keysByPeriodAndTab)) {
|
|
11
|
+
keysByPeriodAndTab[periodTabKey] = keysByPeriodAndTab[periodTabKey].filter((jeScheduleKey) => jeScheduleKey !== keyToRemove);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
7
14
|
export const accountSettingsInitialState = {
|
|
8
15
|
localData: {
|
|
9
16
|
selectedPrepaidExpensesAccountIds: [],
|
|
@@ -35,16 +42,34 @@ export const accountSettingsInitialState = {
|
|
|
35
42
|
accruedExpensesNestedAccountListHierarchy: [],
|
|
36
43
|
accruedExpensesRecommendations: [],
|
|
37
44
|
};
|
|
45
|
+
export const getBaseNewScheduleLocalData = (scheduleType) => ({
|
|
46
|
+
scheduleType,
|
|
47
|
+
jeScheduleDetails: [],
|
|
48
|
+
});
|
|
49
|
+
export const newScheduleInitialState = {
|
|
50
|
+
fixed_assets: getBaseNewScheduleLocalData('fixed_assets'),
|
|
51
|
+
prepaid_expenses: getBaseNewScheduleLocalData('prepaid_expenses'),
|
|
52
|
+
};
|
|
53
|
+
export const searchTransactionsInitialState = {
|
|
54
|
+
searchResults: [],
|
|
55
|
+
fetchState: 'Not-Started',
|
|
56
|
+
error: undefined,
|
|
57
|
+
};
|
|
38
58
|
export const initialState = {
|
|
39
|
-
|
|
40
|
-
|
|
59
|
+
jeScheduleTransactionKeysByPeriodAndTab: {},
|
|
60
|
+
jeScheduleAccruedKeysByPeriodAndTab: {},
|
|
61
|
+
jeScheduleOneTimeAccrualKeysByPeriodAndTab: {},
|
|
62
|
+
failedJeScheduleTransactionKeysByPeriodAndTab: {},
|
|
41
63
|
postStatusById: {},
|
|
42
64
|
ignoreStatusById: {},
|
|
43
65
|
jeScheduleLocalDataById: {},
|
|
44
66
|
uiState: {
|
|
45
|
-
|
|
67
|
+
createdGroupCollapsed: false,
|
|
68
|
+
pendingGroupCollapsed: false,
|
|
46
69
|
scrollPosition: { scrollTop: 0, scrollLeft: undefined },
|
|
47
|
-
|
|
70
|
+
searchString: '',
|
|
71
|
+
selectedJETypeFilter: null,
|
|
72
|
+
selectedPageTab: 'schedules',
|
|
48
73
|
sortKey: 'transactionDate',
|
|
49
74
|
sortOrder: 'descending',
|
|
50
75
|
totalCount: 0,
|
|
@@ -55,6 +80,13 @@ export const initialState = {
|
|
|
55
80
|
error: undefined,
|
|
56
81
|
},
|
|
57
82
|
accountSettings: accountSettingsInitialState,
|
|
83
|
+
newSchedule: {
|
|
84
|
+
newScheduleState: newScheduleInitialState,
|
|
85
|
+
saveStatus: { fetchState: 'Not-Started', error: undefined },
|
|
86
|
+
searchTransactions: searchTransactionsInitialState,
|
|
87
|
+
fetchState: 'Not-Started',
|
|
88
|
+
error: undefined,
|
|
89
|
+
},
|
|
58
90
|
fetchState: 'Not-Started',
|
|
59
91
|
error: undefined,
|
|
60
92
|
hasValidState() {
|
|
@@ -99,9 +131,12 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
99
131
|
},
|
|
100
132
|
},
|
|
101
133
|
fetchJeSchedulesSuccess(draft, action) {
|
|
102
|
-
const { jeSchedules, selectedPeriod, failedJeSchedules, refreshViewInBackground, } = action.payload;
|
|
134
|
+
const { jeSchedules, selectedPeriod, selectedPageTab, failedJeSchedules, accruedJeSchedules, oneTimeAccruals, refreshViewInBackground, } = action.payload;
|
|
135
|
+
const periodTabKey = getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod));
|
|
103
136
|
const jeScheduleTransactionKeys = jeSchedules.map((schedules) => getJEScheduleTransactionDetailKeyPayload(schedules.base_transaction));
|
|
104
137
|
const failedJeScheduleTransactionKeys = failedJeSchedules.map((schedules) => getJEScheduleTransactionDetailKeyPayload(schedules.base_transaction));
|
|
138
|
+
const jeScheduleAccruedKeys = accruedJeSchedules.map((schedule) => getJEScheduleKey(schedule));
|
|
139
|
+
const jeScheduleOneTimeAccrualKeys = oneTimeAccruals.map((accrual) => generateJEOneTimeAccrualKey(accrual._id));
|
|
105
140
|
if (refreshViewInBackground === true &&
|
|
106
141
|
draft.refreshStatus.fetchState === 'In-Progress') {
|
|
107
142
|
draft.refreshStatus = { fetchState: 'Completed', error: undefined };
|
|
@@ -110,19 +145,28 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
110
145
|
draft.fetchState = 'Completed';
|
|
111
146
|
draft.error = undefined;
|
|
112
147
|
}
|
|
113
|
-
draft.
|
|
114
|
-
|
|
148
|
+
draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
|
|
149
|
+
jeScheduleTransactionKeys;
|
|
150
|
+
draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] =
|
|
151
|
+
jeScheduleAccruedKeys;
|
|
152
|
+
draft.jeScheduleOneTimeAccrualKeysByPeriodAndTab[periodTabKey] =
|
|
153
|
+
jeScheduleOneTimeAccrualKeys;
|
|
154
|
+
draft.failedJeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
|
|
155
|
+
failedJeScheduleTransactionKeys;
|
|
115
156
|
},
|
|
116
157
|
fetchJeSchedulesFailure(draft, action) {
|
|
117
|
-
const { status, selectedPeriod } = action.payload;
|
|
158
|
+
const { status, selectedPeriod, selectedPageTab } = action.payload;
|
|
159
|
+
const periodTabKey = getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod));
|
|
118
160
|
if (draft.refreshStatus.fetchState === 'In-Progress') {
|
|
119
161
|
draft.refreshStatus = { fetchState: 'Error', error: status };
|
|
120
162
|
}
|
|
121
163
|
else {
|
|
122
164
|
draft.fetchState = 'Error';
|
|
123
165
|
draft.error = status;
|
|
166
|
+
draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] = [];
|
|
167
|
+
draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] = [];
|
|
168
|
+
draft.jeScheduleOneTimeAccrualKeysByPeriodAndTab[periodTabKey] = [];
|
|
124
169
|
}
|
|
125
|
-
draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = [];
|
|
126
170
|
},
|
|
127
171
|
retryJeSchedule(draft, action) {
|
|
128
172
|
const { scheduledJournalEntryID } = action.payload;
|
|
@@ -210,17 +254,18 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
210
254
|
};
|
|
211
255
|
},
|
|
212
256
|
updateJeScheduleTransactionKeys: {
|
|
213
|
-
prepare(jeScheduleKeys, selectedPeriod) {
|
|
257
|
+
prepare(jeScheduleKeys, selectedPeriod, selectedPageTab) {
|
|
214
258
|
return {
|
|
215
259
|
payload: {
|
|
216
260
|
jeScheduleKeys: jeScheduleKeys,
|
|
217
261
|
selectedPeriod: selectedPeriod,
|
|
262
|
+
selectedPageTab: selectedPageTab,
|
|
218
263
|
},
|
|
219
264
|
};
|
|
220
265
|
},
|
|
221
266
|
reducer(draft, action) {
|
|
222
|
-
const { selectedPeriod, jeScheduleKeys } = action.payload;
|
|
223
|
-
draft.
|
|
267
|
+
const { selectedPeriod, selectedPageTab, jeScheduleKeys } = action.payload;
|
|
268
|
+
draft.jeScheduleTransactionKeysByPeriodAndTab[getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod))] = jeScheduleKeys;
|
|
224
269
|
},
|
|
225
270
|
},
|
|
226
271
|
removeJeScheduleTransactionKey: {
|
|
@@ -233,12 +278,10 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
233
278
|
};
|
|
234
279
|
},
|
|
235
280
|
reducer(draft, action) {
|
|
236
|
-
const {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const filteredKeys = prevData.filter((jeKey) => jeKey !== jeScheduleKey);
|
|
241
|
-
draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = filteredKeys;
|
|
281
|
+
const { jeScheduleKey } = action.payload;
|
|
282
|
+
// Dropped from every tab's slot, not just the visible one: once a schedule is ignored or
|
|
283
|
+
// resolved it must not reappear when the user switches tabs and hits a cached list.
|
|
284
|
+
removeKeyFromEveryTabSlot(draft.jeScheduleTransactionKeysByPeriodAndTab, jeScheduleKey);
|
|
242
285
|
},
|
|
243
286
|
},
|
|
244
287
|
removeFailedJeScheduleTransactionKey: {
|
|
@@ -251,12 +294,8 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
251
294
|
};
|
|
252
295
|
},
|
|
253
296
|
reducer(draft, action) {
|
|
254
|
-
const {
|
|
255
|
-
|
|
256
|
-
...(draft.failedJeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] ?? []),
|
|
257
|
-
];
|
|
258
|
-
const filteredKeys = prevData.filter((jeKey) => jeKey !== failedJeScheduleKey);
|
|
259
|
-
draft.failedJeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = filteredKeys;
|
|
297
|
+
const { failedJeScheduleKey } = action.payload;
|
|
298
|
+
removeKeyFromEveryTabSlot(draft.failedJeScheduleTransactionKeysByPeriodAndTab, failedJeScheduleKey);
|
|
260
299
|
},
|
|
261
300
|
},
|
|
262
301
|
initializeJeScheduleLocalData: {
|
|
@@ -368,6 +407,91 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
368
407
|
clearJeAccountSettingsLocalData(draft) {
|
|
369
408
|
draft.accountSettings.localData = accountSettingsInitialState.localData;
|
|
370
409
|
},
|
|
410
|
+
initializeNewSchedule: {
|
|
411
|
+
prepare({ scheduleType, }) {
|
|
412
|
+
return { payload: { scheduleType } };
|
|
413
|
+
},
|
|
414
|
+
reducer() {
|
|
415
|
+
// Purely an epic-trigger action — the epic fans out the account/class
|
|
416
|
+
// list fetches plus resetNewScheduleLocalData.
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
resetNewScheduleLocalData: {
|
|
420
|
+
prepare({ scheduleType, }) {
|
|
421
|
+
return { payload: { scheduleType } };
|
|
422
|
+
},
|
|
423
|
+
reducer(draft, action) {
|
|
424
|
+
const { scheduleType } = action.payload;
|
|
425
|
+
draft.newSchedule.newScheduleState[scheduleType] =
|
|
426
|
+
getBaseNewScheduleLocalData(scheduleType);
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
updateNewScheduleLocalData(draft, action) {
|
|
430
|
+
const { scheduleType, localData } = action.payload;
|
|
431
|
+
draft.newSchedule.newScheduleState[scheduleType] = {
|
|
432
|
+
...draft.newSchedule.newScheduleState[scheduleType],
|
|
433
|
+
...localData,
|
|
434
|
+
};
|
|
435
|
+
},
|
|
436
|
+
searchTransactionsForNewSchedule: {
|
|
437
|
+
prepare({ query, scheduleType, }) {
|
|
438
|
+
return { payload: { query, scheduleType } };
|
|
439
|
+
},
|
|
440
|
+
reducer(draft, action) {
|
|
441
|
+
const trimmed = action.payload.query.trim();
|
|
442
|
+
// Cleared or too-short query: no API (see epic) — reset immediately.
|
|
443
|
+
if (trimmed.length < MIN_NEW_SCHEDULE_SEARCH_LENGTH) {
|
|
444
|
+
draft.newSchedule.searchTransactions = searchTransactionsInitialState;
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
draft.newSchedule.searchTransactions = {
|
|
448
|
+
...draft.newSchedule.searchTransactions,
|
|
449
|
+
searchString: action.payload.query,
|
|
450
|
+
fetchState: 'In-Progress',
|
|
451
|
+
};
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
searchTransactionsForNewScheduleSuccess(draft, action) {
|
|
455
|
+
draft.newSchedule.searchTransactions = {
|
|
456
|
+
...draft.newSchedule.searchTransactions,
|
|
457
|
+
searchResults: action.payload.searchResults,
|
|
458
|
+
fetchState: 'Completed',
|
|
459
|
+
error: undefined,
|
|
460
|
+
};
|
|
461
|
+
},
|
|
462
|
+
searchTransactionsForNewScheduleFailure(draft, action) {
|
|
463
|
+
draft.newSchedule.searchTransactions = {
|
|
464
|
+
...draft.newSchedule.searchTransactions,
|
|
465
|
+
fetchState: 'Error',
|
|
466
|
+
error: action.payload.status,
|
|
467
|
+
};
|
|
468
|
+
},
|
|
469
|
+
clearSearchTransactionsForNewSchedule(draft) {
|
|
470
|
+
draft.newSchedule.searchTransactions = searchTransactionsInitialState;
|
|
471
|
+
},
|
|
472
|
+
saveNewSchedule: {
|
|
473
|
+
prepare({ scheduleType, }) {
|
|
474
|
+
return { payload: { scheduleType } };
|
|
475
|
+
},
|
|
476
|
+
reducer(draft) {
|
|
477
|
+
draft.newSchedule.saveStatus = {
|
|
478
|
+
fetchState: 'In-Progress',
|
|
479
|
+
error: undefined,
|
|
480
|
+
};
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
saveNewScheduleSuccess(draft) {
|
|
484
|
+
draft.newSchedule.saveStatus = {
|
|
485
|
+
fetchState: 'Completed',
|
|
486
|
+
error: undefined,
|
|
487
|
+
};
|
|
488
|
+
},
|
|
489
|
+
saveNewScheduleFailure(draft, action) {
|
|
490
|
+
draft.newSchedule.saveStatus = {
|
|
491
|
+
fetchState: 'Error',
|
|
492
|
+
error: action.payload.status,
|
|
493
|
+
};
|
|
494
|
+
},
|
|
371
495
|
updateJESchedulesUIState(draft, action) {
|
|
372
496
|
if (action.payload.sortKey != null) {
|
|
373
497
|
draft.uiState.sortKey = action.payload.sortKey;
|
|
@@ -381,16 +505,27 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
381
505
|
if (action.payload.scrollPosition != null) {
|
|
382
506
|
draft.uiState.scrollPosition = action.payload.scrollPosition;
|
|
383
507
|
}
|
|
384
|
-
if (action.payload.
|
|
385
|
-
draft.uiState.
|
|
508
|
+
if (action.payload.selectedPageTab != null) {
|
|
509
|
+
draft.uiState.selectedPageTab = action.payload.selectedPageTab;
|
|
386
510
|
}
|
|
387
511
|
},
|
|
512
|
+
updateJEScheduleTypeFilter(draft, action) {
|
|
513
|
+
draft.uiState.selectedJETypeFilter = action.payload;
|
|
514
|
+
},
|
|
515
|
+
toggleJEPendingGroupCollapsed(draft) {
|
|
516
|
+
draft.uiState.pendingGroupCollapsed =
|
|
517
|
+
!draft.uiState.pendingGroupCollapsed;
|
|
518
|
+
},
|
|
519
|
+
toggleJECreatedGroupCollapsed(draft) {
|
|
520
|
+
draft.uiState.createdGroupCollapsed =
|
|
521
|
+
!draft.uiState.createdGroupCollapsed;
|
|
522
|
+
},
|
|
388
523
|
clearExpenseAutomationJESchedulesView(draft) {
|
|
389
524
|
Object.assign(draft, initialState);
|
|
390
525
|
},
|
|
391
526
|
},
|
|
392
527
|
});
|
|
393
|
-
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;
|
|
528
|
+
export const { clearExpenseAutomationJESchedulesView, clearJeAccountSettingsLocalData, clearJeScheduleLocalData, clearSearchTransactionsForNewSchedule, fetchAccountSettingsListForAccountTypes, fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesPage, fetchJeSchedulesSuccess, fetchRecommendationForAccountSettings, ignoreRecommendedJeSchedule, ignoreRecommendedJeScheduleFailure, ignoreRecommendedJeScheduleSuccess, initializeAccountSettingsView, initializeJeScheduleLocalData, initializeNewSchedule, removeFailedJeScheduleTransactionKey, removeJeScheduleLocalDataById, 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;
|
|
394
529
|
export default expenseAutomationJESchedulesView.reducer;
|
|
395
530
|
const doUpdateRecommendationForAccountSettings = (draft, payload) => {
|
|
396
531
|
const { prepaidExpensesRecommendations, fixedAssetsRecommendations, accruedExpensesRecommendations, } = mapAccountTypeRecommendationPayloadToAccountRecommendationByType(payload);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|