@zeniai/client-epic-state 5.1.50-betaRR0 → 5.1.51
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/commonStateTypes/amount.d.ts +0 -1
- package/lib/commonStateTypes/amount.js +1 -9
- package/lib/commonStateTypes/workingDayHelper.d.ts +3 -4
- package/lib/commonStateTypes/workingDayHelper.js +3 -4
- package/lib/entity/tenant/clearAllEpic.d.ts +1 -3
- package/lib/entity/tenant/clearAllEpic.js +0 -4
- package/lib/epic.d.ts +1 -7
- package/lib/epic.js +1 -7
- package/lib/esm/commonStateTypes/amount.js +0 -7
- package/lib/esm/commonStateTypes/workingDayHelper.js +3 -4
- package/lib/esm/entity/tenant/clearAllEpic.js +0 -4
- package/lib/esm/epic.js +1 -7
- package/lib/esm/index.js +0 -5
- package/lib/esm/reducer.js +0 -6
- package/lib/esm/view/spendManagement/autotransferRules/autoTransferRulesSelector.js +2 -22
- package/lib/esm/view/transactionDetail/epics/markTransactionAsNotMiscategorizedEpic.js +39 -83
- package/lib/index.d.ts +1 -10
- package/lib/index.js +1 -20
- package/lib/reducer.d.ts +0 -6
- package/lib/reducer.js +0 -6
- package/lib/view/spendManagement/autotransferRules/autoTransferRulesSelector.d.ts +1 -8
- package/lib/view/spendManagement/autotransferRules/autoTransferRulesSelector.js +1 -21
- package/lib/view/spendManagement/autotransferRules/autoTransferRulesState.d.ts +0 -22
- package/lib/view/transactionDetail/epics/markTransactionAsNotMiscategorizedEpic.js +38 -82
- package/lib/zeniAPI.d.ts +0 -1
- package/package.json +1 -1
- package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.js +0 -29
- package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.js +0 -78
- package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.js +0 -49
- package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.js +0 -47
- package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.js +0 -32
- package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.js +0 -32
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.js +0 -54
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.js +0 -92
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.js +0 -212
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.js +0 -10
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.js +0 -23
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.js +0 -36
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementRecommendationEpic.js +0 -27
- package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchRecentTransferEpic.js +0 -28
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.d.ts +0 -47
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.js +0 -34
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.d.ts +0 -23
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.js +0 -82
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.d.ts +0 -40
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.js +0 -53
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.d.ts +0 -37
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.js +0 -53
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.d.ts +0 -14
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.js +0 -36
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.d.ts +0 -7
- package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.js +0 -36
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.d.ts +0 -56
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.js +0 -60
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.d.ts +0 -22
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.js +0 -96
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.d.ts +0 -59
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.js +0 -217
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.d.ts +0 -122
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.js +0 -13
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.d.ts +0 -7
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.js +0 -27
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.d.ts +0 -9
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.js +0 -40
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementRecommendationEpic.d.ts +0 -7
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementRecommendationEpic.js +0 -31
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchRecentTransferEpic.d.ts +0 -15
- package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchRecentTransferEpic.js +0 -32
|
@@ -7,93 +7,11 @@ const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
|
|
|
7
7
|
const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
|
|
8
8
|
const tenantSelector_1 = require("../../../entity/tenant/tenantSelector");
|
|
9
9
|
const transactionReducer_1 = require("../../../entity/transaction/transactionReducer");
|
|
10
|
-
const transactionSelector_1 = require("../../../entity/transaction/transactionSelector");
|
|
11
10
|
const responsePayload_1 = require("../../../responsePayload");
|
|
12
11
|
const transactionsViewReducer_1 = require("../../expenseAutomationView/reducers/transactionsViewReducer");
|
|
13
12
|
const transactionDetailReducer_1 = require("../transactionDetailReducer");
|
|
14
13
|
const transactionDetailState_1 = require("../transactionDetailState");
|
|
15
14
|
const markTransactionAsNotMiscategorizedEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(transactionDetailReducer_1.markTransactionAsNotMiscategorized.match), (0, operators_1.mergeMap)((action) => {
|
|
16
|
-
if (action.payload.isExpenseAutomationEnabled === true) {
|
|
17
|
-
const transactionKey = (0, transactionDetailState_1.getTransactionDetailKey)(action.payload.transactionId);
|
|
18
|
-
const transaction = (0, transactionSelector_1.getSupportedTransactionById)(state$.value.transactionState, transactionKey);
|
|
19
|
-
const lineIds = (transaction?.lines ?? []).map((line) => line.id);
|
|
20
|
-
return zeniAPI
|
|
21
|
-
.putAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/expense-automation/mark-as-reviewed`, {
|
|
22
|
-
transactions_reviewed: [
|
|
23
|
-
{
|
|
24
|
-
transaction_id: action.payload.transactionId.id,
|
|
25
|
-
line_ids: lineIds,
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
})
|
|
29
|
-
.pipe((0, operators_1.mergeMap)((response) => {
|
|
30
|
-
if ((0, responsePayload_1.isSuccessResponse)(response)) {
|
|
31
|
-
const actions = [];
|
|
32
|
-
actions.push((0, transactionDetailReducer_1.updateStatusForTransactionNotMiscategorizedUpdate)(action.payload.transactionId, 'Completed', undefined));
|
|
33
|
-
const txnId = action.payload.transactionId.id;
|
|
34
|
-
const reviewedFailed = response.data?.transactions_reviewed_failed ?? [];
|
|
35
|
-
const isTransactionFailed = reviewedFailed.some((t) => t.transaction_id === txnId);
|
|
36
|
-
if (!isTransactionFailed) {
|
|
37
|
-
actions.push((0, transactionReducer_1.updateTransactionIsMiscategorized)(transactionKey, false));
|
|
38
|
-
const { expenseAutomationViewState, expenseAutomationTransactionsViewState, } = state$.value;
|
|
39
|
-
const { transactionCategorizationView, selectedTransactionCategorizationTab, } = expenseAutomationTransactionsViewState;
|
|
40
|
-
const currentTenant = (0, tenantSelector_1.getCurrentTenant)(state$.value);
|
|
41
|
-
const { selectedPeriodByTenantId } = expenseAutomationViewState;
|
|
42
|
-
const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
|
|
43
|
-
const autoTabLineItems = transactionCategorizationView.autoCategorized
|
|
44
|
-
.transactionReviewLocalDataById[txnId]
|
|
45
|
-
?.transactionReviewLocalData.tabSpecificLineItems
|
|
46
|
-
.autoCategorized ?? [];
|
|
47
|
-
const hasAutoLines = autoTabLineItems.length > 0;
|
|
48
|
-
const { uiState } = transactionCategorizationView[selectedTransactionCategorizationTab];
|
|
49
|
-
const removeIdsFromPeriod = selectedTransactionCategorizationTab === 'review'
|
|
50
|
-
? [txnId]
|
|
51
|
-
: hasAutoLines
|
|
52
|
-
? []
|
|
53
|
-
: [txnId];
|
|
54
|
-
actions.push((0, transactionsViewReducer_1.updateStatusForTransactionNotMiscategorizedUpdateForCategorization)(selectedTransactionCategorizationTab, [txnId], removeIdsFromPeriod, selectedPeriod, 'Completed'));
|
|
55
|
-
if (!hasAutoLines) {
|
|
56
|
-
actions.push((0, transactionReducer_1.removeTransactionCategorization)({
|
|
57
|
-
transactionIds: [txnId],
|
|
58
|
-
}));
|
|
59
|
-
}
|
|
60
|
-
if (removeIdsFromPeriod.length > 0) {
|
|
61
|
-
const totalCountByPeriod = uiState.totalCount[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)];
|
|
62
|
-
const updatedTotalCount = totalCountByPeriod === 0
|
|
63
|
-
? totalCountByPeriod
|
|
64
|
-
: totalCountByPeriod - 1;
|
|
65
|
-
actions.push((0, transactionsViewReducer_1.updateTotalCountForTransactionCategorization)({
|
|
66
|
-
selectedPeriod,
|
|
67
|
-
selectedTab: selectedTransactionCategorizationTab,
|
|
68
|
-
totalCount: updatedTotalCount,
|
|
69
|
-
}));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
actions.push((0, transactionDetailReducer_1.updateStatusConsolidatedSaveTransactionDetail)({
|
|
73
|
-
transactionId: action.payload.transactionId,
|
|
74
|
-
fetchState: 'Completed',
|
|
75
|
-
}));
|
|
76
|
-
if (action.payload.transactionSaveUpdates.anyBulkUpdates === true) {
|
|
77
|
-
actions.push((0, snackbarReducer_1.openSnackbar)({
|
|
78
|
-
messageSection: 'transactionDetails_updatingPastTransactions',
|
|
79
|
-
messageText: 'success',
|
|
80
|
-
type: 'success',
|
|
81
|
-
}));
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
actions.push((0, snackbarReducer_1.openSnackbar)({
|
|
85
|
-
messageSection: 'transactionDetails_transactionUpdated',
|
|
86
|
-
messageText: 'success',
|
|
87
|
-
type: 'success',
|
|
88
|
-
}));
|
|
89
|
-
}
|
|
90
|
-
return (0, rxjs_1.from)(actions);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
return (0, rxjs_1.of)((0, transactionDetailReducer_1.updateStatusForTransactionNotMiscategorizedUpdate)(action.payload.transactionId, 'Error', response.status));
|
|
94
|
-
}
|
|
95
|
-
}), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, transactionDetailReducer_1.updateStatusForTransactionNotMiscategorizedUpdate)(action.payload.transactionId, 'Error', (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', `Transaction mark as reviewed REST API call errored out ${error}`)))));
|
|
96
|
-
}
|
|
97
15
|
return zeniAPI
|
|
98
16
|
.putAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/${action.payload.transactionId.id}/mark-miscategorized-as-correct`, preparePayload(action.payload.transactionId))
|
|
99
17
|
.pipe((0, operators_1.mergeMap)((response) => {
|
|
@@ -101,7 +19,44 @@ const markTransactionAsNotMiscategorizedEpic = (actions$, state$, zeniAPI) => ac
|
|
|
101
19
|
const actions = [];
|
|
102
20
|
actions.push((0, transactionDetailReducer_1.updateStatusForTransactionNotMiscategorizedUpdate)(action.payload.transactionId, 'Completed', undefined));
|
|
103
21
|
const transactionKey = (0, transactionDetailState_1.getTransactionDetailKey)(action.payload.transactionId);
|
|
22
|
+
// Mark this transaction as not miscategorized anymore
|
|
104
23
|
actions.push((0, transactionReducer_1.updateTransactionIsMiscategorized)(transactionKey, false));
|
|
24
|
+
if (action.payload.isExpenseAutomationEnabled === true) {
|
|
25
|
+
const { expenseAutomationViewState, expenseAutomationTransactionsViewState, } = state$.value;
|
|
26
|
+
const { transactionCategorizationView, selectedTransactionCategorizationTab, } = expenseAutomationTransactionsViewState;
|
|
27
|
+
const currentTenant = (0, tenantSelector_1.getCurrentTenant)(state$.value);
|
|
28
|
+
const { selectedPeriodByTenantId } = expenseAutomationViewState;
|
|
29
|
+
const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
|
|
30
|
+
const txnId = action.payload.transactionId.id;
|
|
31
|
+
const autoTabLineItems = transactionCategorizationView.autoCategorized
|
|
32
|
+
.transactionReviewLocalDataById[txnId]
|
|
33
|
+
?.transactionReviewLocalData.tabSpecificLineItems
|
|
34
|
+
.autoCategorized ?? [];
|
|
35
|
+
const hasAutoLines = autoTabLineItems.length > 0;
|
|
36
|
+
const { uiState } = transactionCategorizationView[selectedTransactionCategorizationTab];
|
|
37
|
+
const removeIdsFromPeriod = selectedTransactionCategorizationTab === 'review'
|
|
38
|
+
? [txnId]
|
|
39
|
+
: hasAutoLines
|
|
40
|
+
? []
|
|
41
|
+
: [txnId];
|
|
42
|
+
actions.push((0, transactionsViewReducer_1.updateStatusForTransactionNotMiscategorizedUpdateForCategorization)(selectedTransactionCategorizationTab, [txnId], removeIdsFromPeriod, selectedPeriod, 'Completed'));
|
|
43
|
+
if (!hasAutoLines) {
|
|
44
|
+
actions.push((0, transactionReducer_1.removeTransactionCategorization)({
|
|
45
|
+
transactionIds: [txnId],
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
if (removeIdsFromPeriod.length > 0) {
|
|
49
|
+
const totalCountByPeriod = uiState.totalCount[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)];
|
|
50
|
+
const updatedTotalCount = totalCountByPeriod === 0
|
|
51
|
+
? totalCountByPeriod
|
|
52
|
+
: totalCountByPeriod - 1;
|
|
53
|
+
actions.push((0, transactionsViewReducer_1.updateTotalCountForTransactionCategorization)({
|
|
54
|
+
selectedPeriod,
|
|
55
|
+
selectedTab: selectedTransactionCategorizationTab,
|
|
56
|
+
totalCount: updatedTotalCount,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
105
60
|
actions.push((0, transactionDetailReducer_1.updateStatusConsolidatedSaveTransactionDetail)({
|
|
106
61
|
transactionId: action.payload.transactionId,
|
|
107
62
|
fetchState: 'Completed',
|
|
@@ -114,6 +69,7 @@ const markTransactionAsNotMiscategorizedEpic = (actions$, state$, zeniAPI) => ac
|
|
|
114
69
|
}));
|
|
115
70
|
}
|
|
116
71
|
else {
|
|
72
|
+
//Finally everything done for this transaction
|
|
117
73
|
actions.push((0, snackbarReducer_1.openSnackbar)({
|
|
118
74
|
messageSection: 'transactionDetails_transactionUpdated',
|
|
119
75
|
messageText: 'success',
|
package/lib/zeniAPI.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ export interface RESTAPIEndpoints {
|
|
|
10
10
|
readonly authMicroServiceBaseUrl: string;
|
|
11
11
|
readonly bankingMicroServiceBaseUrl: string;
|
|
12
12
|
readonly cardMicroServiceBaseUrl: string;
|
|
13
|
-
readonly cashManagementAgentBaseUrl: string;
|
|
14
13
|
readonly communicationAgentMicroServiceBaseUrl: string;
|
|
15
14
|
readonly documentAIMicroServiceBaseUrl: string;
|
|
16
15
|
readonly fileMicroServiceBaseUrl: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.51",
|
|
4
4
|
"description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { toAmount } from '../../../../commonStateTypes/amount';
|
|
2
|
-
import { date } from '../../../../zeniDayJS';
|
|
3
|
-
import { toAutoSweepFrequency, } from './autoSweepFlowState';
|
|
4
|
-
export const toSaveAutoSweepSettingsBody = (state) => ({
|
|
5
|
-
frequency: state.frequency,
|
|
6
|
-
memo: state.memo,
|
|
7
|
-
minimum_buffer_usd: state.bufferAmount.amount,
|
|
8
|
-
});
|
|
9
|
-
/**
|
|
10
|
-
* Map a `GET /cash-management/settings` payload into the slice's writable
|
|
11
|
-
* fields. Defensive on the frequency (string-from-the-wire → union via
|
|
12
|
-
* `toAutoSweepFrequency`, falling back to `'weekly'` if the server returns
|
|
13
|
-
* something we don't model yet). Only the source account *id* is stored
|
|
14
|
-
* here — the full deposit-account payload is published to the entity bucket
|
|
15
|
-
* by the fetch epic.
|
|
16
|
-
*/
|
|
17
|
-
export const toAutoSweepFlowStatePatch = (payload) => {
|
|
18
|
-
const currencyCode = payload.source_bank_account.balances?.currency_code;
|
|
19
|
-
const currencySymbol = payload.source_bank_account.balances?.currency_symbol;
|
|
20
|
-
return {
|
|
21
|
-
bufferAmount: toAmount(payload.minimum_buffer_usd, currencyCode ?? 'USD', currencySymbol ?? '$'),
|
|
22
|
-
frequency: toAutoSweepFrequency(payload.frequency) ?? 'weekly',
|
|
23
|
-
nextTransferDate: payload.next_run_date != null && payload.next_run_date !== ''
|
|
24
|
-
? date(payload.next_run_date)
|
|
25
|
-
: undefined,
|
|
26
|
-
primaryFundingAccountId: payload.source_bank_account.deposit_account_id ?? undefined,
|
|
27
|
-
settingsId: payload.cash_management_settings_id ?? undefined,
|
|
28
|
-
};
|
|
29
|
-
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
-
import { toAutoSweepFlowStatePatch, } from './autoSweepFlowPayload';
|
|
3
|
-
import { initialAutoSweepFlowState, } from './autoSweepFlowState';
|
|
4
|
-
export const initialState = initialAutoSweepFlowState;
|
|
5
|
-
const autoSweepFlow = createSlice({
|
|
6
|
-
name: 'autoSweepFlow',
|
|
7
|
-
initialState,
|
|
8
|
-
reducers: {
|
|
9
|
-
/**
|
|
10
|
-
* Kicks off `GET /cash-management/settings`. Flips the top-level
|
|
11
|
-
* fetchState to `In-Progress`; the fetch epic picks this up.
|
|
12
|
-
*/
|
|
13
|
-
fetchCashManagementSettings(draft) {
|
|
14
|
-
draft.fetchState = 'In-Progress';
|
|
15
|
-
draft.error = undefined;
|
|
16
|
-
},
|
|
17
|
-
/**
|
|
18
|
-
* Hydrates the form fields with the server-side settings (and stashes
|
|
19
|
-
* the settings id for subsequent saves). Marks the GET as `Completed`.
|
|
20
|
-
*/
|
|
21
|
-
updateCashManagementSettings(draft, action) {
|
|
22
|
-
const patch = toAutoSweepFlowStatePatch(action.payload.data);
|
|
23
|
-
draft.bufferAmount = patch.bufferAmount;
|
|
24
|
-
draft.frequency = patch.frequency;
|
|
25
|
-
draft.nextTransferDate = patch.nextTransferDate;
|
|
26
|
-
draft.primaryFundingAccountId = patch.primaryFundingAccountId;
|
|
27
|
-
draft.settingsId = patch.settingsId;
|
|
28
|
-
draft.fetchState = 'Completed';
|
|
29
|
-
draft.error = undefined;
|
|
30
|
-
},
|
|
31
|
-
updateCashManagementSettingsFetchStatus(draft, action) {
|
|
32
|
-
draft.fetchState = action.payload.fetchState;
|
|
33
|
-
draft.error = action.payload.error;
|
|
34
|
-
},
|
|
35
|
-
/**
|
|
36
|
-
* Live-update the buffer (risk band) as the user toggles the risk picker
|
|
37
|
-
* on the setup page, without staging frequency/memo. The selector derives
|
|
38
|
-
* the risk-adjusted sweep amount off `bufferAmount`, so dispatching this on
|
|
39
|
-
* every risk change keeps the setup and review screens in sync.
|
|
40
|
-
*/
|
|
41
|
-
updateAutoSweepRisk(draft, action) {
|
|
42
|
-
draft.bufferAmount = action.payload.bufferAmount;
|
|
43
|
-
},
|
|
44
|
-
/**
|
|
45
|
-
* Stage the in-flight form values without submitting them — fired from
|
|
46
|
-
* the setup→review transition so other selectors (and devtools) can see
|
|
47
|
-
* what the user is about to confirm. Leaves `saveStatus` untouched; the
|
|
48
|
-
* actual PUT only kicks off when the user clicks "Confirm Sweep" via
|
|
49
|
-
* `saveAutoSweepSettings`.
|
|
50
|
-
*/
|
|
51
|
-
updateAutoSweepDraft(draft, action) {
|
|
52
|
-
draft.bufferAmount = action.payload.bufferAmount;
|
|
53
|
-
draft.frequency = action.payload.frequency;
|
|
54
|
-
draft.memo = action.payload.memo;
|
|
55
|
-
},
|
|
56
|
-
/**
|
|
57
|
-
* Trigger the PUT for the auto-sweep settings already staged via
|
|
58
|
-
* `updateAutoSweepDraft`. Carries no payload — flips `saveStatus` to
|
|
59
|
-
* `In-Progress` and the save epic reads `bufferAmount` / `frequency` /
|
|
60
|
-
* `memo` straight from the slice. Callers must ensure those fields
|
|
61
|
-
* reflect the user's latest input before dispatching.
|
|
62
|
-
*/
|
|
63
|
-
saveAutoSweepSettings(draft) {
|
|
64
|
-
draft.saveStatus = { fetchState: 'In-Progress', error: undefined };
|
|
65
|
-
},
|
|
66
|
-
updateAutoSweepSettingsFetchStatus(draft, action) {
|
|
67
|
-
draft.saveStatus = {
|
|
68
|
-
fetchState: action.payload.fetchState,
|
|
69
|
-
error: action.payload.error,
|
|
70
|
-
};
|
|
71
|
-
},
|
|
72
|
-
clearAutoSweepFlow() {
|
|
73
|
-
return initialAutoSweepFlowState;
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
export const { fetchCashManagementSettings, updateCashManagementSettings, updateCashManagementSettingsFetchStatus, updateAutoSweepRisk, updateAutoSweepDraft, saveAutoSweepSettings, updateAutoSweepSettingsFetchStatus, clearAutoSweepFlow, } = autoSweepFlow.actions;
|
|
78
|
-
export default autoSweepFlow.reducer;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { getDepositAccountByDepositAccountId } from '../../../../entity/depositAccount/depositAccountSelector';
|
|
2
|
-
import { mapDepositAccToFundingAccount, } from '../../commonSetup/setupViewSelector';
|
|
3
|
-
import { getTreasuryDetail } from '../../treasury/treasuryList/treasuryDetailSelector';
|
|
4
|
-
import { getCashManagementOverviewBanner } from '../cashManagementOverview/cashManagementOverviewSelector';
|
|
5
|
-
import { RISK_BUFFER_AMOUNT, bufferAmountToRisk, } from './autoSweepFlowState';
|
|
6
|
-
/**
|
|
7
|
-
* Risk band the agent's recommended sweep amount is computed against. The
|
|
8
|
-
* `sweepAmount` returned by the banner assumes this buffer, so the selector
|
|
9
|
-
* adjusts the displayed sweep by the delta between the user's selected band
|
|
10
|
-
* and this default.
|
|
11
|
-
*/
|
|
12
|
-
const DEFAULT_RISK_LEVEL = 'moderate';
|
|
13
|
-
export const getAutoSweepFlow = (state) => {
|
|
14
|
-
const { bufferAmount, frequency, memo, saveStatus, settingsId, primaryFundingAccountId, fetchState, error, } = state.autoSweepFlowState;
|
|
15
|
-
const depositAccount = primaryFundingAccountId != null
|
|
16
|
-
? getDepositAccountByDepositAccountId(state.depositAccountState, primaryFundingAccountId)
|
|
17
|
-
: undefined;
|
|
18
|
-
const risk = bufferAmountToRisk(bufferAmount.amount);
|
|
19
|
-
// The banner's recommended sweep assumes the default buffer band; shift it
|
|
20
|
-
// by the delta between the default buffer and the user's selected band so a
|
|
21
|
-
// tighter buffer (higher risk → smaller buffer) sweeps more and a looser
|
|
22
|
-
// buffer (lower risk → larger buffer) sweeps less. Clamp at zero so a buffer
|
|
23
|
-
// larger than the available surplus never yields a negative sweep.
|
|
24
|
-
const baseSweepAmount = getCashManagementOverviewBanner(state).amount;
|
|
25
|
-
const sweepAmount = {
|
|
26
|
-
...baseSweepAmount,
|
|
27
|
-
amount: Math.max(0, baseSweepAmount.amount +
|
|
28
|
-
RISK_BUFFER_AMOUNT[DEFAULT_RISK_LEVEL] -
|
|
29
|
-
RISK_BUFFER_AMOUNT[risk]),
|
|
30
|
-
};
|
|
31
|
-
return {
|
|
32
|
-
fetchState,
|
|
33
|
-
error,
|
|
34
|
-
formData: {
|
|
35
|
-
bufferAmount,
|
|
36
|
-
frequency,
|
|
37
|
-
memo,
|
|
38
|
-
risk,
|
|
39
|
-
},
|
|
40
|
-
primaryFundingAccount: depositAccount != null
|
|
41
|
-
? mapDepositAccToFundingAccount(depositAccount)
|
|
42
|
-
: undefined,
|
|
43
|
-
saveStatus,
|
|
44
|
-
settingsId,
|
|
45
|
-
sweepAmount,
|
|
46
|
-
treasurySummary: getTreasuryDetail(state).accountSummary,
|
|
47
|
-
version: 0,
|
|
48
|
-
};
|
|
49
|
-
};
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { toAmount } from '../../../../commonStateTypes/amount';
|
|
2
|
-
import { stringToUnion } from '../../../../commonStateTypes/stringToUnion';
|
|
3
|
-
/**
|
|
4
|
-
* Cadence at which the auto-sweep transfer fires. Lowercase to match the
|
|
5
|
-
* cash-management settings API contract (and the `SweepFrequency` literal
|
|
6
|
-
* already used by `<AutoSweepSetupPage>` in web-components).
|
|
7
|
-
*/
|
|
8
|
-
export const ALL_AUTO_SWEEP_FREQUENCIES = [
|
|
9
|
-
'daily',
|
|
10
|
-
'weekly',
|
|
11
|
-
'biweekly',
|
|
12
|
-
'monthly',
|
|
13
|
-
];
|
|
14
|
-
export const toAutoSweepFrequency = (v) => stringToUnion(v ?? '', ALL_AUTO_SWEEP_FREQUENCIES);
|
|
15
|
-
/**
|
|
16
|
-
* Risk presets the auto-sweep setup form exposes. Each level maps to a
|
|
17
|
-
* canonical minimum-buffer amount (USD). Selecting a level in the UI is
|
|
18
|
-
* shorthand for choosing that buffer.
|
|
19
|
-
*/
|
|
20
|
-
export const ALL_AUTO_SWEEP_RISK_LEVELS = ['low', 'moderate', 'high'];
|
|
21
|
-
export const toAutoSweepRiskLevel = (v) => stringToUnion(v ?? '', ALL_AUTO_SWEEP_RISK_LEVELS);
|
|
22
|
-
export const RISK_BUFFER_AMOUNT = {
|
|
23
|
-
low: 15000,
|
|
24
|
-
moderate: 10000,
|
|
25
|
-
high: 5000,
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Maps a buffer amount back onto the closest preset risk level. Falls back
|
|
29
|
-
* to `'moderate'` when the amount doesn't match a known preset (e.g. the
|
|
30
|
-
* server returned a custom value). The dropdown in `<AutoSweepSetupPage>`
|
|
31
|
-
* uses this so it can pre-select the user's existing band on edit.
|
|
32
|
-
*/
|
|
33
|
-
export const bufferAmountToRisk = (amount) => {
|
|
34
|
-
const match = Object.entries(RISK_BUFFER_AMOUNT).find(([, presetAmount]) => presetAmount === amount);
|
|
35
|
-
return match != null ? match[0] : 'moderate';
|
|
36
|
-
};
|
|
37
|
-
export const initialAutoSweepFlowState = {
|
|
38
|
-
bufferAmount: toAmount(10000, 'USD', '$'),
|
|
39
|
-
frequency: 'weekly',
|
|
40
|
-
memo: '',
|
|
41
|
-
saveStatus: { fetchState: 'Not-Started', error: undefined },
|
|
42
|
-
nextTransferDate: undefined,
|
|
43
|
-
primaryFundingAccountId: undefined,
|
|
44
|
-
settingsId: undefined,
|
|
45
|
-
fetchState: 'Not-Started',
|
|
46
|
-
error: undefined,
|
|
47
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
-
import { updateDepositAccounts } from '../../../../../entity/depositAccount/depositAccountReducer';
|
|
4
|
-
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
|
|
5
|
-
import { fetchCashManagementSettings, updateCashManagementSettings, updateCashManagementSettingsFetchStatus, } from '../autoSweepFlowReducer';
|
|
6
|
-
/**
|
|
7
|
-
* Hits `GET /cash-management/settings` and hydrates the auto-sweep slice
|
|
8
|
-
* with the server's existing settings (frequency, minimum buffer, settings
|
|
9
|
-
* id). Called from the cash management overview page-fetch epic alongside
|
|
10
|
-
* the other top-level fetches.
|
|
11
|
-
*/
|
|
12
|
-
export const fetchCashManagementSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchCashManagementSettings.match), switchMap(() => {
|
|
13
|
-
const endpoint = `${zeniAPI.apiEndPoints.cashManagementAgentBaseUrl}/1.0/cash-management/settings`;
|
|
14
|
-
return zeniAPI.getJSON(endpoint).pipe(mergeMap((response) => {
|
|
15
|
-
if (isSuccessResponse(response) && response.data != null) {
|
|
16
|
-
return of(
|
|
17
|
-
// Publish the source deposit account into the shared entity
|
|
18
|
-
// bucket so the selector can hydrate the full `FundingAccount`
|
|
19
|
-
// from `getDepositAccountByDepositAccountId` rather than the
|
|
20
|
-
// auto-sweep slice holding a duplicate copy.
|
|
21
|
-
updateDepositAccounts([response.data.source_bank_account]), updateCashManagementSettings({ data: response.data }));
|
|
22
|
-
}
|
|
23
|
-
return of(updateCashManagementSettingsFetchStatus({
|
|
24
|
-
fetchState: 'Error',
|
|
25
|
-
error: response.status,
|
|
26
|
-
}));
|
|
27
|
-
}), catchError((error) => of(updateCashManagementSettingsFetchStatus({
|
|
28
|
-
fetchState: 'Error',
|
|
29
|
-
error: createZeniAPIStatus('Unexpected Error', 'Fetch cash management settings REST API call errored out: ' +
|
|
30
|
-
(error?.message ?? String(error))),
|
|
31
|
-
}))));
|
|
32
|
-
}));
|
package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
-
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
|
|
4
|
-
import { toSaveAutoSweepSettingsBody, } from '../autoSweepFlowPayload';
|
|
5
|
-
import { saveAutoSweepSettings, updateAutoSweepSettingsFetchStatus, } from '../autoSweepFlowReducer';
|
|
6
|
-
export const saveAutoSweepSettingsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(saveAutoSweepSettings.match), switchMap(() => {
|
|
7
|
-
const endpoint = `${zeniAPI.apiEndPoints.cashManagementAgentBaseUrl}/1.0/cash-management/settings`;
|
|
8
|
-
const { bufferAmount, frequency, memo, settingsId } = state$.value.autoSweepFlowState;
|
|
9
|
-
const payload = toSaveAutoSweepSettingsBody({
|
|
10
|
-
bufferAmount,
|
|
11
|
-
frequency,
|
|
12
|
-
memo,
|
|
13
|
-
});
|
|
14
|
-
// First-time setup (no settings id from the GET yet) → POST a new
|
|
15
|
-
// record. Subsequent edits update the existing one via PUT.
|
|
16
|
-
const request$ = settingsId == null
|
|
17
|
-
? zeniAPI.postAndGetJSON(endpoint, payload)
|
|
18
|
-
: zeniAPI.putAndGetJSON(endpoint, payload);
|
|
19
|
-
return request$.pipe(mergeMap((response) => {
|
|
20
|
-
if (isSuccessResponse(response) && response.data != null) {
|
|
21
|
-
return of(updateAutoSweepSettingsFetchStatus({ fetchState: 'Completed' }));
|
|
22
|
-
}
|
|
23
|
-
return of(updateAutoSweepSettingsFetchStatus({
|
|
24
|
-
fetchState: 'Error',
|
|
25
|
-
error: response?.status,
|
|
26
|
-
}));
|
|
27
|
-
}), catchError((error) => of(updateAutoSweepSettingsFetchStatus({
|
|
28
|
-
fetchState: 'Error',
|
|
29
|
-
error: createZeniAPIStatus('Unexpected Error', 'Save auto-sweep settings REST API call errored out: ' +
|
|
30
|
-
(error?.message ?? String(error))),
|
|
31
|
-
}))));
|
|
32
|
-
}));
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { toAmount } from '../../../../commonStateTypes/amount';
|
|
2
|
-
import { date as zeniDate } from '../../../../zeniDayJS';
|
|
3
|
-
// ---------------------------------------------------------------------------
|
|
4
|
-
// Converters
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
// The cash agent payload reports `currency_code` only; the v1 surface is
|
|
7
|
-
// USD-only, so we pair it with the canonical `$` symbol here. If the agent
|
|
8
|
-
// grows multi-currency support, this is the single place to widen.
|
|
9
|
-
const CASH_AGENT_CURRENCY_SYMBOL = '$';
|
|
10
|
-
export const toUpcomingPaymentEvent = (event) => ({
|
|
11
|
-
accountId: event.account_id,
|
|
12
|
-
accountType: event.account_type,
|
|
13
|
-
amount: toAmount(event.amount_usd, event.currency_code, CASH_AGENT_CURRENCY_SYMBOL),
|
|
14
|
-
label: event.label,
|
|
15
|
-
paymentDate: zeniDate(event.payment_date),
|
|
16
|
-
});
|
|
17
|
-
/**
|
|
18
|
-
* The agent reports a `null` account id whenever the "account" in question is
|
|
19
|
-
* a singleton inferred from the account type (today: the treasury account —
|
|
20
|
-
* there's only one per company, so the type alone identifies it). Callers
|
|
21
|
-
* already branch on `*BankAccountType`, so collapsing the id to `""` keeps the
|
|
22
|
-
* state type a plain `ID` (string) without losing information.
|
|
23
|
-
*/
|
|
24
|
-
const toCashManagementMovement = (payload) => ({
|
|
25
|
-
amount: toAmount(payload.amount, payload.currency_code, CASH_AGENT_CURRENCY_SYMBOL),
|
|
26
|
-
destinationBankAccountId: payload.destination_bank_account_id ?? '',
|
|
27
|
-
destinationBankAccountType: payload.destination_bank_account_type,
|
|
28
|
-
reasoning: payload.reasoning,
|
|
29
|
-
sourceBankAccountId: payload.source_bank_account_id ?? '',
|
|
30
|
-
sourceBankAccountType: payload.source_bank_account_type,
|
|
31
|
-
subMovementType: payload.sub_movement_type,
|
|
32
|
-
});
|
|
33
|
-
const toCashManagementMoneyMovementGroup = (payload) => ({
|
|
34
|
-
movements: payload.movements.map(toCashManagementMovement),
|
|
35
|
-
movementType: payload.movement_type,
|
|
36
|
-
});
|
|
37
|
-
export const toCashManagementBannerData = (payload) => ({
|
|
38
|
-
inflows: payload.inflows.map(toUpcomingPaymentEvent),
|
|
39
|
-
moneyMovements: payload.money_movements.map(toCashManagementMoneyMovementGroup),
|
|
40
|
-
outflows: payload.outflows.map(toUpcomingPaymentEvent),
|
|
41
|
-
});
|
|
42
|
-
export const toCashManagementTransfer = (payload) => ({
|
|
43
|
-
amount: toAmount(payload.amount, payload.currency_code, CASH_AGENT_CURRENCY_SYMBOL),
|
|
44
|
-
atomicTransactionId: payload.atomic_transaction_id,
|
|
45
|
-
cashManagementTransferId: payload.cash_management_transfer_id,
|
|
46
|
-
createTime: zeniDate(payload.create_time),
|
|
47
|
-
date: zeniDate(payload.date),
|
|
48
|
-
depositAccountId: payload.deposit_account_id,
|
|
49
|
-
reasoning: payload.reasoning,
|
|
50
|
-
scenario: payload.scenario,
|
|
51
|
-
status: payload.status,
|
|
52
|
-
transactionType: payload.transaction_type,
|
|
53
|
-
updateTime: zeniDate(payload.update_time),
|
|
54
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
-
import { toCashManagementBannerData, toCashManagementTransfer, } from './cashManagementOverviewPayload';
|
|
3
|
-
import { initialCashManagementBannerState, initialCashManagementRecentTransferState, } from './cashManagementOverviewState';
|
|
4
|
-
export const initialState = {
|
|
5
|
-
banner: initialCashManagementBannerState,
|
|
6
|
-
recentTransfer: initialCashManagementRecentTransferState,
|
|
7
|
-
};
|
|
8
|
-
const cashManagementOverview = createSlice({
|
|
9
|
-
name: 'cashManagementOverview',
|
|
10
|
-
initialState,
|
|
11
|
-
reducers: {
|
|
12
|
-
fetchCashManagementOverviewPage: {
|
|
13
|
-
reducer() { },
|
|
14
|
-
prepare(cacheOverride) {
|
|
15
|
-
return { payload: { cacheOverride } };
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
/**
|
|
19
|
-
* Public banner-fetch entry point. Triggers an orchestrator epic that
|
|
20
|
-
* fans out to the recommend, settings, and recent-transfer API calls
|
|
21
|
-
* in parallel. No reducer-side state change — each inner action drives
|
|
22
|
-
* its own sub-state.
|
|
23
|
-
*
|
|
24
|
-
* `cacheOverride === true` forces all three inner fetches regardless
|
|
25
|
-
* of current slice state; `false` keeps the per-slice dedup so repeat
|
|
26
|
-
* dispatches are no-ops once a slice is loaded or in-flight.
|
|
27
|
-
*/
|
|
28
|
-
fetchCashManagementBanner: {
|
|
29
|
-
reducer() { },
|
|
30
|
-
prepare(cacheOverride) {
|
|
31
|
-
return { payload: { cacheOverride } };
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
/**
|
|
35
|
-
* Internal trigger for the recommend API (`/cash-agent/recommend`).
|
|
36
|
-
* Dispatched by the orchestrator; not exported.
|
|
37
|
-
*/
|
|
38
|
-
fetchCashManagementRecommendation(draft) {
|
|
39
|
-
// Keep `draft.banner.data` so the projection chart renders the last
|
|
40
|
-
// good payload while the refetch is in flight, instead of flickering
|
|
41
|
-
// to the empty/skeleton state on every page revisit.
|
|
42
|
-
draft.banner.fetchState = 'In-Progress';
|
|
43
|
-
draft.banner.error = undefined;
|
|
44
|
-
},
|
|
45
|
-
updateCashManagementRecommendation(draft, action) {
|
|
46
|
-
draft.banner = {
|
|
47
|
-
fetchState: 'Completed',
|
|
48
|
-
error: undefined,
|
|
49
|
-
data: toCashManagementBannerData(action.payload.data),
|
|
50
|
-
};
|
|
51
|
-
},
|
|
52
|
-
updateCashManagementRecommendationFetchStatus(draft, action) {
|
|
53
|
-
draft.banner = {
|
|
54
|
-
...draft.banner,
|
|
55
|
-
fetchState: action.payload.fetchState,
|
|
56
|
-
error: action.payload.error,
|
|
57
|
-
};
|
|
58
|
-
},
|
|
59
|
-
/**
|
|
60
|
-
* Internal trigger for the recent-transfer API
|
|
61
|
-
* (`/cash-management/transfers`). Dispatched by the orchestrator; not
|
|
62
|
-
* exported.
|
|
63
|
-
*/
|
|
64
|
-
fetchRecentTransfer(draft) {
|
|
65
|
-
// Same anti-flicker pattern as the recommend fetch: keep prior data
|
|
66
|
-
// while the refetch is in flight.
|
|
67
|
-
draft.recentTransfer.fetchState = 'In-Progress';
|
|
68
|
-
draft.recentTransfer.error = undefined;
|
|
69
|
-
},
|
|
70
|
-
updateRecentTransfer(draft, action) {
|
|
71
|
-
draft.recentTransfer = {
|
|
72
|
-
fetchState: 'Completed',
|
|
73
|
-
error: undefined,
|
|
74
|
-
data: action.payload.data != null
|
|
75
|
-
? toCashManagementTransfer(action.payload.data)
|
|
76
|
-
: undefined,
|
|
77
|
-
};
|
|
78
|
-
},
|
|
79
|
-
updateRecentTransferFetchStatus(draft, action) {
|
|
80
|
-
draft.recentTransfer = {
|
|
81
|
-
...draft.recentTransfer,
|
|
82
|
-
fetchState: action.payload.fetchState,
|
|
83
|
-
error: action.payload.error,
|
|
84
|
-
};
|
|
85
|
-
},
|
|
86
|
-
clearCashManagementOverview(draft) {
|
|
87
|
-
Object.assign(draft, initialState);
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
export const { fetchCashManagementOverviewPage, fetchCashManagementBanner, fetchCashManagementRecommendation, updateCashManagementRecommendation, updateCashManagementRecommendationFetchStatus, fetchRecentTransfer, updateRecentTransfer, updateRecentTransferFetchStatus, clearCashManagementOverview, } = cashManagementOverview.actions;
|
|
92
|
-
export default cashManagementOverview.reducer;
|