@zeniai/client-epic-state 5.2.93-betaNB2 → 5.2.94

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 (88) hide show
  1. package/lib/commonStateTypes/timeframeTick.d.ts +1 -0
  2. package/lib/commonStateTypes/timeframeTick.js +1 -0
  3. package/lib/commonStateTypes/viewAndReport/reportUIState.d.ts +2 -0
  4. package/lib/commonStateTypes/viewAndReport/viewAndReport.d.ts +2 -0
  5. package/lib/entity/reconciliationReport/reconciliationReportPayload.d.ts +0 -1
  6. package/lib/entity/reconciliationReport/reconciliationReportReducer.js +0 -1
  7. package/lib/entity/reconciliationReport/reconciliationReportState.d.ts +2 -4
  8. package/lib/entity/reconciliationReport/reconciliationReportState.js +1 -4
  9. package/lib/esm/commonStateTypes/timeframeTick.js +1 -0
  10. package/lib/esm/entity/reconciliationReport/reconciliationReportReducer.js +0 -1
  11. package/lib/esm/entity/reconciliationReport/reconciliationReportState.js +1 -4
  12. package/lib/esm/view/balanceSheet/balanceSheetForTimeframeEpic.js +4 -0
  13. package/lib/esm/view/balanceSheet/balanceSheetReducer.js +8 -2
  14. package/lib/esm/view/cashFlow/cashFlowForTimeframeEpic.js +4 -0
  15. package/lib/esm/view/cashFlow/cashFlowReducer.js +2 -2
  16. package/lib/esm/view/cashInCashOut/cashInCashOutEpic.js +22 -14
  17. package/lib/esm/view/cashInCashOut/cashInCashOutReducer.js +161 -41
  18. package/lib/esm/view/cashInCashOut/cashInCashOutSelector.js +42 -15
  19. package/lib/esm/view/cashPosition/cashPositionEpic.js +21 -13
  20. package/lib/esm/view/cashPosition/cashPositionReducer.js +155 -44
  21. package/lib/esm/view/cashPosition/cashPositionSelector.js +28 -9
  22. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeEpic.js +7 -7
  23. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.js +25 -10
  24. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeReducer.js +184 -40
  25. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeSelector.js +26 -8
  26. package/lib/esm/view/opEx/opExEpic.js +7 -7
  27. package/lib/esm/view/opEx/opExForTimeFrameEpic.js +21 -6
  28. package/lib/esm/view/opEx/opExReducer.js +169 -32
  29. package/lib/esm/view/opEx/opExSelector.js +28 -10
  30. package/lib/esm/view/profitAndLoss/profitAndLossForTimeframeEpic.js +4 -0
  31. package/lib/esm/view/profitAndLoss/profitAndLossReducer.js +9 -2
  32. package/lib/esm/view/revenue/revenueEpic.js +7 -7
  33. package/lib/esm/view/revenue/revenueForTimeframeEpic.js +23 -8
  34. package/lib/esm/view/revenue/revenueReducer.js +183 -40
  35. package/lib/esm/view/revenue/revenueSelector.js +30 -10
  36. package/lib/view/balanceSheet/balanceSheetForTimeframeEpic.js +4 -0
  37. package/lib/view/balanceSheet/balanceSheetReducer.d.ts +3 -1
  38. package/lib/view/balanceSheet/balanceSheetReducer.js +8 -2
  39. package/lib/view/cashFlow/cashFlowForTimeframeEpic.js +4 -0
  40. package/lib/view/cashFlow/cashFlowReducer.d.ts +3 -1
  41. package/lib/view/cashFlow/cashFlowReducer.js +2 -2
  42. package/lib/view/cashInCashOut/cashInCashOutEpic.d.ts +8 -2
  43. package/lib/view/cashInCashOut/cashInCashOutEpic.js +22 -14
  44. package/lib/view/cashInCashOut/cashInCashOutReducer.d.ts +13 -1
  45. package/lib/view/cashInCashOut/cashInCashOutReducer.js +161 -41
  46. package/lib/view/cashInCashOut/cashInCashOutSelector.d.ts +2 -1
  47. package/lib/view/cashInCashOut/cashInCashOutSelector.js +42 -15
  48. package/lib/view/cashInCashOut/cashInCashOutState.d.ts +5 -1
  49. package/lib/view/cashPosition/cashPositionEpic.d.ts +8 -2
  50. package/lib/view/cashPosition/cashPositionEpic.js +21 -13
  51. package/lib/view/cashPosition/cashPositionReducer.d.ts +13 -2
  52. package/lib/view/cashPosition/cashPositionReducer.js +155 -44
  53. package/lib/view/cashPosition/cashPositionSelector.d.ts +2 -1
  54. package/lib/view/cashPosition/cashPositionSelector.js +28 -9
  55. package/lib/view/cashPosition/cashPositionState.d.ts +5 -1
  56. package/lib/view/financeStatement/financeStatementEpic.d.ts +6 -0
  57. package/lib/view/netBurnOrIncome/fetchNetBurnOrIncomeWithForecastEpic.d.ts +1 -0
  58. package/lib/view/netBurnOrIncome/netBurnOrIncomeEpic.js +7 -7
  59. package/lib/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.d.ts +2 -1
  60. package/lib/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.js +26 -11
  61. package/lib/view/netBurnOrIncome/netBurnOrIncomeReducer.d.ts +12 -3
  62. package/lib/view/netBurnOrIncome/netBurnOrIncomeReducer.js +184 -40
  63. package/lib/view/netBurnOrIncome/netBurnOrIncomeSelector.d.ts +1 -1
  64. package/lib/view/netBurnOrIncome/netBurnOrIncomeSelector.js +26 -8
  65. package/lib/view/netBurnOrIncome/netBurnOrIncomeState.d.ts +8 -0
  66. package/lib/view/opEx/fetchOpExWithForecastEpic.d.ts +1 -0
  67. package/lib/view/opEx/opExEpic.js +7 -7
  68. package/lib/view/opEx/opExForTimeFrameEpic.d.ts +2 -1
  69. package/lib/view/opEx/opExForTimeFrameEpic.js +22 -7
  70. package/lib/view/opEx/opExReducer.d.ts +12 -3
  71. package/lib/view/opEx/opExReducer.js +168 -31
  72. package/lib/view/opEx/opExSelector.d.ts +1 -1
  73. package/lib/view/opEx/opExSelector.js +28 -10
  74. package/lib/view/opEx/opExState.d.ts +6 -0
  75. package/lib/view/profitAndLoss/profitAndLossForTimeframeEpic.js +4 -0
  76. package/lib/view/profitAndLoss/profitAndLossReducer.d.ts +3 -1
  77. package/lib/view/profitAndLoss/profitAndLossReducer.js +9 -2
  78. package/lib/view/reportUIOptions/updateReportUIOptionCOABalancesRangeEpic.d.ts +15 -0
  79. package/lib/view/revenue/fetchRevenueWithForecastEpic.d.ts +1 -0
  80. package/lib/view/revenue/revenueEpic.js +7 -7
  81. package/lib/view/revenue/revenueForTimeframeEpic.d.ts +2 -1
  82. package/lib/view/revenue/revenueForTimeframeEpic.js +24 -9
  83. package/lib/view/revenue/revenueReducer.d.ts +12 -3
  84. package/lib/view/revenue/revenueReducer.js +182 -39
  85. package/lib/view/revenue/revenueSelector.d.ts +1 -1
  86. package/lib/view/revenue/revenueSelector.js +30 -10
  87. package/lib/view/revenue/revenueState.d.ts +8 -0
  88. package/package.json +1 -1
@@ -9,6 +9,7 @@ const dataAvailable_1 = require("../../commonStateTypes/dataAvailable");
9
9
  const thisPeriodHelpers_1 = require("../../commonStateTypes/viewAndReport/thisPeriodHelpers");
10
10
  const insightSummaryPayload_1 = require("../../entity/insights/insightSummaryPayload");
11
11
  const rootActions_1 = require("../../rootActions");
12
+ const zeniDayJS_1 = require("../../zeniDayJS");
12
13
  const getSelectedAndHighlightedRanges_1 = require("../common/getSelectedAndHighlightedRanges");
13
14
  exports.defaultPeriods = {
14
15
  numberOfPeriods: 5,
@@ -19,6 +20,10 @@ exports.initialState = {
19
20
  cashIn: undefined,
20
21
  cashOut: undefined,
21
22
  netCashFlow: undefined,
23
+ customCashIn: undefined,
24
+ customCashOut: undefined,
25
+ customNetCashFlow: undefined,
26
+ customFetchState: undefined,
22
27
  dataAvailable: undefined,
23
28
  firstMonthOfFY: 1,
24
29
  reportId: 'cash_in_cash_out',
@@ -53,49 +58,118 @@ const cashInCashOut = (0, toolkit_1.createSlice)({
53
58
  name: 'cashInCashOut',
54
59
  initialState: exports.initialState,
55
60
  reducers: {
56
- fetchCashInCashOut(draft) {
57
- draft.fetchState = 'In-Progress';
58
- draft.error = undefined;
61
+ fetchCashInCashOut: {
62
+ prepare(startDate, endDate) {
63
+ return { payload: { endDate, startDate } };
64
+ },
65
+ reducer(draft, action) {
66
+ // Route by per-fetch dates: a custom (dated) fetch marks only the
67
+ // isolated customFetchState so the shared fetchState the dashboard reads
68
+ // stays as custom-mode activation left it (self-heal), and the shared
69
+ // error isn't cleared by a detail-only fetch.
70
+ if (action.payload.startDate != null &&
71
+ action.payload.endDate != null) {
72
+ draft.customFetchState = 'In-Progress';
73
+ }
74
+ else {
75
+ draft.fetchState = 'In-Progress';
76
+ draft.error = undefined;
77
+ }
78
+ },
59
79
  },
60
- updateCashInCashOut(draft, action) {
61
- draft.fetchState = 'Completed';
62
- draft.error = undefined;
63
- const report = (0, viewAndReportPayload_1.mapReportPayloadToReport)(action.payload.report);
64
- Object.assign(draft, report);
65
- const { cash_in, cash_out, net_cash_flow, insights } = action.payload.report;
66
- draft.cashIn =
67
- (0, coaBalancePayload_1.mapCOABalanceGroupedWithIDsPayloadToCOABalanceGroupedWithIDs)(cash_in);
68
- draft.cashOut =
69
- (0, coaBalancePayload_1.mapCOABalanceGroupedWithIDsPayloadToCOABalanceGroupedWithIDs)(cash_out);
70
- draft.netCashFlow =
71
- (0, coaBalancePayload_1.mapCOABalanceGroupedPayloadToCOABalanceGrouped)(net_cash_flow);
72
- draft.insights = (0, insightSummaryPayload_1.mapInsightsPayloadtoInsightsState)(insights);
73
- const cashInOrCashOut = draft.cashIn != null ? draft.cashIn : draft.cashOut;
74
- draft.dataAvailable = report.dataAvailable
75
- ? report.dataAvailable
76
- : (0, dataAvailable_1.getDataAvailableDateRange)(cashInOrCashOut);
77
- if (draft.dataAvailable != null) {
78
- const timeframe = draft.uiState.timeframe;
79
- const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(draft.firstMonthOfFY, timeframe, [draft.cashIn, draft.cashOut], draft.dataAvailable);
80
- const selectionRanges = (0, getSelectedAndHighlightedRanges_1.getInitialSelectedAndHighlightedRanges)({
81
- firstMonthOfFY: draft.firstMonthOfFY,
82
- timeframe,
83
- coaBalances,
84
- orderBy: 'ascending_date',
85
- maxNumOfPeriodsToSelect: exports.defaultPeriods.numberOfPeriods,
86
- maxNumOfPeriodsToHighlight: exports.initialState.uiState.maxNumOfPeriodsToHighlight,
87
- });
88
- if (selectionRanges?.selectedCOABalancesRange != null) {
89
- draft.uiState.selectedCOABalancesRange =
90
- selectionRanges?.selectedCOABalancesRange;
80
+ updateCashInCashOut: {
81
+ prepare(data, isCustomDateRange = false) {
82
+ return { payload: { data, isCustomDateRange } };
83
+ },
84
+ reducer(draft, action) {
85
+ const isCustomDateRange = action.payload.isCustomDateRange === true;
86
+ // A custom (dated) fetch marks the isolated scalar customFetchState so the
87
+ // shared fetchState the dashboard reads via hasValidState() stays as
88
+ // custom-mode activation left it (Not-Started), letting the card self-heal.
89
+ if (isCustomDateRange) {
90
+ draft.customFetchState = 'Completed';
91
91
  }
92
- draft.uiState.highlightedCOABalancesRange =
93
- selectionRanges?.highlightedCOABalancesRange;
94
- }
92
+ else {
93
+ draft.fetchState = 'Completed';
94
+ draft.error = undefined;
95
+ }
96
+ const report = (0, viewAndReportPayload_1.mapReportPayloadToReport)(action.payload.data.report);
97
+ // A custom (dated) fetch must not overwrite the shared report fields the
98
+ // dashboard card reads (firstMonthOfFY, bookCloseDate, reportTitle,
99
+ // status, version) — only its isolated custom* slots below.
100
+ if (!isCustomDateRange) {
101
+ Object.assign(draft, report);
102
+ }
103
+ const { cash_in, cash_out, net_cash_flow, insights } = action.payload.data.report;
104
+ const mappedCashIn = (0, coaBalancePayload_1.mapCOABalanceGroupedWithIDsPayloadToCOABalanceGroupedWithIDs)(cash_in);
105
+ const mappedCashOut = (0, coaBalancePayload_1.mapCOABalanceGroupedWithIDsPayloadToCOABalanceGroupedWithIDs)(cash_out);
106
+ const mappedNetCashFlow = (0, coaBalancePayload_1.mapCOABalanceGroupedPayloadToCOABalanceGrouped)(net_cash_flow);
107
+ // Route custom-date results to the separate slots so the dashboard card
108
+ // (which reads cashIn/cashOut/netCashFlow) keeps the default window.
109
+ if (isCustomDateRange) {
110
+ draft.customCashIn = mappedCashIn;
111
+ draft.customCashOut = mappedCashOut;
112
+ draft.customNetCashFlow = mappedNetCashFlow;
113
+ }
114
+ else {
115
+ draft.cashIn = mappedCashIn;
116
+ draft.cashOut = mappedCashOut;
117
+ draft.netCashFlow = mappedNetCashFlow;
118
+ }
119
+ // Insights are shared (read by the dashboard card); a custom slice must
120
+ // not overwrite them.
121
+ if (!isCustomDateRange) {
122
+ draft.insights = (0, insightSummaryPayload_1.mapInsightsPayloadtoInsightsState)(insights);
123
+ }
124
+ // Derive dataAvailable from the slot this fetch actually populated.
125
+ const cashInOrCashOut = mappedCashIn != null ? mappedCashIn : mappedCashOut;
126
+ // Don't let a custom slice shrink the shared dataAvailable the dashboard
127
+ // uses for its period count; a default fetch always updates it, a custom
128
+ // one only populates it on first load (when nothing has set it yet).
129
+ if (!isCustomDateRange || draft.dataAvailable == null) {
130
+ draft.dataAvailable = report.dataAvailable
131
+ ? report.dataAvailable
132
+ : (0, dataAvailable_1.getDataAvailableDateRange)(cashInOrCashOut);
133
+ }
134
+ if (draft.dataAvailable != null &&
135
+ // A custom date range drives the window; don't reset it to the default on
136
+ // every report receipt (this is what clamped wide ranges back to 8).
137
+ draft.uiState.customTimeframe == null) {
138
+ const timeframe = draft.uiState.timeframe;
139
+ const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(draft.firstMonthOfFY, timeframe, [draft.cashIn, draft.cashOut], draft.dataAvailable);
140
+ const selectionRanges = (0, getSelectedAndHighlightedRanges_1.getInitialSelectedAndHighlightedRanges)({
141
+ firstMonthOfFY: draft.firstMonthOfFY,
142
+ timeframe,
143
+ coaBalances,
144
+ orderBy: 'ascending_date',
145
+ maxNumOfPeriodsToSelect: exports.defaultPeriods.numberOfPeriods,
146
+ maxNumOfPeriodsToHighlight: exports.initialState.uiState.maxNumOfPeriodsToHighlight,
147
+ });
148
+ if (selectionRanges?.selectedCOABalancesRange != null) {
149
+ draft.uiState.selectedCOABalancesRange =
150
+ selectionRanges?.selectedCOABalancesRange;
151
+ }
152
+ draft.uiState.highlightedCOABalancesRange =
153
+ selectionRanges?.highlightedCOABalancesRange;
154
+ }
155
+ },
95
156
  },
96
- updateCashInCashOutFailure(draft, action) {
97
- draft.fetchState = 'Error';
98
- draft.error = action.payload;
157
+ updateCashInCashOutFailure: {
158
+ prepare(error, isCustomDateRange = false) {
159
+ return { payload: { error, isCustomDateRange } };
160
+ },
161
+ reducer(draft, action) {
162
+ // Route the error like the request/success: a custom (dated) fetch's
163
+ // failure lands in customFetchState so the shared default the dashboard
164
+ // reads isn't marked Error.
165
+ if (action.payload.isCustomDateRange === true) {
166
+ draft.customFetchState = 'Error';
167
+ }
168
+ else {
169
+ draft.fetchState = 'Error';
170
+ draft.error = action.payload.error;
171
+ }
172
+ },
99
173
  },
100
174
  updateCashInCashOutAdditionalBalancesSelection(draft, action) {
101
175
  const { cashIn, cashOut, dataAvailable } = draft;
@@ -111,7 +185,7 @@ const cashInCashOut = (0, toolkit_1.createSlice)({
111
185
  action.payload.additionalBalances.length != 0
112
186
  ? true
113
187
  : false;
114
- if (dataAvailable != null) {
188
+ if (dataAvailable != null && draft.uiState.customTimeframe == null) {
115
189
  const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(draft.firstMonthOfFY, timeframe, [cashIn, cashOut], dataAvailable);
116
190
  const thisPeriod = (0, thisPeriodHelpers_1.extractThisPeriod)(draft.firstMonthOfFY, timeframe, selectedCOABalancesRange, coaBalances);
117
191
  if (thisPeriod != null &&
@@ -140,6 +214,45 @@ const cashInCashOut = (0, toolkit_1.createSlice)({
140
214
  }
141
215
  },
142
216
  updateCashInCashOutCOABalancesRange(draft, action) {
217
+ if (action.payload.isCustomDateRange != null) {
218
+ if (action.payload.isCustomDateRange === true) {
219
+ // Collapse the two raw date strings into a single customTimeframe object.
220
+ // Presence of customTimeframe signals custom-mode active (replaces the
221
+ // old isCustomDateRangeActive boolean + customStartDate/customEndDate).
222
+ draft.uiState.customTimeframe =
223
+ action.payload.customStartDate != null &&
224
+ action.payload.customEndDate != null
225
+ ? {
226
+ startDate: (0, zeniDayJS_1.date)(action.payload.customStartDate),
227
+ endDate: (0, zeniDayJS_1.date)(action.payload.customEndDate),
228
+ }
229
+ : undefined;
230
+ // Invalidate the shared default-window fetchState so dashboardEpic
231
+ // refetches the default data on the next dashboard visit — the custom
232
+ // fetch writes into the custom slots, and this lets the card self-heal
233
+ // without a reload. The detail screen reads customFetchState.
234
+ draft.fetchState = 'Not-Started';
235
+ }
236
+ else {
237
+ draft.uiState.customTimeframe = undefined;
238
+ }
239
+ }
240
+ // A custom date range drives the visible window directly: honor the exact
241
+ // numberOfPeriods + thisPeriod from the payload instead of re-deriving
242
+ // (which clamps the range to the available/non-zero periods).
243
+ if (draft.uiState.customTimeframe != null) {
244
+ draft.uiState.selectedCOABalancesRange =
245
+ action.payload.selectedCOABalancesRange;
246
+ if (action.payload.highlightedCOABalancesRange != null) {
247
+ // Clamp the highlight to the same cap the non-custom path enforces so
248
+ // a wide custom range doesn't highlight all N periods at once.
249
+ draft.uiState.highlightedCOABalancesRange = {
250
+ ...action.payload.highlightedCOABalancesRange,
251
+ numberOfPeriods: Math.min(action.payload.highlightedCOABalancesRange.numberOfPeriods, draft.uiState.maxNumOfPeriodsToHighlight),
252
+ };
253
+ }
254
+ return;
255
+ }
143
256
  const { cashIn, cashOut, dataAvailable } = draft;
144
257
  const { timeframe, selectedCOABalancesRange, maxNumOfPeriodsToHighlight, highlightedCOABalancesRange, } = draft.uiState;
145
258
  if (dataAvailable != null &&
@@ -184,6 +297,13 @@ const cashInCashOut = (0, toolkit_1.createSlice)({
184
297
  draft.uiState.downloadState = action.payload;
185
298
  },
186
299
  updateCashInCashOutThisPeriod(draft, action) {
300
+ // In custom-date mode the picker drives the window; skip re-deriving the
301
+ // selected/highlighted ranges from the default dataAvailable (the epic
302
+ // re-dispatches the default thisPeriod on every response, which would
303
+ // otherwise clamp the custom window back to the default).
304
+ if (draft.uiState.customTimeframe != null) {
305
+ return;
306
+ }
187
307
  const { cashIn, cashOut, dataAvailable } = draft;
188
308
  const { timeframe, selectedCOABalancesRange, highlightedCOABalancesRange, maxNumOfPeriodsToHighlight, } = draft.uiState;
189
309
  if (dataAvailable != null && action.payload.thisPeriod != null) {
@@ -6,7 +6,7 @@ import { AccountGroupState } from '../../entity/accountGroup/accountGroupState';
6
6
  import { RootState } from '../../rootStateTypes';
7
7
  import { CashInCashOutReport, CashInCashOutUIStateSelectorView } from './cashInCashOutSelectorTypes';
8
8
  import { CashInCashOutState } from './cashInCashOutState';
9
- export declare const getCashInCashOut: (accountState: AccountState, accountGroupState: AccountGroupState, cashInCashOutState: CashInCashOutState, filter: COABalancesFilter) => {
9
+ export declare const getCashInCashOut: (accountState: AccountState, accountGroupState: AccountGroupState, cashInCashOutState: CashInCashOutState, filter: COABalancesFilter, readCustomRangeSlot?: boolean) => {
10
10
  filter: COABalancesFilter;
11
11
  cashIn: Section;
12
12
  cashOut: Section;
@@ -23,6 +23,7 @@ export declare const getCashInCashOut: (accountState: AccountState, accountGroup
23
23
  error: import("../..").ZeniAPIStatus<Record<string, unknown>> | undefined;
24
24
  insights: import("../..").InsightSummary[];
25
25
  downloadState: import("../..").FetchState;
26
+ customTimeframe: import("../../commonStateTypes/timeframeTick").TimeframeTick | undefined;
26
27
  };
27
28
  export declare const getCashInCashOutUIState: (state: RootState) => CashInCashOutUIStateSelectorView;
28
29
  export declare const getCashInCashOutForSelectedRange: (state: RootState) => CashInCashOutReport;
@@ -8,39 +8,53 @@ const dataAvailable_1 = require("../../commonStateTypes/dataAvailable");
8
8
  const timeframeTick_1 = require("../../commonStateTypes/timeframeTick");
9
9
  const accountSelector_1 = require("../../entity/account/accountSelector");
10
10
  const accountGroupSelector_1 = require("../../entity/accountGroup/accountGroupSelector");
11
- const getCashInCashOut = (accountState, accountGroupState, cashInCashOutState, filter) => {
11
+ const getCashInCashOut = (accountState, accountGroupState, cashInCashOutState, filter, readCustomRangeSlot) => {
12
12
  const reportId = 'cash_in_cash_out';
13
+ // The detail (in custom mode) reads the isolated custom slots so a default
14
+ // fetch can't overwrite the partial-period data; the dashboard (no flag) reads
15
+ // the default slots, so the two can never clobber each other.
16
+ const useCustomRange = readCustomRangeSlot === true &&
17
+ cashInCashOutState.uiState.customTimeframe != null;
18
+ const cashInSource = useCustomRange
19
+ ? cashInCashOutState.customCashIn
20
+ : cashInCashOutState.cashIn;
21
+ const cashOutSource = useCustomRange
22
+ ? cashInCashOutState.customCashOut
23
+ : cashInCashOutState.cashOut;
24
+ const netCashFlowSource = useCustomRange
25
+ ? cashInCashOutState.customNetCashFlow
26
+ : cashInCashOutState.netCashFlow;
13
27
  const cashIn = {
14
28
  itemOrder: 'last_balance_descending',
15
- accountGroupsOrdered: (0, accountGroupSelector_1.getAccountGroupsOrdered)(filter, accountState, accountGroupState, cashInCashOutState.cashIn?.accountGroupIDs ?? [], 'cash_in_cash_out', 'cash_in_cash_out', 'cashIn'),
16
- accountsOrdered: cashInCashOutState.cashIn?.accountGroupIDs.length === 0
29
+ accountGroupsOrdered: (0, accountGroupSelector_1.getAccountGroupsOrdered)(filter, accountState, accountGroupState, cashInSource?.accountGroupIDs ?? [], 'cash_in_cash_out', 'cash_in_cash_out', 'cashIn'),
30
+ accountsOrdered: cashInSource?.accountGroupIDs.length === 0
17
31
  ? (0, accountSelector_1.getAccountsOrdered)(filter, accountState, {
18
- accountIDs: cashInCashOutState.cashIn?.accountIDs ?? [],
32
+ accountIDs: cashInSource?.accountIDs ?? [],
19
33
  reportId,
20
34
  }, 'cashIn')
21
35
  : [],
22
- ...(0, getCOABalancesSlice_1.getCOABalances)(cashInCashOutState.cashIn, filter),
36
+ ...(0, getCOABalancesSlice_1.getCOABalances)(cashInSource, filter),
23
37
  };
24
38
  const cashOut = {
25
39
  itemOrder: 'last_balance_descending',
26
- accountGroupsOrdered: (0, accountGroupSelector_1.getAccountGroupsOrdered)(filter, accountState, accountGroupState, cashInCashOutState.cashOut?.accountGroupIDs ?? [], 'cash_in_cash_out', 'cash_in_cash_out', 'cashOut'),
27
- accountsOrdered: cashInCashOutState.cashOut?.accountGroupIDs.length === 0
40
+ accountGroupsOrdered: (0, accountGroupSelector_1.getAccountGroupsOrdered)(filter, accountState, accountGroupState, cashOutSource?.accountGroupIDs ?? [], 'cash_in_cash_out', 'cash_in_cash_out', 'cashOut'),
41
+ accountsOrdered: cashOutSource?.accountGroupIDs.length === 0
28
42
  ? (0, accountSelector_1.getAccountsOrdered)(filter, accountState, {
29
- accountIDs: cashInCashOutState.cashOut?.accountIDs ?? [],
43
+ accountIDs: cashOutSource?.accountIDs ?? [],
30
44
  reportId,
31
45
  }, 'cashOut')
32
46
  : [],
33
- ...(0, getCOABalancesSlice_1.getCOABalances)(cashInCashOutState.cashOut, filter),
47
+ ...(0, getCOABalancesSlice_1.getCOABalances)(cashOutSource, filter),
34
48
  };
35
- const netCashFlow = (0, getCOABalancesSlice_1.getCOABalances)(cashInCashOutState.netCashFlow, filter);
49
+ const netCashFlow = (0, getCOABalancesSlice_1.getCOABalances)(netCashFlowSource, filter);
36
50
  let allTimeframeTicks = [];
37
51
  const dataAvailable = cashInCashOutState.dataAvailable;
38
52
  const firstMonthOfFY = cashInCashOutState.firstMonthOfFY;
39
53
  if (dataAvailable != null) {
40
54
  const noFilter = (0, coaBalancesFilter_1.newBalancesFilterForDateRange)(firstMonthOfFY, cashInCashOutState.uiState.timeframe, dataAvailable, 'ascending_date', []);
41
55
  const cashInCashOutBalances = cashIn.balances.length > 0
42
- ? (0, getCOABalancesSlice_1.getCOABalances)(cashInCashOutState.cashIn, noFilter)
43
- : (0, getCOABalancesSlice_1.getCOABalances)(cashInCashOutState.cashOut, noFilter);
56
+ ? (0, getCOABalancesSlice_1.getCOABalances)(cashInSource, noFilter)
57
+ : (0, getCOABalancesSlice_1.getCOABalances)(cashOutSource, noFilter);
44
58
  allTimeframeTicks = cashInCashOutBalances.balances.map((balance) => (0, timeframeTick_1.toTimeframeTick)(balance));
45
59
  }
46
60
  return {
@@ -56,10 +70,17 @@ const getCashInCashOut = (accountState, accountGroupState, cashInCashOutState, f
56
70
  reportTitle: cashInCashOutState.reportTitle,
57
71
  version: cashInCashOutState.version,
58
72
  status: cashInCashOutState.status,
59
- fetchState: cashInCashOutState.fetchState,
73
+ // The detail reads the isolated customFetchState so its loading state follows
74
+ // the custom fetch; the dashboard (no flag) reads the shared fetchState, which
75
+ // custom-mode activation reset to Not-Started so dashboardEpic refetches.
76
+ fetchState: useCustomRange && cashInCashOutState.customFetchState != null
77
+ ? cashInCashOutState.customFetchState
78
+ : cashInCashOutState.fetchState,
60
79
  error: cashInCashOutState.error,
61
80
  insights: cashInCashOutState.insights ?? [],
62
81
  downloadState: cashInCashOutState.uiState.downloadState,
82
+ // Surface the customTimeframe so the detail picker can restore the selection.
83
+ customTimeframe: cashInCashOutState.uiState.customTimeframe,
63
84
  };
64
85
  };
65
86
  exports.getCashInCashOut = getCashInCashOut;
@@ -86,11 +107,17 @@ exports.getCashInCashOutUIState = (0, toolkit_1.createSelector)((state) => state
86
107
  exports.getCashInCashOutForSelectedRange = (0, toolkit_1.createSelector)((state) => state.accountState, (state) => state.accountGroupState, (state) => state.cashInCashOutState, (accountState, accountGroupState, cashInCashOutState) => {
87
108
  const { timeframe, selectedCOABalancesRange, selectedAdditionalBalances } = cashInCashOutState.uiState;
88
109
  const noFilter = (0, coaBalancesFilter_1.newBalancesFilter)(cashInCashOutState.firstMonthOfFY, timeframe, selectedCOABalancesRange.numberOfPeriods, selectedCOABalancesRange.thisPeriod, 'ascending_date', selectedAdditionalBalances);
89
- return (0, exports.getCashInCashOut)(accountState, accountGroupState, cashInCashOutState, noFilter);
110
+ return (0, exports.getCashInCashOut)(accountState, accountGroupState, cashInCashOutState, noFilter,
111
+ // Detail selectors read the custom slot when the detail is in custom mode;
112
+ // the dashboard's getCashInCashOutLast4Periods does not.
113
+ cashInCashOutState.uiState.customTimeframe != null);
90
114
  });
91
115
  exports.getCashInCashOutForHighlightedRange = (0, toolkit_1.createSelector)((state) => state.accountState, (state) => state.accountGroupState, (state) => state.cashInCashOutState, (accountState, accountGroupState, cashInCashOutState) => {
92
116
  const { timeframe, highlightedCOABalancesRange, selectedAdditionalBalances, maxNumOfPeriodsToHighlight, } = cashInCashOutState.uiState;
93
117
  const filter = (0, coaBalancesFilter_1.newBalancesFilter)(cashInCashOutState.firstMonthOfFY, timeframe, highlightedCOABalancesRange?.numberOfPeriods ??
94
118
  maxNumOfPeriodsToHighlight, highlightedCOABalancesRange?.thisPeriod, 'ascending_date', selectedAdditionalBalances);
95
- return (0, exports.getCashInCashOut)(accountState, accountGroupState, cashInCashOutState, filter);
119
+ return (0, exports.getCashInCashOut)(accountState, accountGroupState, cashInCashOutState, filter,
120
+ // Detail selectors read the custom slot when the detail is in custom mode;
121
+ // the dashboard's getCashInCashOutLast4Periods does not.
122
+ cashInCashOutState.uiState.customTimeframe != null);
96
123
  });
@@ -1,5 +1,5 @@
1
1
  import { COABalanceGrouped, COABalanceGroupedWithIDs } from '../../commonStateTypes/coaBalance/coaBalance';
2
- import { FetchedState, ID } from '../../commonStateTypes/common';
2
+ import { FetchState, FetchedState, ID } from '../../commonStateTypes/common';
3
3
  import { ReportUIState } from '../../commonStateTypes/viewAndReport/reportUIState';
4
4
  import { Report } from '../../commonStateTypes/viewAndReport/viewAndReport';
5
5
  import { InsightSummary } from '../../entity/insights/insightSummary';
@@ -15,5 +15,9 @@ export interface CashInCashOutState extends FetchedState, Report {
15
15
  uiState: CashInCashOutUIState;
16
16
  cashIn?: COABalanceGroupedWithIDs;
17
17
  cashOut?: COABalanceGroupedWithIDs;
18
+ customCashIn?: COABalanceGroupedWithIDs;
19
+ customCashOut?: COABalanceGroupedWithIDs;
20
+ customFetchState?: FetchState;
21
+ customNetCashFlow?: COABalanceGrouped;
18
22
  netCashFlow?: COABalanceGrouped;
19
23
  }
@@ -9,10 +9,16 @@ export declare const fetchCashPositionEpic: (actions$: ActionsObservable<ActionT
9
9
  classesViewParentId: import("../../commonStateTypes/classesView/nestedClassID").ClassesViewParentID | undefined;
10
10
  updateType: import("../..").UpdateType;
11
11
  }, never> | {
12
- payload: import("../../responsePayload").ZeniReportData<import("./cashPositionPayload").CashPositionPayload>;
12
+ payload: {
13
+ reportData: import("../../responsePayload").ZeniReportData<import("./cashPositionPayload").CashPositionPayload>;
14
+ isCustomDateRange: boolean;
15
+ };
13
16
  type: "cashPosition/updateCashPosition";
14
17
  } | {
15
- payload: import("../../zeniAPIStatus").ZeniAPIStatus<Record<string, unknown>>;
18
+ payload: {
19
+ error: import("../../zeniAPIStatus").ZeniAPIStatus<Record<string, unknown>>;
20
+ isCustomDateRange: boolean;
21
+ };
16
22
  type: "cashPosition/updateCashPositionFailure";
17
23
  } | {
18
24
  payload: {
@@ -6,18 +6,26 @@ const operators_1 = require("rxjs/operators");
6
6
  const accountReducer_1 = require("../../entity/account/accountReducer");
7
7
  const responsePayload_1 = require("../../responsePayload");
8
8
  const cashPositionReducer_1 = require("./cashPositionReducer");
9
- const fetchCashPositionEpic = (actions$, state, zeniAPI) => actions$.pipe((0, operators_1.filter)(cashPositionReducer_1.fetchCashPosition.match), (0, operators_1.switchMap)((action) => zeniAPI
10
- .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/reports/cash_position?query=${encodeURIComponent(`{"is_full_response":${action.payload.fetchFullReport}}`)}`)
11
- .pipe((0, operators_1.mergeMap)((response) => {
12
- if ((0, responsePayload_1.isSuccessResponse)(response)) {
13
- return (0, rxjs_1.of)((0, accountReducer_1.updateAccounts)(response.data?.report.accounts ?? [], 'cash_position'), (0, cashPositionReducer_1.updateCashPosition)(response.data), // eslint-disable-line @typescript-eslint/no-non-null-assertion
14
- (0, cashPositionReducer_1.updateCashPositionThisPeriod)({
15
- thisPeriod: state.value.reportUIOptionsState.thisPeriod,
16
- }));
9
+ const fetchCashPositionEpic = (actions$, state, zeniAPI) => actions$.pipe((0, operators_1.filter)(cashPositionReducer_1.fetchCashPosition.match), (0, operators_1.switchMap)((action) => {
10
+ const queryValue = { is_full_response: action.payload.fetchFullReport };
11
+ const isCustomDateRange = action.payload.startDate != null && action.payload.endDate != null;
12
+ if (isCustomDateRange) {
13
+ queryValue.custom_start_date = action.payload.startDate;
14
+ queryValue.custom_end_date = action.payload.endDate;
17
15
  }
18
- else {
19
- return (0, rxjs_1.of)((0, cashPositionReducer_1.updateCashPositionFailure)(response.status));
20
- }
21
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, cashPositionReducer_1.updateCashPositionFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected error', 'Cash Position REST API call errored out' +
22
- JSON.stringify(error))))))));
16
+ return zeniAPI
17
+ .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/reports/cash_position?query=${encodeURIComponent(JSON.stringify(queryValue))}`)
18
+ .pipe((0, operators_1.mergeMap)((response) => {
19
+ if ((0, responsePayload_1.isSuccessResponse)(response)) {
20
+ return (0, rxjs_1.of)((0, accountReducer_1.updateAccounts)(response.data?.report.accounts ?? [], 'cash_position'), (0, cashPositionReducer_1.updateCashPosition)(response.data, isCustomDateRange), // eslint-disable-line @typescript-eslint/no-non-null-assertion
21
+ (0, cashPositionReducer_1.updateCashPositionThisPeriod)({
22
+ thisPeriod: state.value.reportUIOptionsState.thisPeriod,
23
+ }));
24
+ }
25
+ else {
26
+ return (0, rxjs_1.of)((0, cashPositionReducer_1.updateCashPositionFailure)(response.status, isCustomDateRange));
27
+ }
28
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, cashPositionReducer_1.updateCashPositionFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected error', 'Cash Position REST API call errored out' +
29
+ JSON.stringify(error)), isCustomDateRange))));
30
+ }));
23
31
  exports.fetchCashPositionEpic = fetchCashPositionEpic;
@@ -9,11 +9,22 @@ export declare const defaultPeriods: {
9
9
  numberOfPeriods: number;
10
10
  };
11
11
  export declare const initialState: CashPositionState;
12
- export declare const fetchCashPosition: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[fetchFullReport?: boolean | undefined], {
12
+ export declare const fetchCashPosition: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[fetchFullReport?: boolean | undefined, startDate?: string | undefined, endDate?: string | undefined], {
13
13
  fetchFullReport: boolean;
14
- }, "cashPosition/fetchCashPosition", never, never>, updateCashPosition: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniReportData<CashPositionPayload>, "cashPosition/updateCashPosition">, updateCashPositionFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "cashPosition/updateCashPositionFailure">, updateCashPositionTimeFrame: import("@reduxjs/toolkit").ActionCreatorWithPayload<"month" | "year" | "quarter", "cashPosition/updateCashPositionTimeFrame">, updateCashPositionCOABalancesRange: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
14
+ startDate: string | undefined;
15
+ endDate: string | undefined;
16
+ }, "cashPosition/fetchCashPosition", never, never>, updateCashPosition: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[reportData: ZeniReportData<CashPositionPayload>, isCustomDateRange?: boolean | undefined], {
17
+ reportData: ZeniReportData<CashPositionPayload>;
18
+ isCustomDateRange: boolean;
19
+ }, "cashPosition/updateCashPosition", never, never>, updateCashPositionFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[error: ZeniAPIStatus<Record<string, unknown>>, isCustomDateRange?: boolean | undefined], {
20
+ error: ZeniAPIStatus<Record<string, unknown>>;
21
+ isCustomDateRange: boolean;
22
+ }, "cashPosition/updateCashPositionFailure", never, never>, updateCashPositionTimeFrame: import("@reduxjs/toolkit").ActionCreatorWithPayload<"month" | "year" | "quarter", "cashPosition/updateCashPositionTimeFrame">, updateCashPositionCOABalancesRange: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
15
23
  selectedCOABalancesRange: COABalancesRange;
24
+ customEndDate?: string;
25
+ customStartDate?: string;
16
26
  highlightedCOABalancesRange?: COABalancesRangeWithThisPeriod;
27
+ isCustomDateRange?: boolean;
17
28
  }, "cashPosition/updateCashPositionCOABalancesRange">, updateCashPositionAdditionalBalancesSelection: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
18
29
  additionalBalances: COABalanceType[];
19
30
  isCompareModeOn: boolean;