@zeniai/client-epic-state 5.0.84-betaAK3 → 5.0.84-betaAS1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/lib/commonStateTypes/amount.d.ts +0 -1
  2. package/lib/commonStateTypes/amount.js +1 -3
  3. package/lib/commonStateTypes/workingDayHelper.d.ts +0 -9
  4. package/lib/commonStateTypes/workingDayHelper.js +1 -28
  5. package/lib/entity/tenant/clearAllEpic.d.ts +1 -3
  6. package/lib/entity/tenant/clearAllEpic.js +0 -4
  7. package/lib/epic.d.ts +1 -5
  8. package/lib/epic.js +1 -5
  9. package/lib/esm/commonStateTypes/amount.js +0 -1
  10. package/lib/esm/commonStateTypes/workingDayHelper.js +0 -26
  11. package/lib/esm/entity/tenant/clearAllEpic.js +0 -4
  12. package/lib/esm/epic.js +1 -5
  13. package/lib/esm/index.js +3 -8
  14. package/lib/esm/reducer.js +0 -6
  15. package/lib/esm/view/spendManagement/autotransferRules/autoTransferRulesSelector.js +2 -22
  16. package/lib/index.d.ts +6 -15
  17. package/lib/index.js +17 -37
  18. package/lib/reducer.d.ts +0 -6
  19. package/lib/reducer.js +0 -6
  20. package/lib/view/spendManagement/autotransferRules/autoTransferRulesSelector.d.ts +1 -8
  21. package/lib/view/spendManagement/autotransferRules/autoTransferRulesSelector.js +1 -21
  22. package/lib/view/spendManagement/autotransferRules/autoTransferRulesState.d.ts +0 -22
  23. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationState.d.ts +16 -0
  24. package/lib/zeniAPI.d.ts +0 -1
  25. package/package.json +1 -1
  26. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.js +0 -31
  27. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.js +0 -69
  28. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.js +0 -29
  29. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.js +0 -47
  30. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.js +0 -34
  31. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.js +0 -32
  32. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.js +0 -41
  33. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.js +0 -44
  34. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.js +0 -193
  35. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.js +0 -5
  36. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.js +0 -27
  37. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.js +0 -42
  38. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.d.ts +0 -48
  39. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.js +0 -36
  40. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.d.ts +0 -21
  41. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.js +0 -73
  42. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.d.ts +0 -40
  43. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.js +0 -33
  44. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.d.ts +0 -37
  45. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.js +0 -53
  46. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.d.ts +0 -14
  47. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.js +0 -38
  48. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.d.ts +0 -7
  49. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.js +0 -36
  50. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.d.ts +0 -32
  51. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.js +0 -46
  52. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.d.ts +0 -15
  53. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.js +0 -48
  54. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.d.ts +0 -35
  55. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.js +0 -198
  56. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.d.ts +0 -75
  57. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.js +0 -8
  58. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.d.ts +0 -7
  59. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.js +0 -31
  60. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.d.ts +0 -10
  61. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.js +0 -46
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchCashManagementSettingsEpic = void 0;
4
- const rxjs_1 = require("rxjs");
5
- const operators_1 = require("rxjs/operators");
6
- const depositAccountReducer_1 = require("../../../../../entity/depositAccount/depositAccountReducer");
7
- const responsePayload_1 = require("../../../../../responsePayload");
8
- const autoSweepFlowReducer_1 = require("../autoSweepFlowReducer");
9
- /**
10
- * Hits `GET /cash-management/settings` and hydrates the auto-sweep slice
11
- * with the server's existing settings (frequency, minimum buffer, settings
12
- * id). Called from the cash management overview page-fetch epic alongside
13
- * the other top-level fetches.
14
- */
15
- const fetchCashManagementSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(autoSweepFlowReducer_1.fetchCashManagementSettings.match), (0, operators_1.switchMap)(() => {
16
- const endpoint = `${zeniAPI.apiEndPoints.cashManagementAgentBaseUrl}/1.0/cash-management/settings`;
17
- return zeniAPI
18
- .getJSON(endpoint)
19
- .pipe((0, operators_1.mergeMap)((response) => {
20
- if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
21
- return (0, rxjs_1.of)(
22
- // Publish the source deposit account into the shared entity
23
- // bucket so the selector can hydrate the full `FundingAccount`
24
- // from `getDepositAccountByDepositAccountId` rather than the
25
- // auto-sweep slice holding a duplicate copy.
26
- (0, depositAccountReducer_1.updateDepositAccounts)([response.data.source_bank_account]), (0, autoSweepFlowReducer_1.updateCashManagementSettings)({ data: response.data }));
27
- }
28
- return (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateCashManagementSettingsFetchStatus)({
29
- fetchState: 'Error',
30
- error: response.status,
31
- }));
32
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateCashManagementSettingsFetchStatus)({
33
- fetchState: 'Error',
34
- error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch cash management settings REST API call errored out: ' +
35
- (error?.message ?? String(error))),
36
- }))));
37
- }));
38
- exports.fetchCashManagementSettingsEpic = fetchCashManagementSettingsEpic;
@@ -1,7 +0,0 @@
1
- import { ActionsObservable, StateObservable } from 'redux-observable';
2
- import { Observable } from 'rxjs';
3
- import { RootState } from '../../../../../reducer';
4
- import { ZeniAPI } from '../../../../../zeniAPI';
5
- import { saveAutoSweepSettings, updateAutoSweepSettingsFetchStatus } from '../autoSweepFlowReducer';
6
- export type ActionType = ReturnType<typeof saveAutoSweepSettings> | ReturnType<typeof updateAutoSweepSettingsFetchStatus>;
7
- export declare const saveAutoSweepSettingsEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -1,36 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.saveAutoSweepSettingsEpic = void 0;
4
- const rxjs_1 = require("rxjs");
5
- const operators_1 = require("rxjs/operators");
6
- const responsePayload_1 = require("../../../../../responsePayload");
7
- const autoSweepFlowPayload_1 = require("../autoSweepFlowPayload");
8
- const autoSweepFlowReducer_1 = require("../autoSweepFlowReducer");
9
- const saveAutoSweepSettingsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(autoSweepFlowReducer_1.saveAutoSweepSettings.match), (0, operators_1.switchMap)(() => {
10
- const endpoint = `${zeniAPI.apiEndPoints.cashManagementAgentBaseUrl}/1.0/cash-management/settings`;
11
- const { bufferAmount, frequency, memo, settingsId } = state$.value.autoSweepFlowState;
12
- const payload = (0, autoSweepFlowPayload_1.toSaveAutoSweepSettingsBody)({
13
- bufferAmount,
14
- frequency,
15
- memo,
16
- });
17
- // First-time setup (no settings id from the GET yet) → POST a new
18
- // record. Subsequent edits update the existing one via PUT.
19
- const request$ = settingsId == null
20
- ? zeniAPI.postAndGetJSON(endpoint, payload)
21
- : zeniAPI.putAndGetJSON(endpoint, payload);
22
- return request$.pipe((0, operators_1.mergeMap)((response) => {
23
- if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
24
- return (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateAutoSweepSettingsFetchStatus)({ fetchState: 'Completed' }));
25
- }
26
- return (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateAutoSweepSettingsFetchStatus)({
27
- fetchState: 'Error',
28
- error: response?.status,
29
- }));
30
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateAutoSweepSettingsFetchStatus)({
31
- fetchState: 'Error',
32
- error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Save auto-sweep settings REST API call errored out: ' +
33
- (error?.message ?? String(error))),
34
- }))));
35
- }));
36
- exports.saveAutoSweepSettingsEpic = saveAutoSweepSettingsEpic;
@@ -1,32 +0,0 @@
1
- import { ZeniAPIResponse } from '../../../../responsePayload';
2
- import { CashManagementBannerData, CashManagementBankAccountType, CashManagementSubMovementType, UpcomingPaymentEvent, UpcomingPaymentEventAccountType } from './cashManagementOverviewState';
3
- export interface CashAgentEventPayload {
4
- account_id: string;
5
- account_type: UpcomingPaymentEventAccountType;
6
- amount_usd: number;
7
- currency_code: string;
8
- label: string;
9
- payment_date: string;
10
- }
11
- export interface CashAgentMovementPayload {
12
- amount: number;
13
- currency_code: string;
14
- destination_bank_account_id: string | null;
15
- destination_bank_account_type: CashManagementBankAccountType;
16
- reasoning: string;
17
- source_bank_account_id: string | null;
18
- source_bank_account_type: CashManagementBankAccountType;
19
- sub_movement_type: CashManagementSubMovementType;
20
- }
21
- export interface CashAgentMoneyMovementGroupPayload {
22
- movement_type: string;
23
- movements: CashAgentMovementPayload[];
24
- }
25
- export interface CashAgentRecommendPayload {
26
- inflows: CashAgentEventPayload[];
27
- money_movements: CashAgentMoneyMovementGroupPayload[];
28
- outflows: CashAgentEventPayload[];
29
- }
30
- export type CashAgentRecommendResponse = ZeniAPIResponse<CashAgentRecommendPayload>;
31
- export declare const toUpcomingPaymentEvent: (event: CashAgentEventPayload) => UpcomingPaymentEvent;
32
- export declare const toCashManagementBannerData: (payload: CashAgentRecommendPayload) => CashManagementBannerData;
@@ -1,46 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toCashManagementBannerData = exports.toUpcomingPaymentEvent = void 0;
4
- const amount_1 = require("../../../../commonStateTypes/amount");
5
- const zeniDayJS_1 = require("../../../../zeniDayJS");
6
- // ---------------------------------------------------------------------------
7
- // Converters
8
- // ---------------------------------------------------------------------------
9
- // The cash agent payload reports `currency_code` only; the v1 surface is
10
- // USD-only, so we pair it with the canonical `$` symbol here. If the agent
11
- // grows multi-currency support, this is the single place to widen.
12
- const CASH_AGENT_CURRENCY_SYMBOL = '$';
13
- const toUpcomingPaymentEvent = (event) => ({
14
- accountId: event.account_id,
15
- accountType: event.account_type,
16
- amount: (0, amount_1.toAmount)(event.amount_usd, event.currency_code, CASH_AGENT_CURRENCY_SYMBOL),
17
- label: event.label,
18
- paymentDate: (0, zeniDayJS_1.date)(event.payment_date),
19
- });
20
- exports.toUpcomingPaymentEvent = toUpcomingPaymentEvent;
21
- /**
22
- * The agent reports a `null` account id whenever the "account" in question is
23
- * a singleton inferred from the account type (today: the treasury account —
24
- * there's only one per company, so the type alone identifies it). Callers
25
- * already branch on `*BankAccountType`, so collapsing the id to `""` keeps the
26
- * state type a plain `ID` (string) without losing information.
27
- */
28
- const toCashManagementMovement = (payload) => ({
29
- amount: (0, amount_1.toAmount)(payload.amount, payload.currency_code, CASH_AGENT_CURRENCY_SYMBOL),
30
- destinationBankAccountId: payload.destination_bank_account_id ?? '',
31
- destinationBankAccountType: payload.destination_bank_account_type,
32
- reasoning: payload.reasoning,
33
- sourceBankAccountId: payload.source_bank_account_id ?? '',
34
- sourceBankAccountType: payload.source_bank_account_type,
35
- subMovementType: payload.sub_movement_type,
36
- });
37
- const toCashManagementMoneyMovementGroup = (payload) => ({
38
- movements: payload.movements.map(toCashManagementMovement),
39
- movementType: payload.movement_type,
40
- });
41
- const toCashManagementBannerData = (payload) => ({
42
- inflows: payload.inflows.map(exports.toUpcomingPaymentEvent),
43
- moneyMovements: payload.money_movements.map(toCashManagementMoneyMovementGroup),
44
- outflows: payload.outflows.map(exports.toUpcomingPaymentEvent),
45
- });
46
- exports.toCashManagementBannerData = toCashManagementBannerData;
@@ -1,15 +0,0 @@
1
- import { FetchState } from '../../../../commonStateTypes/common';
2
- import { ZeniAPIStatus } from '../../../../responsePayload';
3
- import { CashAgentRecommendPayload } from './cashManagementOverviewPayload';
4
- import { CashManagementOverviewState } from './cashManagementOverviewState';
5
- export declare const initialState: CashManagementOverviewState;
6
- export declare const fetchCashManagementOverviewPage: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[cacheOverride: boolean], {
7
- cacheOverride: boolean;
8
- }, "cashManagementOverview/fetchCashManagementOverviewPage", never, never>, fetchCashManagementBanner: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"cashManagementOverview/fetchCashManagementBanner">, updateCashManagementBanner: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
9
- data: CashAgentRecommendPayload;
10
- }, "cashManagementOverview/updateCashManagementBanner">, updateCashManagementBannerFetchStatus: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
11
- fetchState: FetchState;
12
- error?: ZeniAPIStatus;
13
- }, "cashManagementOverview/updateCashManagementBannerFetchStatus">, clearCashManagementOverview: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"cashManagementOverview/clearCashManagementOverview">;
14
- declare const _default: import("redux").Reducer<CashManagementOverviewState>;
15
- export default _default;
@@ -1,48 +0,0 @@
1
- "use strict";
2
- var _a;
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.clearCashManagementOverview = exports.updateCashManagementBannerFetchStatus = exports.updateCashManagementBanner = exports.fetchCashManagementBanner = exports.fetchCashManagementOverviewPage = exports.initialState = void 0;
5
- const toolkit_1 = require("@reduxjs/toolkit");
6
- const cashManagementOverviewPayload_1 = require("./cashManagementOverviewPayload");
7
- const cashManagementOverviewState_1 = require("./cashManagementOverviewState");
8
- exports.initialState = {
9
- banner: cashManagementOverviewState_1.initialCashManagementBannerState,
10
- };
11
- const cashManagementOverview = (0, toolkit_1.createSlice)({
12
- name: 'cashManagementOverview',
13
- initialState: exports.initialState,
14
- reducers: {
15
- fetchCashManagementOverviewPage: {
16
- reducer() { },
17
- prepare(cacheOverride) {
18
- return { payload: { cacheOverride } };
19
- },
20
- },
21
- fetchCashManagementBanner(draft) {
22
- // Keep `draft.banner.data` so the projection chart renders the last
23
- // good payload while the refetch is in flight, instead of flickering
24
- // to the empty/skeleton state on every page revisit.
25
- draft.banner.fetchState = 'In-Progress';
26
- draft.banner.error = undefined;
27
- },
28
- updateCashManagementBanner(draft, action) {
29
- draft.banner = {
30
- fetchState: 'Completed',
31
- error: undefined,
32
- data: (0, cashManagementOverviewPayload_1.toCashManagementBannerData)(action.payload.data),
33
- };
34
- },
35
- updateCashManagementBannerFetchStatus(draft, action) {
36
- draft.banner = {
37
- ...draft.banner,
38
- fetchState: action.payload.fetchState,
39
- error: action.payload.error,
40
- };
41
- },
42
- clearCashManagementOverview(draft) {
43
- Object.assign(draft, exports.initialState);
44
- },
45
- },
46
- });
47
- _a = cashManagementOverview.actions, exports.fetchCashManagementOverviewPage = _a.fetchCashManagementOverviewPage, exports.fetchCashManagementBanner = _a.fetchCashManagementBanner, exports.updateCashManagementBanner = _a.updateCashManagementBanner, exports.updateCashManagementBannerFetchStatus = _a.updateCashManagementBannerFetchStatus, exports.clearCashManagementOverview = _a.clearCashManagementOverview;
48
- exports.default = cashManagementOverview.reducer;
@@ -1,35 +0,0 @@
1
- import { Amount } from '../../../../commonStateTypes/amount';
2
- import { ID } from '../../../../commonStateTypes/common';
3
- import { SelectorView } from '../../../../commonStateTypes/viewAndReport/viewAndReport';
4
- import { RootState } from '../../../../reducer';
5
- import { CashManagementMovement, UpcomingPaymentEvent } from './cashManagementOverviewState';
6
- export interface CashManagementOverviewBannerSelectorView extends SelectorView, CashManagementMovement {
7
- cashManagementSettingsId?: ID;
8
- }
9
- export interface CashProjectionPoint {
10
- balance: Amount;
11
- /** Pre-formatted display label (e.g. `"Today"`, `"May 27"`). */
12
- date: string;
13
- isInflow?: boolean;
14
- isOutflow?: boolean;
15
- }
16
- export interface CashManagementOverviewSelectorView extends SelectorView {
17
- banner: CashManagementOverviewBannerSelectorView;
18
- cashBalance: Amount;
19
- /** Net cash flow over the horizon — `totalInFlow` minus `totalOutFlow`.
20
- * Positive = surplus, negative = burn. */
21
- cashflow: Amount;
22
- inflowEvents: UpcomingPaymentEvent[];
23
- outflowEvents: UpcomingPaymentEvent[];
24
- /** Running cash-balance projection seeded by `cashBalance` and stepped by
25
- * the inflow / outflow events. */
26
- projectionData: CashProjectionPoint[];
27
- totalCash: Amount;
28
- /** Sum of all `inflowEvents[].amount` values. */
29
- totalInFlow: Amount;
30
- /** Sum of all `outflowEvents[].amount` values. */
31
- totalOutFlow: Amount;
32
- treasuryBalance: Amount;
33
- }
34
- export declare const getCashManagementOverviewBanner: (state: RootState) => CashManagementOverviewBannerSelectorView;
35
- export declare const getCashManagementOverview: (state: RootState) => CashManagementOverviewSelectorView;
@@ -1,198 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getCashManagementOverview = exports.getCashManagementOverviewBanner = void 0;
4
- const amount_1 = require("../../../../commonStateTypes/amount");
5
- const reduceFetchState_1 = require("../../../../commonStateTypes/reduceFetchState");
6
- /**
7
- * Default account type used when the recommend payload has no movement to
8
- * expose yet (e.g. before the first fetch resolves). Callers that care about
9
- * the movement should also gate on `fetchState === 'Completed'`.
10
- */
11
- const DEFAULT_BANK_ACCOUNT_TYPE = 'deposit_account';
12
- const DEFAULT_SUB_MOVEMENT_TYPE = 'push';
13
- const getCashManagementOverviewBanner = (state) => {
14
- const { banner } = state.cashManagementOverviewState;
15
- const autoSweep = state.autoSweepFlowState;
16
- // The banner today surfaces a single recommended movement (the first one
17
- // returned by the agent). When the agent returns multiple groups/movements
18
- // we'll need to broaden this — for now consumers only render one.
19
- const movement = banner.data?.moneyMovements[0]?.movements[0];
20
- const aggregate = (0, reduceFetchState_1.reduceAllFetchState)([
21
- { fetchState: banner.fetchState, error: banner.error },
22
- { fetchState: autoSweep.fetchState, error: autoSweep.error },
23
- ]);
24
- return {
25
- fetchState: aggregate.fetchState,
26
- error: aggregate.error,
27
- amount: movement?.amount ?? (0, amount_1.zeroAmount)(),
28
- cashManagementSettingsId: autoSweep.settingsId,
29
- destinationBankAccountId: movement?.destinationBankAccountId ?? '',
30
- destinationBankAccountType: movement?.destinationBankAccountType ?? DEFAULT_BANK_ACCOUNT_TYPE,
31
- reasoning: movement?.reasoning ?? '',
32
- sourceBankAccountId: movement?.sourceBankAccountId ?? '',
33
- sourceBankAccountType: movement?.sourceBankAccountType ?? DEFAULT_BANK_ACCOUNT_TYPE,
34
- subMovementType: movement?.subMovementType ?? DEFAULT_SUB_MOVEMENT_TYPE,
35
- version: 0,
36
- };
37
- };
38
- exports.getCashManagementOverviewBanner = getCashManagementOverviewBanner;
39
- const getCashManagementOverview = (state) => {
40
- const { cashManagementOverviewState, depositAccountListState, depositAccountState, paymentAccountListState, paymentAccountState, treasuryDetailState, } = state;
41
- const aggregate = (0, reduceFetchState_1.reduceAllFetchState)([
42
- {
43
- fetchState: paymentAccountListState.fetchState,
44
- error: paymentAccountListState.error,
45
- },
46
- {
47
- fetchState: depositAccountListState.fetchState,
48
- error: depositAccountListState.error,
49
- },
50
- {
51
- fetchState: treasuryDetailState.fetchState,
52
- error: treasuryDetailState.error,
53
- },
54
- {
55
- fetchState: cashManagementOverviewState.banner.fetchState,
56
- error: cashManagementOverviewState.banner.error,
57
- },
58
- {
59
- fetchState: state.autoSweepFlowState.fetchState,
60
- error: state.autoSweepFlowState.error,
61
- },
62
- ]);
63
- const treasuryBalance = treasuryDetailState.accountSummary?.totalBalance ?? (0, amount_1.zeroAmount)();
64
- const cashBalance = sumCashBalances(paymentAccountListState.paymentAccountIds, paymentAccountState, depositAccountListState.accountIds, depositAccountState);
65
- const totalCash = addAmounts(treasuryBalance, cashBalance);
66
- const bannerData = cashManagementOverviewState.banner.data;
67
- const inflowEvents = bannerData?.inflows ?? [];
68
- const outflowEvents = bannerData?.outflows ?? [];
69
- const totalInFlow = sumEventAmounts(inflowEvents);
70
- const totalOutFlow = sumEventAmounts(outflowEvents);
71
- const cashflow = subtractAmounts(totalInFlow, totalOutFlow);
72
- const projectionData = buildProjectionData(cashBalance, inflowEvents, outflowEvents);
73
- return {
74
- banner: (0, exports.getCashManagementOverviewBanner)(state),
75
- cashBalance,
76
- cashflow,
77
- inflowEvents,
78
- outflowEvents,
79
- projectionData,
80
- totalCash,
81
- totalInFlow,
82
- totalOutFlow,
83
- treasuryBalance,
84
- fetchState: aggregate.fetchState,
85
- error: aggregate.error,
86
- version: 0,
87
- };
88
- };
89
- exports.getCashManagementOverview = getCashManagementOverview;
90
- /**
91
- * Walks the inflow / outflow events in chronological order, stepping the
92
- * running balance from today's `cashBalance`. Emits a point per event so the
93
- * chart can render colored markers at each cash event. Events with the same
94
- * payment date are kept as separate steps (preserves the marker count even
95
- * if Recharts overlays them at the same X position).
96
- */
97
- const buildProjectionData = (cashBalance, inflowEvents, outflowEvents) => {
98
- const events = [
99
- ...inflowEvents.map((e) => ({
100
- amount: e.amount,
101
- date: e.paymentDate,
102
- isInflow: true,
103
- })),
104
- ...outflowEvents.map((e) => ({
105
- amount: e.amount,
106
- date: e.paymentDate,
107
- isInflow: false,
108
- })),
109
- ].sort((a, b) => {
110
- const diff = a.date.valueOf() - b.date.valueOf();
111
- if (diff !== 0) {
112
- return diff;
113
- }
114
- // Same-day tie-breaker: apply outflows before inflows so the projection
115
- // shows the worst-case low first, then the recovery — matches the
116
- // "show me the dip" framing on the cash management overview.
117
- if (a.isInflow === b.isInflow) {
118
- return 0;
119
- }
120
- return a.isInflow ? 1 : -1;
121
- });
122
- let balance = cashBalance;
123
- const points = [{ balance, date: 'Today' }];
124
- events.forEach((event) => {
125
- balance = event.isInflow
126
- ? addAmounts(balance, event.amount)
127
- : subtractAmounts(balance, event.amount);
128
- points.push({
129
- balance,
130
- date: event.date.format('MMM D'),
131
- isInflow: event.isInflow ? true : undefined,
132
- isOutflow: event.isInflow ? undefined : true,
133
- });
134
- });
135
- return points;
136
- };
137
- const sumEventAmounts = (events) => events.reduce((acc, event) => addAmounts(acc, event.amount), (0, amount_1.zeroAmount)());
138
- /**
139
- * Subtracts `b` from `a`, sharing the currency-match guard with `addAmounts`.
140
- * Used to compute net cash flow (`inflow - outflow`).
141
- */
142
- const subtractAmounts = (a, b) => {
143
- if (isZeroAmount(b)) {
144
- return { ...a };
145
- }
146
- if (isZeroAmount(a)) {
147
- return { ...b, amount: -b.amount };
148
- }
149
- if (a.currencyCode !== b.currencyCode ||
150
- a.currencySymbol !== b.currencySymbol) {
151
- console.warn(`cashManagementOverview: skipping balance with mismatched currency. Expected ${a.currencyCode} (${a.currencySymbol}), got ${b.currencyCode} (${b.currencySymbol}).`);
152
- return a;
153
- }
154
- return {
155
- amount: a.amount - b.amount,
156
- currencyCode: a.currencyCode,
157
- currencySymbol: a.currencySymbol,
158
- };
159
- };
160
- const isZeroAmount = (a) => a.amount === 0 && a.currencyCode === 'USD' && a.currencySymbol === '$';
161
- /**
162
- * Adds two Amounts. Currencies must match (the seeded zeroAmount() counts as
163
- * "no currency yet" and adopts `b`'s currency). Mismatches return `a`
164
- * unchanged and warn — mixing currencies in a total is a bug, not silent
165
- * conversion.
166
- */
167
- const addAmounts = (a, b) => {
168
- if (isZeroAmount(a)) {
169
- return { ...b };
170
- }
171
- if (a.currencyCode !== b.currencyCode ||
172
- a.currencySymbol !== b.currencySymbol) {
173
- console.warn(`cashManagementOverview: skipping balance with mismatched currency. Expected ${a.currencyCode} (${a.currencySymbol}), got ${b.currencyCode} (${b.currencySymbol}).`);
174
- return a;
175
- }
176
- return {
177
- amount: a.amount + b.amount,
178
- currencyCode: a.currencyCode,
179
- currencySymbol: a.currencySymbol,
180
- };
181
- };
182
- const sumCashBalances = (paymentAccountIds, paymentAccountState, depositAccountIds, depositAccountState) => {
183
- let total = (0, amount_1.zeroAmount)();
184
- paymentAccountIds.forEach((id) => {
185
- const balance = paymentAccountState.paymentAccountByID[id]?.balances
186
- ?.available;
187
- if (balance != null) {
188
- total = addAmounts(total, balance);
189
- }
190
- });
191
- depositAccountIds.forEach((id) => {
192
- const balance = depositAccountState.depositAccountByID[id]?.accountBalance?.available;
193
- if (balance != null) {
194
- total = addAmounts(total, balance);
195
- }
196
- });
197
- return total;
198
- };
@@ -1,75 +0,0 @@
1
- import { Amount } from '../../../../commonStateTypes/amount';
2
- import { FetchStateAndError, ID } from '../../../../commonStateTypes/common';
3
- import { ZeniDate } from '../../../../zeniDayJS';
4
- /**
5
- * Bank account types the cash agent reports against. Kept as a string union so
6
- * the consumer can branch on it; new values from the agent will widen the type
7
- * via TypeScript inference and won't break callers handling the known set.
8
- */
9
- export type CashManagementBankAccountType = 'deposit_account' | 'treasury_account';
10
- /** Direction of a single sweep movement. */
11
- export type CashManagementSubMovementType = 'push' | 'pull';
12
- /**
13
- * Bank account types reported on upcoming-payment events. Wider than
14
- * `CashManagementBankAccountType` because the cash agent can attribute
15
- * inflows / outflows to payment accounts too.
16
- */
17
- export type UpcomingPaymentEventAccountType = 'deposit_account' | 'treasury_account' | 'payment_account';
18
- /**
19
- * One projected inflow / outflow returned by the cash agent. Stored on the
20
- * banner state directly (no separate entity bucket) because these events are
21
- * only meaningful in the context of a banner fetch — they're not addressable
22
- * by id from anywhere else.
23
- */
24
- export interface UpcomingPaymentEvent {
25
- accountId: ID;
26
- accountType: UpcomingPaymentEventAccountType;
27
- amount: Amount;
28
- label: string;
29
- paymentDate: ZeniDate;
30
- }
31
- /**
32
- * A single recommended money movement returned by the cash agent (e.g.
33
- * "sweep $99,100 from checking to treasury"). Mirrors one element of the
34
- * `money_movements[].movements` array in the recommend response, with field
35
- * names camelCased and `amount`/`currency_code` collapsed into an `Amount`.
36
- */
37
- export interface CashManagementMovement {
38
- amount: Amount;
39
- destinationBankAccountId: ID;
40
- destinationBankAccountType: CashManagementBankAccountType;
41
- reasoning: string;
42
- sourceBankAccountId: ID;
43
- sourceBankAccountType: CashManagementBankAccountType;
44
- subMovementType: CashManagementSubMovementType;
45
- }
46
- /**
47
- * A group of related recommended movements (e.g. all `treasury` sweeps).
48
- * `movementType` is left as `string` because the agent may grow new groups
49
- * over time; today the only known value is `'treasury'`.
50
- */
51
- export interface CashManagementMoneyMovementGroup {
52
- movements: CashManagementMovement[];
53
- movementType: string;
54
- }
55
- /**
56
- * Banner-side data derived from the cash agent's recommend endpoint.
57
- * `inflows` and `outflows` carry the full event objects; the selector reads
58
- * them directly without an entity-bucket lookup.
59
- */
60
- export interface CashManagementBannerData {
61
- inflows: UpcomingPaymentEvent[];
62
- moneyMovements: CashManagementMoneyMovementGroup[];
63
- outflows: UpcomingPaymentEvent[];
64
- }
65
- export interface CashManagementBannerState extends FetchStateAndError {
66
- data?: CashManagementBannerData;
67
- }
68
- /**
69
- * The slice's effective fetch state is the banner's — consumers should query
70
- * `banner.fetchState` rather than a duplicate top-level field.
71
- */
72
- export interface CashManagementOverviewState {
73
- banner: CashManagementBannerState;
74
- }
75
- export declare const initialCashManagementBannerState: CashManagementBannerState;
@@ -1,8 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initialCashManagementBannerState = void 0;
4
- exports.initialCashManagementBannerState = {
5
- fetchState: 'Not-Started',
6
- error: undefined,
7
- data: undefined,
8
- };
@@ -1,7 +0,0 @@
1
- import { ActionsObservable, StateObservable } from 'redux-observable';
2
- import { Observable } from 'rxjs';
3
- import { RootState } from '../../../../../reducer';
4
- import { ZeniAPI } from '../../../../../zeniAPI';
5
- import { fetchCashManagementBanner, updateCashManagementBanner, updateCashManagementBannerFetchStatus } from '../cashManagementOverviewReducer';
6
- export type ActionType = ReturnType<typeof fetchCashManagementBanner> | ReturnType<typeof updateCashManagementBanner> | ReturnType<typeof updateCashManagementBannerFetchStatus>;
7
- export declare const fetchCashManagementBannerEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -1,31 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchCashManagementBannerEpic = void 0;
4
- const rxjs_1 = require("rxjs");
5
- const operators_1 = require("rxjs/operators");
6
- const responsePayload_1 = require("../../../../../responsePayload");
7
- const cashManagementOverviewReducer_1 = require("../cashManagementOverviewReducer");
8
- /**
9
- * Hits the cash agent's recommend endpoint and stores the full response on
10
- * the banner state — `inflows[]`, `outflows[]`, and `money_movements[]` all
11
- * live there, so consumers can read them directly without an entity-bucket
12
- * lookup.
13
- */
14
- const DEFAULT_RECOMMEND_HORIZON_DAYS = 30;
15
- const fetchCashManagementBannerEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(cashManagementOverviewReducer_1.fetchCashManagementBanner.match), (0, operators_1.switchMap)(() => {
16
- const endpoint = `${zeniAPI.apiEndPoints.cashManagementAgentBaseUrl}/1.0/cash-agent/recommend?horizon_days=${DEFAULT_RECOMMEND_HORIZON_DAYS}`;
17
- return zeniAPI.getJSON(endpoint).pipe((0, operators_1.mergeMap)((response) => {
18
- if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
19
- return (0, rxjs_1.of)((0, cashManagementOverviewReducer_1.updateCashManagementBanner)({ data: response.data }));
20
- }
21
- return (0, rxjs_1.of)((0, cashManagementOverviewReducer_1.updateCashManagementBannerFetchStatus)({
22
- fetchState: 'Error',
23
- error: response.status,
24
- }));
25
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, cashManagementOverviewReducer_1.updateCashManagementBannerFetchStatus)({
26
- fetchState: 'Error',
27
- error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch cash management banner REST API call errored out: ' +
28
- (error?.message ?? String(error))),
29
- }))));
30
- }));
31
- exports.fetchCashManagementBannerEpic = fetchCashManagementBannerEpic;
@@ -1,10 +0,0 @@
1
- import { ActionsObservable, StateObservable } from 'redux-observable';
2
- import { Observable } from 'rxjs';
3
- import { RootState } from '../../../../../reducer';
4
- import { fetchAutoTransferRules } from '../../../autotransferRules/autoTransferRulesReducer';
5
- import { fetchCashManagementSettings } from '../../autoSweepFlow/autoSweepFlowReducer';
6
- import { fetchTreasuryOverviewDetail } from '../../../treasury/treasuryList/treasuryDetailReducer';
7
- import { fetchZeniAccountList } from '../../../zeniAccounts/zeniAccountList/zeniAccountListReducer';
8
- import { fetchCashManagementBanner, fetchCashManagementOverviewPage } from '../cashManagementOverviewReducer';
9
- export type ActionType = ReturnType<typeof fetchCashManagementOverviewPage> | ReturnType<typeof fetchTreasuryOverviewDetail> | ReturnType<typeof fetchZeniAccountList> | ReturnType<typeof fetchCashManagementBanner> | ReturnType<typeof fetchCashManagementSettings> | ReturnType<typeof fetchAutoTransferRules>;
10
- export declare const fetchCashManagementOverviewPageEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => Observable<ActionType>;
@@ -1,46 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchCashManagementOverviewPageEpic = void 0;
4
- const rxjs_1 = require("rxjs");
5
- const operators_1 = require("rxjs/operators");
6
- const autoTransferRulesReducer_1 = require("../../../autotransferRules/autoTransferRulesReducer");
7
- const autoSweepFlowReducer_1 = require("../../autoSweepFlow/autoSweepFlowReducer");
8
- const treasuryDetailReducer_1 = require("../../../treasury/treasuryList/treasuryDetailReducer");
9
- const zeniAccountListReducer_1 = require("../../../zeniAccounts/zeniAccountList/zeniAccountListReducer");
10
- const cashManagementOverviewReducer_1 = require("../cashManagementOverviewReducer");
11
- const fetchCashManagementOverviewPageEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(cashManagementOverviewReducer_1.fetchCashManagementOverviewPage.match), (0, operators_1.mergeMap)((action) => {
12
- const { cacheOverride } = action.payload;
13
- const state = state$.value;
14
- const pageActions = [];
15
- if (cacheOverride === true) {
16
- pageActions.push((0, treasuryDetailReducer_1.fetchTreasuryOverviewDetail)(true), (0, zeniAccountListReducer_1.fetchZeniAccountList)(true), (0, cashManagementOverviewReducer_1.fetchCashManagementBanner)(), (0, autoSweepFlowReducer_1.fetchCashManagementSettings)(), (0, autoTransferRulesReducer_1.fetchAutoTransferRules)(true));
17
- }
18
- else {
19
- const treasuryDetailState = state.treasuryDetailState;
20
- if (treasuryDetailState.hasValidState() === false &&
21
- treasuryDetailState.fetchState !== 'In-Progress') {
22
- pageActions.push((0, treasuryDetailReducer_1.fetchTreasuryOverviewDetail)(false));
23
- }
24
- // zeniAccountListState has no top-level fetchState to dedup against
25
- // (only `newCheckingAccount.fetchState`), and the downstream epic is
26
- // cheap. Always re-dispatch so the summary stays fresh on page entry.
27
- pageActions.push((0, zeniAccountListReducer_1.fetchZeniAccountList)(false));
28
- const banner = state.cashManagementOverviewState.banner;
29
- if (banner.fetchState !== 'Completed' &&
30
- banner.fetchState !== 'In-Progress') {
31
- pageActions.push((0, cashManagementOverviewReducer_1.fetchCashManagementBanner)());
32
- }
33
- const autoSweep = state.autoSweepFlowState;
34
- if (autoSweep.fetchState !== 'Completed' &&
35
- autoSweep.fetchState !== 'In-Progress') {
36
- pageActions.push((0, autoSweepFlowReducer_1.fetchCashManagementSettings)());
37
- }
38
- const autoTransferRules = state.autotransferRulesState;
39
- if (autoTransferRules.fetchState !== 'Completed' &&
40
- autoTransferRules.fetchState !== 'In-Progress') {
41
- pageActions.push((0, autoTransferRulesReducer_1.fetchAutoTransferRules)(false));
42
- }
43
- }
44
- return (0, rxjs_1.concat)((0, rxjs_1.from)(pageActions));
45
- }));
46
- exports.fetchCashManagementOverviewPageEpic = fetchCashManagementOverviewPageEpic;