@zeniai/client-epic-state 5.0.81 → 5.0.82-betaAK1

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 (118) hide show
  1. package/lib/commonStateTypes/amount.d.ts +2 -1
  2. package/lib/commonStateTypes/amount.js +5 -2
  3. package/lib/commonStateTypes/viewAndReport/viewAndReport.d.ts +2 -2
  4. package/lib/commonStateTypes/viewAndReport/viewAndReport.js +2 -0
  5. package/lib/commonStateTypes/workingDayHelper.d.ts +11 -0
  6. package/lib/commonStateTypes/workingDayHelper.js +31 -1
  7. package/lib/entity/account/accountSelector.d.ts +9 -0
  8. package/lib/entity/account/accountSelector.js +14 -1
  9. package/lib/entity/account/accountState.d.ts +1 -1
  10. package/lib/entity/accountGroup/accountGroupState.d.ts +1 -1
  11. package/lib/entity/class/classReducer.d.ts +4 -4
  12. package/lib/entity/class/classState.d.ts +1 -1
  13. package/lib/entity/forecast/forecastState.d.ts +1 -1
  14. package/lib/entity/sectionAccountsView/sectionAccountsView.d.ts +1 -1
  15. package/lib/entity/sectionClassesViewV2/sectionClassesView.d.ts +1 -1
  16. package/lib/entity/sectionClassesViewV2/sectionClassesViewReducer.d.ts +2 -2
  17. package/lib/entity/sectionProjectView/sectionProjectView.d.ts +1 -1
  18. package/lib/entity/sectionProjectView/sectionProjectViewReducer.d.ts +2 -2
  19. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  20. package/lib/entity/snackbar/snackbarTypes.js +1 -0
  21. package/lib/entity/tenant/clearAllEpic.d.ts +2 -1
  22. package/lib/entity/tenant/clearAllEpic.js +2 -0
  23. package/lib/entity/transaction/payloadTypes/transactionPayload.d.ts +4 -0
  24. package/lib/entity/transaction/payloadTypes/transactionPayload.js +18 -10
  25. package/lib/entity/transaction/stateTypes/transaction.d.ts +3 -0
  26. package/lib/epic.d.ts +7 -1
  27. package/lib/epic.js +7 -1
  28. package/lib/esm/commonStateTypes/amount.js +3 -1
  29. package/lib/esm/commonStateTypes/viewAndReport/viewAndReport.js +2 -0
  30. package/lib/esm/commonStateTypes/workingDayHelper.js +29 -0
  31. package/lib/esm/entity/account/accountSelector.js +11 -0
  32. package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
  33. package/lib/esm/entity/tenant/clearAllEpic.js +2 -0
  34. package/lib/esm/entity/transaction/payloadTypes/transactionPayload.js +18 -10
  35. package/lib/esm/epic.js +7 -1
  36. package/lib/esm/index.js +12 -6
  37. package/lib/esm/reducer.js +9 -0
  38. package/lib/esm/view/createTransferEntry/createTransferEntryReducer.js +82 -0
  39. package/lib/esm/view/createTransferEntry/createTransferEntrySelector.js +64 -0
  40. package/lib/esm/view/createTransferEntry/createTransferEntryState.js +17 -0
  41. package/lib/esm/view/createTransferEntry/epics/createTransferEntryEpic.js +130 -0
  42. package/lib/esm/view/createTransferEntry/epics/fetchTransferAccountsEpic.js +36 -0
  43. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +13 -1
  44. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +9 -1
  45. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.js +24 -0
  46. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.js +55 -0
  47. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.js +15 -0
  48. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.js +45 -0
  49. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.js +28 -0
  50. package/lib/esm/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.js +27 -0
  51. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.js +37 -0
  52. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.js +49 -0
  53. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.js +179 -0
  54. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.js +5 -0
  55. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.js +28 -0
  56. package/lib/esm/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.js +39 -0
  57. package/lib/esm/view/transactionDetail/transactionDetailSelector.js +6 -1
  58. package/lib/index.d.ts +15 -6
  59. package/lib/index.js +62 -33
  60. package/lib/reducer.d.ts +9 -0
  61. package/lib/reducer.js +9 -0
  62. package/lib/view/auditReportView/auditReportViewState.d.ts +1 -1
  63. package/lib/view/billPayCard/billPayCardSelector.d.ts +1 -1
  64. package/lib/view/cardBalance/cardBalanceSelector.d.ts +1 -1
  65. package/lib/view/cashBalance/cashBalanceSelector.d.ts +1 -1
  66. package/lib/view/cashInCashOut/cashInCashOutSelector.d.ts +1 -1
  67. package/lib/view/cashPosition/cashPositionSelector.d.ts +1 -1
  68. package/lib/view/createTransferEntry/createTransferEntryReducer.d.ts +32 -0
  69. package/lib/view/createTransferEntry/createTransferEntryReducer.js +86 -0
  70. package/lib/view/createTransferEntry/createTransferEntrySelector.d.ts +39 -0
  71. package/lib/view/createTransferEntry/createTransferEntrySelector.js +69 -0
  72. package/lib/view/createTransferEntry/createTransferEntryState.d.ts +30 -0
  73. package/lib/view/createTransferEntry/createTransferEntryState.js +20 -0
  74. package/lib/view/createTransferEntry/epics/createTransferEntryEpic.d.ts +11 -0
  75. package/lib/view/createTransferEntry/epics/createTransferEntryEpic.js +134 -0
  76. package/lib/view/createTransferEntry/epics/fetchTransferAccountsEpic.d.ts +14 -0
  77. package/lib/view/createTransferEntry/epics/fetchTransferAccountsEpic.js +40 -0
  78. package/lib/view/dashboard/dashboardReducer.d.ts +2 -2
  79. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  80. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +3 -1
  81. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +14 -2
  82. package/lib/view/expenseAutomationView/selectorTypes/transactionsViewSelectorTypes.d.ts +4 -1
  83. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.d.ts +1 -0
  84. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +11 -2
  85. package/lib/view/financeStatement/financeStatementReducer.d.ts +1 -1
  86. package/lib/view/globalMerchantView/globalMerchantViewReducer.d.ts +2 -2
  87. package/lib/view/reimbursementCard/reimbursementCardSelector.d.ts +1 -1
  88. package/lib/view/reportsResync/reportsResyncReducer.d.ts +2 -2
  89. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.d.ts +52 -0
  90. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowPayload.js +29 -0
  91. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.d.ts +21 -0
  92. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowReducer.js +59 -0
  93. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.d.ts +16 -0
  94. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowSelector.js +19 -0
  95. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.d.ts +44 -0
  96. package/lib/view/spendManagement/cashManagement/autoSweepFlow/autoSweepFlowState.js +51 -0
  97. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.d.ts +16 -0
  98. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/fetchCashManagementSettingsEpic.js +32 -0
  99. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.d.ts +14 -0
  100. package/lib/view/spendManagement/cashManagement/autoSweepFlow/epics/saveAutoSweepSettingsEpic.js +31 -0
  101. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.d.ts +32 -0
  102. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewPayload.js +42 -0
  103. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.d.ts +15 -0
  104. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewReducer.js +53 -0
  105. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.d.ts +41 -0
  106. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewSelector.js +184 -0
  107. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.d.ts +71 -0
  108. package/lib/view/spendManagement/cashManagement/cashManagementOverview/cashManagementOverviewState.js +8 -0
  109. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.d.ts +16 -0
  110. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementBannerEpic.js +32 -0
  111. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.d.ts +10 -0
  112. package/lib/view/spendManagement/cashManagement/cashManagementOverview/epics/fetchCashManagementOverviewPageEpic.js +43 -0
  113. package/lib/view/tasksCard/tasksCardSelector.d.ts +1 -1
  114. package/lib/view/topEx/topExSelector.d.ts +1 -1
  115. package/lib/view/transactionDetail/transactionDetailPayload.d.ts +1 -1
  116. package/lib/view/transactionDetail/transactionDetailSelector.d.ts +6 -1
  117. package/lib/view/transactionDetail/transactionDetailSelector.js +6 -1
  118. package/package.json +34 -62
@@ -0,0 +1,44 @@
1
+ import { Amount } from '../../../../commonStateTypes/amount';
2
+ import { FetchStateAndError, ID } from '../../../../commonStateTypes/common';
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 declare const ALL_AUTO_SWEEP_FREQUENCIES: readonly ["daily", "weekly", "biweekly", "monthly"];
9
+ export declare const toAutoSweepFrequency: (v?: string) => "weekly" | "biweekly" | "monthly" | "daily";
10
+ export type AutoSweepFrequency = NonNullable<ReturnType<typeof toAutoSweepFrequency>>;
11
+ /**
12
+ * Risk presets the auto-sweep setup form exposes. Each level maps to a
13
+ * canonical minimum-buffer amount (USD). Selecting a level in the UI is
14
+ * shorthand for choosing that buffer.
15
+ */
16
+ export declare const ALL_AUTO_SWEEP_RISK_LEVELS: readonly ["low", "moderate", "high"];
17
+ export declare const toAutoSweepRiskLevel: (v?: string) => "high" | "low" | "moderate";
18
+ export type RiskLevel = NonNullable<ReturnType<typeof toAutoSweepRiskLevel>>;
19
+ export declare const RISK_BUFFER_AMOUNT: Record<RiskLevel, number>;
20
+ /**
21
+ * Maps a buffer amount back onto the closest preset risk level. Falls back
22
+ * to `'moderate'` when the amount doesn't match a known preset (e.g. the
23
+ * server returned a custom value). The dropdown in `<AutoSweepSetupPage>`
24
+ * uses this so it can pre-select the user's existing band on edit.
25
+ */
26
+ export declare const bufferAmountToRisk: (amount: number) => RiskLevel;
27
+ /**
28
+ * Auto-sweep configuration state.
29
+ *
30
+ * `fetchState` / `error` (inherited from `FetchStateAndError`) track the
31
+ * GET `/cash-management/settings` fetch. `saveStatus` tracks the PUT save
32
+ * separately so the two flows don't stomp on each other's status.
33
+ *
34
+ * `settingsId` is the server-issued id (nullable on the wire — undefined
35
+ * here when the agent has no settings record yet).
36
+ */
37
+ export interface AutoSweepFlowState extends FetchStateAndError {
38
+ bufferAmount: Amount;
39
+ frequency: AutoSweepFrequency;
40
+ memo: string;
41
+ saveStatus: FetchStateAndError;
42
+ settingsId?: ID;
43
+ }
44
+ export declare const initialAutoSweepFlowState: AutoSweepFlowState;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initialAutoSweepFlowState = exports.bufferAmountToRisk = exports.RISK_BUFFER_AMOUNT = exports.toAutoSweepRiskLevel = exports.ALL_AUTO_SWEEP_RISK_LEVELS = exports.toAutoSweepFrequency = exports.ALL_AUTO_SWEEP_FREQUENCIES = void 0;
4
+ const amount_1 = require("../../../../commonStateTypes/amount");
5
+ const stringToUnion_1 = require("../../../../commonStateTypes/stringToUnion");
6
+ /**
7
+ * Cadence at which the auto-sweep transfer fires. Lowercase to match the
8
+ * cash-management settings API contract (and the `SweepFrequency` literal
9
+ * already used by `<AutoSweepSetupPage>` in web-components).
10
+ */
11
+ exports.ALL_AUTO_SWEEP_FREQUENCIES = [
12
+ 'daily',
13
+ 'weekly',
14
+ 'biweekly',
15
+ 'monthly',
16
+ ];
17
+ const toAutoSweepFrequency = (v) => (0, stringToUnion_1.stringToUnion)(v ?? '', exports.ALL_AUTO_SWEEP_FREQUENCIES);
18
+ exports.toAutoSweepFrequency = toAutoSweepFrequency;
19
+ /**
20
+ * Risk presets the auto-sweep setup form exposes. Each level maps to a
21
+ * canonical minimum-buffer amount (USD). Selecting a level in the UI is
22
+ * shorthand for choosing that buffer.
23
+ */
24
+ exports.ALL_AUTO_SWEEP_RISK_LEVELS = ['low', 'moderate', 'high'];
25
+ const toAutoSweepRiskLevel = (v) => (0, stringToUnion_1.stringToUnion)(v ?? '', exports.ALL_AUTO_SWEEP_RISK_LEVELS);
26
+ exports.toAutoSweepRiskLevel = toAutoSweepRiskLevel;
27
+ exports.RISK_BUFFER_AMOUNT = {
28
+ low: 15000,
29
+ moderate: 10000,
30
+ high: 5000,
31
+ };
32
+ /**
33
+ * Maps a buffer amount back onto the closest preset risk level. Falls back
34
+ * to `'moderate'` when the amount doesn't match a known preset (e.g. the
35
+ * server returned a custom value). The dropdown in `<AutoSweepSetupPage>`
36
+ * uses this so it can pre-select the user's existing band on edit.
37
+ */
38
+ const bufferAmountToRisk = (amount) => {
39
+ const match = Object.entries(exports.RISK_BUFFER_AMOUNT).find(([, presetAmount]) => presetAmount === amount);
40
+ return match != null ? match[0] : 'moderate';
41
+ };
42
+ exports.bufferAmountToRisk = bufferAmountToRisk;
43
+ exports.initialAutoSweepFlowState = {
44
+ bufferAmount: (0, amount_1.toAmount)(10000, 'USD'),
45
+ frequency: 'weekly',
46
+ memo: '',
47
+ saveStatus: { fetchState: 'Not-Started', error: undefined },
48
+ settingsId: undefined,
49
+ fetchState: 'Not-Started',
50
+ error: undefined,
51
+ };
@@ -0,0 +1,16 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { Observable } from 'rxjs';
3
+ import { RootState } from '../../../../../reducer';
4
+ import { ZeniAPI } from '../../../../../zeniAPI';
5
+ import { fetchCashManagementSettings, updateCashManagementSettings, updateCashManagementSettingsFetchStatus } from '../autoSweepFlowReducer';
6
+ export type ActionType = ReturnType<typeof fetchCashManagementSettings> | ReturnType<typeof updateCashManagementSettings> | ReturnType<typeof updateCashManagementSettingsFetchStatus>;
7
+ /**
8
+ * Hits `GET /cash-management/settings` and hydrates the auto-sweep slice
9
+ * with the server's existing settings (frequency, minimum buffer, settings
10
+ * id). Called from the cash management overview page-fetch epic alongside
11
+ * the other top-level fetches.
12
+ *
13
+ * TODO: switch the endpoint to a base URL constant once the prod endpoint
14
+ * lands; right now this hits the dev environment directly.
15
+ */
16
+ export declare const fetchCashManagementSettingsEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -0,0 +1,32 @@
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 responsePayload_1 = require("../../../../../responsePayload");
7
+ const autoSweepFlowReducer_1 = require("../autoSweepFlowReducer");
8
+ /**
9
+ * Hits `GET /cash-management/settings` and hydrates the auto-sweep slice
10
+ * with the server's existing settings (frequency, minimum buffer, settings
11
+ * id). Called from the cash management overview page-fetch epic alongside
12
+ * the other top-level fetches.
13
+ *
14
+ * TODO: switch the endpoint to a base URL constant once the prod endpoint
15
+ * lands; right now this hits the dev environment directly.
16
+ */
17
+ const fetchCashManagementSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(autoSweepFlowReducer_1.fetchCashManagementSettings.match), (0, operators_1.switchMap)(() => zeniAPI
18
+ .getJSON(`https://dev.api.zeni.ai/cash-management-agent/1.0/cash-management/settings`)
19
+ .pipe((0, operators_1.mergeMap)((response) => {
20
+ if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
21
+ return (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateCashManagementSettings)({ data: response.data }));
22
+ }
23
+ return (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateCashManagementSettingsFetchStatus)({
24
+ fetchState: 'Error',
25
+ error: response.status,
26
+ }));
27
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateCashManagementSettingsFetchStatus)({
28
+ fetchState: 'Error',
29
+ error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch cash management settings REST API call errored out' +
30
+ JSON.stringify(error)),
31
+ }))))));
32
+ exports.fetchCashManagementSettingsEpic = fetchCashManagementSettingsEpic;
@@ -0,0 +1,14 @@
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
+ /**
8
+ * Hits `PUT /cash-management/settings` with the values the user just
9
+ * confirmed in the auto-sweep flow.
10
+ *
11
+ * TODO: switch the endpoint to a base URL constant once the prod endpoint
12
+ * lands; right now this hits the dev environment directly.
13
+ */
14
+ export declare const saveAutoSweepSettingsEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -0,0 +1,31 @@
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
+ /**
10
+ * Hits `PUT /cash-management/settings` with the values the user just
11
+ * confirmed in the auto-sweep flow.
12
+ *
13
+ * TODO: switch the endpoint to a base URL constant once the prod endpoint
14
+ * lands; right now this hits the dev environment directly.
15
+ */
16
+ const saveAutoSweepSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(autoSweepFlowReducer_1.saveAutoSweepSettings.match), (0, operators_1.switchMap)((action) => zeniAPI
17
+ .putAndGetJSON(`https://dev.api.zeni.ai/cash-management-agent/1.0/cash-management/settings`, (0, autoSweepFlowPayload_1.toSaveAutoSweepSettingsBody)(action.payload))
18
+ .pipe((0, operators_1.mergeMap)((response) => {
19
+ if ((0, responsePayload_1.isSuccessResponse)(response)) {
20
+ return (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateAutoSweepSettingsFetchStatus)({ fetchState: 'Completed' }));
21
+ }
22
+ return (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateAutoSweepSettingsFetchStatus)({
23
+ fetchState: 'Error',
24
+ error: response.status,
25
+ }));
26
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, autoSweepFlowReducer_1.updateAutoSweepSettingsFetchStatus)({
27
+ fetchState: 'Error',
28
+ error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Save auto-sweep settings REST API call errored out' +
29
+ JSON.stringify(error)),
30
+ }))))));
31
+ exports.saveAutoSweepSettingsEpic = saveAutoSweepSettingsEpic;
@@ -0,0 +1,32 @@
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;
@@ -0,0 +1,42 @@
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
+ const toUpcomingPaymentEvent = (event) => ({
10
+ accountId: event.account_id,
11
+ accountType: event.account_type,
12
+ amount: (0, amount_1.toAmount)(event.amount_usd, event.currency_code),
13
+ label: event.label,
14
+ paymentDate: (0, zeniDayJS_1.date)(event.payment_date),
15
+ });
16
+ exports.toUpcomingPaymentEvent = toUpcomingPaymentEvent;
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: (0, amount_1.toAmount)(payload.amount, payload.currency_code),
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
+ const toCashManagementBannerData = (payload) => ({
38
+ inflows: payload.inflows.map(exports.toUpcomingPaymentEvent),
39
+ moneyMovements: payload.money_movements.map(toCashManagementMoneyMovementGroup),
40
+ outflows: payload.outflows.map(exports.toUpcomingPaymentEvent),
41
+ });
42
+ exports.toCashManagementBannerData = toCashManagementBannerData;
@@ -0,0 +1,15 @@
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;
@@ -0,0 +1,53 @@
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
+ fetchState: 'Not-Started',
11
+ error: undefined,
12
+ hasValidState() {
13
+ return this.fetchState == 'Completed';
14
+ },
15
+ };
16
+ const cashManagementOverview = (0, toolkit_1.createSlice)({
17
+ name: 'cashManagementOverview',
18
+ initialState: exports.initialState,
19
+ reducers: {
20
+ fetchCashManagementOverviewPage: {
21
+ reducer() { },
22
+ prepare(cacheOverride) {
23
+ return { payload: { cacheOverride } };
24
+ },
25
+ },
26
+ fetchCashManagementBanner(draft) {
27
+ draft.banner = {
28
+ ...cashManagementOverviewState_1.initialCashManagementBannerState,
29
+ fetchState: 'In-Progress',
30
+ error: undefined,
31
+ };
32
+ },
33
+ updateCashManagementBanner(draft, action) {
34
+ draft.banner = {
35
+ fetchState: 'Completed',
36
+ error: undefined,
37
+ data: (0, cashManagementOverviewPayload_1.toCashManagementBannerData)(action.payload.data),
38
+ };
39
+ },
40
+ updateCashManagementBannerFetchStatus(draft, action) {
41
+ draft.banner = {
42
+ ...draft.banner,
43
+ fetchState: action.payload.fetchState,
44
+ error: action.payload.error,
45
+ };
46
+ },
47
+ clearCashManagementOverview(draft) {
48
+ Object.assign(draft, exports.initialState);
49
+ },
50
+ },
51
+ });
52
+ _a = cashManagementOverview.actions, exports.fetchCashManagementOverviewPage = _a.fetchCashManagementOverviewPage, exports.fetchCashManagementBanner = _a.fetchCashManagementBanner, exports.updateCashManagementBanner = _a.updateCashManagementBanner, exports.updateCashManagementBannerFetchStatus = _a.updateCashManagementBannerFetchStatus, exports.clearCashManagementOverview = _a.clearCashManagementOverview;
53
+ exports.default = cashManagementOverview.reducer;
@@ -0,0 +1,41 @@
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
+ /**
10
+ * One point on the cash-balance projection line. The first point is today's
11
+ * `cashBalance`; each subsequent point is the running balance after applying
12
+ * the next inflow / outflow event (in chronological order). The `isInflow` /
13
+ * `isOutflow` flags drive the colored dot markers in the chart.
14
+ */
15
+ export interface CashProjectionPoint {
16
+ balance: number;
17
+ /** Pre-formatted display label (e.g. `"Today"`, `"May 27"`). */
18
+ date: string;
19
+ isInflow?: boolean;
20
+ isOutflow?: boolean;
21
+ }
22
+ export interface CashManagementOverviewSelectorView extends SelectorView {
23
+ banner: CashManagementOverviewBannerSelectorView;
24
+ cashBalance: Amount;
25
+ /** Net cash flow over the horizon — `totalInFlow` minus `totalOutFlow`.
26
+ * Positive = surplus, negative = burn. */
27
+ cashflow: Amount;
28
+ inflowEvents: UpcomingPaymentEvent[];
29
+ outflowEvents: UpcomingPaymentEvent[];
30
+ /** Running cash-balance projection seeded by `cashBalance` and stepped by
31
+ * the inflow / outflow events. */
32
+ projectionData: CashProjectionPoint[];
33
+ totalCash: Amount;
34
+ /** Sum of all `inflowEvents[].amount` values. */
35
+ totalInFlow: Amount;
36
+ /** Sum of all `outflowEvents[].amount` values. */
37
+ totalOutFlow: Amount;
38
+ treasuryBalance: Amount;
39
+ }
40
+ export declare const getCashManagementOverviewBanner: (state: RootState) => CashManagementOverviewBannerSelectorView;
41
+ export declare const getCashManagementOverview: (state: RootState) => CashManagementOverviewSelectorView;
@@ -0,0 +1,184 @@
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
+ date: e.paymentDate,
101
+ delta: e.amount.amount,
102
+ isInflow: true,
103
+ })),
104
+ ...outflowEvents.map((e) => ({
105
+ date: e.paymentDate,
106
+ delta: -e.amount.amount,
107
+ isOutflow: true,
108
+ })),
109
+ ].sort((a, b) => a.date.valueOf() - b.date.valueOf());
110
+ let balance = cashBalance.amount;
111
+ const points = [{ balance, date: 'Today' }];
112
+ events.forEach((event) => {
113
+ balance += event.delta;
114
+ points.push({
115
+ balance,
116
+ date: event.date.format('MMM D'),
117
+ isInflow: event.isInflow,
118
+ isOutflow: event.isOutflow,
119
+ });
120
+ });
121
+ return points;
122
+ };
123
+ const sumEventAmounts = (events) => events.reduce((acc, event) => addAmounts(acc, event.amount), (0, amount_1.zeroAmount)());
124
+ /**
125
+ * Subtracts `b` from `a`, sharing the currency-match guard with `addAmounts`.
126
+ * Used to compute net cash flow (`inflow - outflow`).
127
+ */
128
+ const subtractAmounts = (a, b) => {
129
+ if (isZeroAmount(b)) {
130
+ return { ...a };
131
+ }
132
+ if (isZeroAmount(a)) {
133
+ return { ...b, amount: -b.amount };
134
+ }
135
+ if (a.currencyCode !== b.currencyCode ||
136
+ a.currencySymbol !== b.currencySymbol) {
137
+ console.warn(`cashManagementOverview: skipping balance with mismatched currency. Expected ${a.currencyCode} (${a.currencySymbol}), got ${b.currencyCode} (${b.currencySymbol}).`);
138
+ return a;
139
+ }
140
+ return {
141
+ amount: a.amount - b.amount,
142
+ currencyCode: a.currencyCode,
143
+ currencySymbol: a.currencySymbol,
144
+ };
145
+ };
146
+ const isZeroAmount = (a) => a.amount === 0 && a.currencyCode === 'USD' && a.currencySymbol === '$';
147
+ /**
148
+ * Adds two Amounts. Currencies must match (the seeded zeroAmount() counts as
149
+ * "no currency yet" and adopts `b`'s currency). Mismatches return `a`
150
+ * unchanged and warn — mixing currencies in a total is a bug, not silent
151
+ * conversion.
152
+ */
153
+ const addAmounts = (a, b) => {
154
+ if (isZeroAmount(a)) {
155
+ return { ...b };
156
+ }
157
+ if (a.currencyCode !== b.currencyCode ||
158
+ a.currencySymbol !== b.currencySymbol) {
159
+ console.warn(`cashManagementOverview: skipping balance with mismatched currency. Expected ${a.currencyCode} (${a.currencySymbol}), got ${b.currencyCode} (${b.currencySymbol}).`);
160
+ return a;
161
+ }
162
+ return {
163
+ amount: a.amount + b.amount,
164
+ currencyCode: a.currencyCode,
165
+ currencySymbol: a.currencySymbol,
166
+ };
167
+ };
168
+ const sumCashBalances = (paymentAccountIds, paymentAccountState, depositAccountIds, depositAccountState) => {
169
+ let total = (0, amount_1.zeroAmount)();
170
+ paymentAccountIds.forEach((id) => {
171
+ const balance = paymentAccountState.paymentAccountByID[id]?.balances
172
+ ?.available;
173
+ if (balance != null) {
174
+ total = addAmounts(total, balance);
175
+ }
176
+ });
177
+ depositAccountIds.forEach((id) => {
178
+ const balance = depositAccountState.depositAccountByID[id]?.accountBalance?.available;
179
+ if (balance != null) {
180
+ total = addAmounts(total, balance);
181
+ }
182
+ });
183
+ return total;
184
+ };
@@ -0,0 +1,71 @@
1
+ import { Amount } from '../../../../commonStateTypes/amount';
2
+ import { FetchStateAndError, FetchedState, 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
+ export interface CashManagementOverviewState extends FetchedState {
69
+ banner: CashManagementBannerState;
70
+ }
71
+ export declare const initialCashManagementBannerState: CashManagementBannerState;
@@ -0,0 +1,8 @@
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
+ };