@zeniai/client-epic-state 5.2.93 → 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 (82) 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/esm/commonStateTypes/timeframeTick.js +1 -0
  6. package/lib/esm/view/balanceSheet/balanceSheetForTimeframeEpic.js +4 -0
  7. package/lib/esm/view/balanceSheet/balanceSheetReducer.js +8 -2
  8. package/lib/esm/view/cashFlow/cashFlowForTimeframeEpic.js +4 -0
  9. package/lib/esm/view/cashFlow/cashFlowReducer.js +2 -2
  10. package/lib/esm/view/cashInCashOut/cashInCashOutEpic.js +22 -14
  11. package/lib/esm/view/cashInCashOut/cashInCashOutReducer.js +161 -41
  12. package/lib/esm/view/cashInCashOut/cashInCashOutSelector.js +42 -15
  13. package/lib/esm/view/cashPosition/cashPositionEpic.js +21 -13
  14. package/lib/esm/view/cashPosition/cashPositionReducer.js +155 -44
  15. package/lib/esm/view/cashPosition/cashPositionSelector.js +28 -9
  16. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeEpic.js +7 -7
  17. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.js +25 -10
  18. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeReducer.js +184 -40
  19. package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeSelector.js +26 -8
  20. package/lib/esm/view/opEx/opExEpic.js +7 -7
  21. package/lib/esm/view/opEx/opExForTimeFrameEpic.js +21 -6
  22. package/lib/esm/view/opEx/opExReducer.js +169 -32
  23. package/lib/esm/view/opEx/opExSelector.js +28 -10
  24. package/lib/esm/view/profitAndLoss/profitAndLossForTimeframeEpic.js +4 -0
  25. package/lib/esm/view/profitAndLoss/profitAndLossReducer.js +9 -2
  26. package/lib/esm/view/revenue/revenueEpic.js +7 -7
  27. package/lib/esm/view/revenue/revenueForTimeframeEpic.js +23 -8
  28. package/lib/esm/view/revenue/revenueReducer.js +183 -40
  29. package/lib/esm/view/revenue/revenueSelector.js +30 -10
  30. package/lib/view/balanceSheet/balanceSheetForTimeframeEpic.js +4 -0
  31. package/lib/view/balanceSheet/balanceSheetReducer.d.ts +3 -1
  32. package/lib/view/balanceSheet/balanceSheetReducer.js +8 -2
  33. package/lib/view/cashFlow/cashFlowForTimeframeEpic.js +4 -0
  34. package/lib/view/cashFlow/cashFlowReducer.d.ts +3 -1
  35. package/lib/view/cashFlow/cashFlowReducer.js +2 -2
  36. package/lib/view/cashInCashOut/cashInCashOutEpic.d.ts +8 -2
  37. package/lib/view/cashInCashOut/cashInCashOutEpic.js +22 -14
  38. package/lib/view/cashInCashOut/cashInCashOutReducer.d.ts +13 -1
  39. package/lib/view/cashInCashOut/cashInCashOutReducer.js +161 -41
  40. package/lib/view/cashInCashOut/cashInCashOutSelector.d.ts +2 -1
  41. package/lib/view/cashInCashOut/cashInCashOutSelector.js +42 -15
  42. package/lib/view/cashInCashOut/cashInCashOutState.d.ts +5 -1
  43. package/lib/view/cashPosition/cashPositionEpic.d.ts +8 -2
  44. package/lib/view/cashPosition/cashPositionEpic.js +21 -13
  45. package/lib/view/cashPosition/cashPositionReducer.d.ts +13 -2
  46. package/lib/view/cashPosition/cashPositionReducer.js +155 -44
  47. package/lib/view/cashPosition/cashPositionSelector.d.ts +2 -1
  48. package/lib/view/cashPosition/cashPositionSelector.js +28 -9
  49. package/lib/view/cashPosition/cashPositionState.d.ts +5 -1
  50. package/lib/view/financeStatement/financeStatementEpic.d.ts +6 -0
  51. package/lib/view/netBurnOrIncome/fetchNetBurnOrIncomeWithForecastEpic.d.ts +1 -0
  52. package/lib/view/netBurnOrIncome/netBurnOrIncomeEpic.js +7 -7
  53. package/lib/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.d.ts +2 -1
  54. package/lib/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.js +26 -11
  55. package/lib/view/netBurnOrIncome/netBurnOrIncomeReducer.d.ts +12 -3
  56. package/lib/view/netBurnOrIncome/netBurnOrIncomeReducer.js +184 -40
  57. package/lib/view/netBurnOrIncome/netBurnOrIncomeSelector.d.ts +1 -1
  58. package/lib/view/netBurnOrIncome/netBurnOrIncomeSelector.js +26 -8
  59. package/lib/view/netBurnOrIncome/netBurnOrIncomeState.d.ts +8 -0
  60. package/lib/view/opEx/fetchOpExWithForecastEpic.d.ts +1 -0
  61. package/lib/view/opEx/opExEpic.js +7 -7
  62. package/lib/view/opEx/opExForTimeFrameEpic.d.ts +2 -1
  63. package/lib/view/opEx/opExForTimeFrameEpic.js +22 -7
  64. package/lib/view/opEx/opExReducer.d.ts +12 -3
  65. package/lib/view/opEx/opExReducer.js +168 -31
  66. package/lib/view/opEx/opExSelector.d.ts +1 -1
  67. package/lib/view/opEx/opExSelector.js +28 -10
  68. package/lib/view/opEx/opExState.d.ts +6 -0
  69. package/lib/view/profitAndLoss/profitAndLossForTimeframeEpic.js +4 -0
  70. package/lib/view/profitAndLoss/profitAndLossReducer.d.ts +3 -1
  71. package/lib/view/profitAndLoss/profitAndLossReducer.js +9 -2
  72. package/lib/view/reportUIOptions/updateReportUIOptionCOABalancesRangeEpic.d.ts +15 -0
  73. package/lib/view/revenue/fetchRevenueWithForecastEpic.d.ts +1 -0
  74. package/lib/view/revenue/revenueEpic.js +7 -7
  75. package/lib/view/revenue/revenueForTimeframeEpic.d.ts +2 -1
  76. package/lib/view/revenue/revenueForTimeframeEpic.js +24 -9
  77. package/lib/view/revenue/revenueReducer.d.ts +12 -3
  78. package/lib/view/revenue/revenueReducer.js +182 -39
  79. package/lib/view/revenue/revenueSelector.d.ts +1 -1
  80. package/lib/view/revenue/revenueSelector.js +30 -10
  81. package/lib/view/revenue/revenueState.d.ts +8 -0
  82. package/package.json +1 -1
@@ -70,8 +70,16 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
70
70
  initialState: exports.initialState,
71
71
  reducers: {
72
72
  fetchOpEx: {
73
- prepare(fetchFullReport = false, forecastId, cacheOverride = false) {
74
- return { payload: { fetchFullReport, forecastId, cacheOverride } };
73
+ prepare(fetchFullReport = false, forecastId, cacheOverride = false, startDate, endDate) {
74
+ return {
75
+ payload: {
76
+ fetchFullReport,
77
+ forecastId,
78
+ cacheOverride,
79
+ startDate,
80
+ endDate,
81
+ },
82
+ };
75
83
  },
76
84
  reducer(
77
85
  //eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -82,22 +90,49 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
82
90
  },
83
91
  },
84
92
  fetchOpExReportForTimeframe: {
85
- prepare(timeframe, forecastId, fetchFullReport = true, cacheOverride = false) {
93
+ prepare(timeframe, forecastId, fetchFullReport = true, cacheOverride = false, startDate, endDate) {
86
94
  return {
87
- payload: { forecastId, timeframe, fetchFullReport, cacheOverride },
95
+ payload: {
96
+ forecastId,
97
+ timeframe,
98
+ fetchFullReport,
99
+ cacheOverride,
100
+ startDate,
101
+ endDate,
102
+ },
88
103
  };
89
104
  },
90
105
  reducer(draft, action) {
91
106
  const timeframe = action.payload.timeframe;
92
107
  const opExReport = getState(draft, draft.uiState.isForecastModeOn, action.payload.forecastId);
93
- const fetchState = {
94
- ...opExReport.fetchState,
95
- };
96
- fetchState[timeframe] = {
97
- fetchState: 'In-Progress',
98
- error: undefined,
99
- };
100
- updateState(draft, action.payload.forecastId, { fetchState });
108
+ // Route by the fetch's own dates, not the global flag: a custom fetch
109
+ // (carries start/end) marks customFetchState so the shared fetchState the
110
+ // dashboard reads is never left In-Progress by a detail-screen fetch.
111
+ const isCustomDateRange = action.payload.startDate != null && action.payload.endDate != null;
112
+ if (isCustomDateRange) {
113
+ const customFetchState = {
114
+ ...(opExReport.customFetchState ?? {
115
+ month: { fetchState: 'Not-Started', error: undefined },
116
+ quarter: { fetchState: 'Not-Started', error: undefined },
117
+ year: { fetchState: 'Not-Started', error: undefined },
118
+ }),
119
+ };
120
+ customFetchState[timeframe] = {
121
+ fetchState: 'In-Progress',
122
+ error: undefined,
123
+ };
124
+ updateState(draft, action.payload.forecastId, { customFetchState });
125
+ }
126
+ else {
127
+ const fetchState = {
128
+ ...opExReport.fetchState,
129
+ };
130
+ fetchState[timeframe] = {
131
+ fetchState: 'In-Progress',
132
+ error: undefined,
133
+ };
134
+ updateState(draft, action.payload.forecastId, { fetchState });
135
+ }
101
136
  },
102
137
  },
103
138
  fetchOpExWithForecast: {
@@ -127,25 +162,44 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
127
162
  },
128
163
  },
129
164
  updateOpExForTimeframe(draft, action) {
130
- doUpdatedOpExReport(draft, action.payload.forecastId, action.payload.timeframe, action.payload.report);
165
+ doUpdatedOpExReport(draft, action.payload.forecastId, action.payload.timeframe, action.payload.report, action.payload.isCustomDateRange === true);
131
166
  },
132
167
  updateOpExFailureForTimeframe: {
133
- prepare(error, forecastId, timeframe) {
168
+ prepare(error, forecastId, timeframe, isCustomDateRange = false) {
134
169
  return {
135
170
  payload: {
136
171
  error,
137
172
  forecastId,
138
173
  timeframe,
174
+ isCustomDateRange,
139
175
  },
140
176
  };
141
177
  },
142
178
  reducer(draft, action) {
143
179
  const timeframe = action.payload.timeframe;
144
180
  const opExReport = getState(draft, draft.uiState.isForecastModeOn, draft.uiState.selectedForecast?.id);
145
- opExReport.fetchState[timeframe] = {
146
- fetchState: 'Error',
147
- error: action.payload.error,
148
- };
181
+ // Route the error like the request/success: a custom (dated) fetch's
182
+ // failure lands in customFetchState so the shared default the dashboard
183
+ // reads isn't marked Error, and the detail's customFetchState isn't left
184
+ // stuck In-Progress.
185
+ if (action.payload.isCustomDateRange === true) {
186
+ const customFetchState = opExReport.customFetchState ?? {
187
+ month: { fetchState: 'Not-Started', error: undefined },
188
+ quarter: { fetchState: 'Not-Started', error: undefined },
189
+ year: { fetchState: 'Not-Started', error: undefined },
190
+ };
191
+ customFetchState[timeframe] = {
192
+ fetchState: 'Error',
193
+ error: action.payload.error,
194
+ };
195
+ opExReport.customFetchState = customFetchState;
196
+ }
197
+ else {
198
+ opExReport.fetchState[timeframe] = {
199
+ fetchState: 'Error',
200
+ error: action.payload.error,
201
+ };
202
+ }
149
203
  updateState(draft, action.payload.forecastId, opExReport);
150
204
  },
151
205
  },
@@ -163,8 +217,12 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
163
217
  action.payload.additionalBalances.length != 0
164
218
  ? true
165
219
  : false;
166
- // Note: We don't want to update selected & highlighted ranges in Ui State when forecast is ON
167
- if (dataAvailable != null && draft.uiState.isForecastModeOn === false) {
220
+ // Note: We don't want to update selected & highlighted ranges in Ui State when forecast is ON.
221
+ // Also skip when a custom date range is driving the window — otherwise the
222
+ // auto-window re-derivation below clamps the user's range to the default.
223
+ if (dataAvailable != null &&
224
+ draft.uiState.isForecastModeOn === false &&
225
+ draft.uiState.customTimeframe == null) {
168
226
  const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(opExReport.firstMonthOfFY, draft.uiState.timeframe, [opExBalancesByTimeframe], dataAvailable);
169
227
  const thisPeriod = (0, thisPeriodHelpers_1.extractThisPeriod)(opExReport.firstMonthOfFY, draft.uiState.timeframe, draft.uiState.selectedCOABalancesRange, coaBalances);
170
228
  if (thisPeriod != null &&
@@ -193,6 +251,48 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
193
251
  }
194
252
  },
195
253
  updateOpExCOABalancesRange(draft, action) {
254
+ if (action.payload.isCustomDateRange != null) {
255
+ if (action.payload.isCustomDateRange === true) {
256
+ // Convert the string dates the action carries to ZeniDate values and
257
+ // store as a single customTimeframe. Presence signals custom-mode active.
258
+ draft.uiState.customTimeframe =
259
+ action.payload.customStartDate != null &&
260
+ action.payload.customEndDate != null
261
+ ? {
262
+ startDate: (0, zeniDayJS_1.date)(action.payload.customStartDate),
263
+ endDate: (0, zeniDayJS_1.date)(action.payload.customEndDate),
264
+ }
265
+ : undefined;
266
+ // Invalidate the shared default-window fetchState so dashboardEpic
267
+ // refetches the default data on the next dashboard visit — the custom
268
+ // fetch writes into the shared section store, and this lets the card
269
+ // self-heal without a reload. The detail screen reads customFetchState.
270
+ draft.opEx.fetchState = {
271
+ month: { fetchState: 'Not-Started', error: undefined },
272
+ quarter: { fetchState: 'Not-Started', error: undefined },
273
+ year: { fetchState: 'Not-Started', error: undefined },
274
+ };
275
+ }
276
+ else {
277
+ draft.uiState.customTimeframe = undefined;
278
+ }
279
+ }
280
+ // A custom date range drives the visible window directly: honor the exact
281
+ // numberOfPeriods + thisPeriod from the payload instead of re-deriving
282
+ // (which clamps the range to the available/non-zero periods).
283
+ if (draft.uiState.customTimeframe != null) {
284
+ draft.uiState.selectedCOABalancesRange =
285
+ action.payload.selectedCOABalancesRange;
286
+ if (action.payload.highlightedCOABalancesRange != null) {
287
+ // Clamp the highlight to the same cap the non-custom path enforces so
288
+ // a wide custom range doesn't highlight all N periods at once.
289
+ draft.uiState.highlightedCOABalancesRange = {
290
+ ...action.payload.highlightedCOABalancesRange,
291
+ numberOfPeriods: Math.min(action.payload.highlightedCOABalancesRange.numberOfPeriods, draft.uiState.maxNumOfPeriodsToHighlight),
292
+ };
293
+ }
294
+ return;
295
+ }
196
296
  // Note: When thisPeriod changes the selected and highlighted balances ranges should be calculated based on full report period.
197
297
  const opExReport = getState(draft, undefined, undefined);
198
298
  const { opExBalancesByTimeframe, dataAvailable } = opExReport;
@@ -237,6 +337,13 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
237
337
  }
238
338
  },
239
339
  updateOpExThisPeriod(draft, action) {
340
+ // In custom-date mode the picker drives the window; skip re-deriving the
341
+ // selected/highlighted ranges from the default dataAvailable (the epic
342
+ // re-dispatches the default thisPeriod on every month response, which
343
+ // would otherwise clamp the custom window back to the default).
344
+ if (draft.uiState.customTimeframe != null) {
345
+ return;
346
+ }
240
347
  // Note: When thisPeriod changes the selected and highlighted balances ranges should be calculated based on full report period.
241
348
  const opExReport = getState(draft, undefined, undefined);
242
349
  const { opExBalancesByTimeframe, dataAvailable } = opExReport;
@@ -315,7 +422,7 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
315
422
  draft.uiState.maxNumOfPeriodsToHighlight =
316
423
  exports.initialState.uiState.maxNumOfPeriodsToHighlight;
317
424
  }
318
- if (dataAvailable != null) {
425
+ if (dataAvailable != null && draft.uiState.customTimeframe == null) {
319
426
  const timeframe = draft.uiState.timeframe;
320
427
  const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(opExReport.firstMonthOfFY, timeframe, [opExBalancesByTimeframe], dataAvailable);
321
428
  const selectionRanges = (0, getSelectedAndHighlightedRanges_1.getInitialSelectedAndHighlightedRanges)({
@@ -343,27 +450,57 @@ const operatingExpenses = (0, toolkit_1.createSlice)({
343
450
  });
344
451
  _a = operatingExpenses.actions, exports.fetchOpEx = _a.fetchOpEx, exports.fetchOpExReportForTimeframe = _a.fetchOpExReportForTimeframe, exports.updateOpExForTimeframe = _a.updateOpExForTimeframe, exports.updateOpExFailureForTimeframe = _a.updateOpExFailureForTimeframe, exports.updateOpExCOABalancesRange = _a.updateOpExCOABalancesRange, exports.updateOpExAdditionalBalancesSelection = _a.updateOpExAdditionalBalancesSelection, exports.updateOpExThisPeriod = _a.updateOpExThisPeriod, exports.updateOpExDownloadState = _a.updateOpExDownloadState, exports.updateOpExUIState = _a.updateOpExUIState, exports.opExToggleForecastMode = _a.opExToggleForecastMode, exports.fetchOpExWithForecast = _a.fetchOpExWithForecast, exports.waitForForecastListThenFetchOpExWithForecast = _a.waitForForecastListThenFetchOpExWithForecast, exports.updateOpExTimeFrame = _a.updateOpExTimeFrame;
345
452
  exports.default = operatingExpenses.reducer;
346
- const doUpdatedOpExReport = (draft, forecastId, timeframe, data) => {
453
+ const doUpdatedOpExReport = (draft, forecastId, timeframe, data, isCustomDateRange) => {
347
454
  const report = (0, viewAndReportPayloadv2_1.mapReportPayloadV2ToReportV2)(data.report);
348
455
  const opExReport = getState(draft, draft.uiState.isForecastModeOn, forecastId);
349
456
  const { currency, expenses, insights } = data.report;
350
457
  const { firstMonthOfFY, bookCloseDate, dataAvailable } = report;
351
458
  const expensesCOABalance = (0, coaBalancePayload_1.mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod)(expenses, currency, timeframe);
352
- opExReport.opExBalancesByTimeframe = Object.assign({}, opExReport.opExBalancesByTimeframe, expensesCOABalance);
353
- if (timeframe === 'month' && insights != null) {
459
+ // Route custom-date results (identified by the fetch's own dates, not the
460
+ // global flag) to the separate slot so the dashboard card (which reads
461
+ // opExBalancesByTimeframe) keeps the default window.
462
+ if (isCustomDateRange) {
463
+ opExReport.customOpExBalancesByTimeframe = Object.assign({}, opExReport.customOpExBalancesByTimeframe, expensesCOABalance);
464
+ }
465
+ else {
466
+ opExReport.opExBalancesByTimeframe = Object.assign({}, opExReport.opExBalancesByTimeframe, expensesCOABalance);
467
+ }
468
+ // Insights are shared (read by the dashboard card); a custom slice must not
469
+ // overwrite them.
470
+ if (timeframe === 'month' && insights != null && !isCustomDateRange) {
354
471
  // we will get insights only in the month timeframe api
355
472
  opExReport.insights = (0, insightSummaryPayload_1.mapInsightsPayloadtoInsightsState)(insights);
356
473
  }
357
- opExReport.dataAvailable = dataAvailable
358
- ? dataAvailable
359
- : (0, dataAvailable_1.getDataAvailableDateRange)(expensesCOABalance);
474
+ // Don't let a custom slice shrink the shared dataAvailable the dashboard uses
475
+ // for its period count; a default fetch always updates it, a custom one only
476
+ // populates it on first load (when nothing has set it yet).
477
+ if (!isCustomDateRange || opExReport.dataAvailable == null) {
478
+ opExReport.dataAvailable = dataAvailable
479
+ ? dataAvailable
480
+ : (0, dataAvailable_1.getDataAvailableDateRange)(expensesCOABalance);
481
+ }
360
482
  opExReport.firstMonthOfFY = firstMonthOfFY;
361
483
  opExReport.bookCloseDate = bookCloseDate;
362
- opExReport.fetchState[timeframe].fetchState = 'Completed';
363
- opExReport.fetchState[timeframe].error = undefined;
484
+ // Mark the matching fetchState Completed. A custom fetch uses customFetchState so
485
+ // dashboardEpic's Completed check on the default fetchState is untouched.
486
+ if (isCustomDateRange) {
487
+ const customFetchState = opExReport.customFetchState ?? {
488
+ month: { fetchState: 'Not-Started', error: undefined },
489
+ quarter: { fetchState: 'Not-Started', error: undefined },
490
+ year: { fetchState: 'Not-Started', error: undefined },
491
+ };
492
+ customFetchState[timeframe] = { fetchState: 'Completed', error: undefined };
493
+ opExReport.customFetchState = customFetchState;
494
+ }
495
+ else {
496
+ opExReport.fetchState[timeframe].fetchState = 'Completed';
497
+ opExReport.fetchState[timeframe].error = undefined;
498
+ }
364
499
  if (opExReport.dataAvailable != null &&
365
- forecastId == null // Note: We don't want to update selected & highlighted ranges in Ui State when forecast is ON
366
- ) {
500
+ forecastId == null && // Note: We don't want to update selected & highlighted ranges in Ui State when forecast is ON
501
+ // A custom date range drives the window; don't reset it to the default on
502
+ // every report receipt (this is what clamped wide ranges back to 8).
503
+ draft.uiState.customTimeframe == null) {
367
504
  const timeframe = draft.uiState.timeframe;
368
505
  const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(opExReport.firstMonthOfFY, timeframe, [expensesCOABalance], opExReport.dataAvailable);
369
506
  const selectionRanges = (0, getSelectedAndHighlightedRanges_1.getInitialSelectedAndHighlightedRanges)({
@@ -4,7 +4,7 @@ import { RootState } from '../../rootStateTypes';
4
4
  import { OpExReport, OpExUIStateSelectorView } from './opExSelectorTypes';
5
5
  import { OpExWithForecastState } from './opExState';
6
6
  export declare const getOperatingExpensesUIState: (state: RootState) => OpExUIStateSelectorView;
7
- export declare const getOperatingExpensesReport: (state: RootState, filter: COABalancesFilter, forecastId?: ID) => OpExReport;
7
+ export declare const getOperatingExpensesReport: (state: RootState, filter: COABalancesFilter, forecastId?: ID, readCustomRangeSlot?: boolean) => OpExReport;
8
8
  export declare const getOperatingExpensesForSelectedRange: (state: RootState) => OpExReport;
9
9
  export declare const getOperatingExpensesForHighlightedRange: (state: RootState) => OpExReport;
10
10
  export declare const getOperatingExpensesReportFetchState: (forecastId: ID | undefined, opExState: OpExWithForecastState) => FetchStateAndError;
@@ -61,8 +61,10 @@ exports.getOperatingExpensesUIState = (0, toolkit_1.createSelector)((state) => s
61
61
  reportFormat,
62
62
  };
63
63
  });
64
- const getOpExBalancesInTimeFrame = (0, toolkit_1.createSelector)((state) => state.opExState, (state) => state.sectionAccountsViewState, (opExState, sectionState) => {
65
- const reportId = 'operating_expenses';
64
+ const getOpExBalancesInTimeFrame = (0, toolkit_1.createSelector)((state) => state.opExState, (state) => state.sectionAccountsViewState, (_state, readCustomRangeSlot) => readCustomRangeSlot === true, (opExState, sectionState, readCustomRangeSlot) => {
65
+ // Custom detail reads its own section-accounts slot so a default fetch can't
66
+ // overwrite the partial-period data; the dashboard reads the default slot.
67
+ const reportId = (0, opExForTimeFrameEpic_1.reportIdUniqueKey)(undefined, readCustomRangeSlot && opExState.uiState.customTimeframe != null);
66
68
  const opExStateReport = (0, opExReducer_1.getState)(opExState, false, undefined);
67
69
  if (opExStateReport.dataAvailable != null) {
68
70
  const noFilter = (0, coaBalancesFilter_1.newBalancesFilterForDateRange)(opExStateReport.firstMonthOfFY, opExState.uiState.timeframe, opExStateReport.dataAvailable, 'ascending_date', []);
@@ -75,14 +77,25 @@ const getOpExBalancesInTimeFrame = (0, toolkit_1.createSelector)((state) => stat
75
77
  }
76
78
  return [];
77
79
  });
78
- exports.getOperatingExpensesReport = (0, toolkit_1.createSelector)((state) => state, (state) => state.accountState, (state) => state.accountGroupState, (state) => state.sectionAccountsViewState, (state) => state.opExState, (state) => state.forecastState, (state) => state.forecastListState, (_state, filter) => filter, (_state, _filter, forecastId) => forecastId, (state, accountState, accountGroupState, sectionsState, opExState, forecastState, forecastListState, filter, forecastId) => {
80
+ exports.getOperatingExpensesReport = (0, toolkit_1.createSelector)((state) => state, (state) => state.accountState, (state) => state.accountGroupState, (state) => state.sectionAccountsViewState, (state) => state.opExState, (state) => state.forecastState, (state) => state.forecastListState, (_state, filter) => filter, (_state, _filter, forecastId) => forecastId, (_state, _filter, _forecastId, readCustomRangeSlot) => readCustomRangeSlot === true, (state, accountState, accountGroupState, sectionsState, opExState, forecastState, forecastListState, filter, forecastId, readCustomRangeSlot) => {
79
81
  const opEx = (0, opExReducer_1.getState)(opExState, opExState.uiState.isForecastModeOn, forecastId);
82
+ // The detail screen opts into customFetchState so its Completed check fires
83
+ // off the custom fetch; the dashboard (no flag) reads the shared fetchState,
84
+ // which custom-mode activation reset to Not-Started so dashboardEpic refetches.
85
+ const activeFetchState = readCustomRangeSlot &&
86
+ opExState.uiState.customTimeframe != null &&
87
+ opEx.customFetchState != null
88
+ ? opEx.customFetchState
89
+ : opEx.fetchState;
80
90
  const fetchState = (0, reduceFetchState_1.reduceAnyFetchState)([
81
- opEx.fetchState.month,
82
- opEx.fetchState.quarter,
83
- opEx.fetchState.year,
91
+ activeFetchState.month,
92
+ activeFetchState.quarter,
93
+ activeFetchState.year,
84
94
  ]);
85
- const reportId = (0, opExForTimeFrameEpic_1.reportIdUniqueKey)(forecastId);
95
+ // Custom detail reads the isolated custom section-accounts slot; dashboard
96
+ // (no flag) reads the default slot, so a default fetch can't clobber it.
97
+ const useCustomRange = readCustomRangeSlot && opExState.uiState.customTimeframe != null;
98
+ const reportId = (0, opExForTimeFrameEpic_1.reportIdUniqueKey)(forecastId, useCustomRange);
86
99
  const sections = {};
87
100
  const calculatedSections = {};
88
101
  if (fetchState.fetchState === 'Completed') {
@@ -93,7 +106,7 @@ exports.getOperatingExpensesReport = (0, toolkit_1.createSelector)((state) => st
93
106
  }, filter);
94
107
  });
95
108
  }
96
- const balancesInTimeframe = getOpExBalancesInTimeFrame(state);
109
+ const balancesInTimeframe = getOpExBalancesInTimeFrame(state, useCustomRange);
97
110
  const allTimeframeTicks = balancesInTimeframe.map((balance) => (0, timeframeTick_1.toTimeframeTick)(balance));
98
111
  const forecast = opEx.forecastId != null
99
112
  ? (0, forecastSelector_1.getForecast)(forecastState, opEx.forecastId)
@@ -120,6 +133,8 @@ exports.getOperatingExpensesReport = (0, toolkit_1.createSelector)((state) => st
120
133
  allTimeframeTicks,
121
134
  balancesInTimeframe,
122
135
  availableNumberOfPeriods: (0, dataAvailable_1.getNumberOfPeriods)(opEx.firstMonthOfFY, filter.timeframe, opEx.dataAvailable),
136
+ // Surface the saved custom timeframe so the detail picker can restore them.
137
+ customTimeframe: opExState.uiState.customTimeframe,
123
138
  };
124
139
  });
125
140
  exports.getOperatingExpensesForSelectedRange = (0, toolkit_1.createSelector)((state) => state, (state) => state.opExState, (state, opExWithForecastState) => {
@@ -129,7 +144,10 @@ exports.getOperatingExpensesForSelectedRange = (0, toolkit_1.createSelector)((st
129
144
  selectedForecast?.id != null &&
130
145
  (0, exports.getOperatingExpensesReportFetchState)(selectedForecast.id, opExWithForecastState).fetchState === 'Completed'
131
146
  ? getOpExWithForecastOnDataAvailableDateRange(state, noFilter, selectedForecast?.id)
132
- : (0, exports.getOperatingExpensesReport)(state, noFilter, opExWithForecastState.uiState.selectedForecast?.id);
147
+ : (0, exports.getOperatingExpensesReport)(state, noFilter, opExWithForecastState.uiState.selectedForecast?.id,
148
+ // Detail selectors read the custom slot when the detail is in custom
149
+ // mode; the dashboard's getOperatingExpensesForLast5Periods does not.
150
+ opExWithForecastState.uiState.customTimeframe != null);
133
151
  });
134
152
  exports.getOperatingExpensesForHighlightedRange = (0, toolkit_1.createSelector)((state) => state, (state) => state.opExState, (state, opExWithForecastState) => {
135
153
  const { timeframe, highlightedCOABalancesRange, selectedAdditionalBalances, maxNumOfPeriodsToHighlight, isForecastModeOn, selectedForecast, } = opExWithForecastState.uiState;
@@ -139,7 +157,7 @@ exports.getOperatingExpensesForHighlightedRange = (0, toolkit_1.createSelector)(
139
157
  selectedForecast?.id != null &&
140
158
  (0, exports.getOperatingExpensesReportFetchState)(selectedForecast.id, opExWithForecastState).fetchState === 'Completed'
141
159
  ? getOpExWithForecastOnDataAvailableDateRange(state, filter, selectedForecast?.id)
142
- : (0, exports.getOperatingExpensesReport)(state, filter, opExWithForecastState.uiState.selectedForecast?.id);
160
+ : (0, exports.getOperatingExpensesReport)(state, filter, opExWithForecastState.uiState.selectedForecast?.id, opExWithForecastState.uiState.customTimeframe != null);
143
161
  });
144
162
  /**
145
163
  * Get Net Burn or Income with forecast data overlaid on actuals.
@@ -18,6 +18,12 @@ export interface OpExState extends Report {
18
18
  year: FetchStateAndError;
19
19
  };
20
20
  insights: InsightSummary[];
21
+ customFetchState?: {
22
+ month: FetchStateAndError;
23
+ quarter: FetchStateAndError;
24
+ year: FetchStateAndError;
25
+ };
26
+ customOpExBalancesByTimeframe?: COABalanceGroupedByPeriod;
21
27
  forecastId?: ID;
22
28
  opExBalancesByTimeframe?: COABalanceGroupedByPeriod;
23
29
  }
@@ -29,6 +29,10 @@ const fetchProfitAndLossForTimeframeEpic = (actions$, _, zeniAPI) => actions$.pi
29
29
  queryValue.forecast_id = action.payload.forecastId;
30
30
  queryValue.is_forecast_vs_actual = true;
31
31
  }
32
+ if (action.payload.startDate != null && action.payload.endDate != null) {
33
+ queryValue.custom_start_date = action.payload.startDate;
34
+ queryValue.custom_end_date = action.payload.endDate;
35
+ }
32
36
  return zeniAPI
33
37
  .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/2.0/reports/profit_and_loss?query=${encodeURIComponent(JSON.stringify(queryValue))}`)
34
38
  .pipe((0, operators_1.mergeMap)((response) => {
@@ -7,11 +7,13 @@ export declare const initialState: ProfitAndLossWithForecastState;
7
7
  export declare const fetchProfitAndLoss: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[forecastId?: string | undefined, cacheOverride?: boolean | undefined], {
8
8
  forecastId: string | undefined;
9
9
  cacheOverride: boolean;
10
- }, "profitAndLoss/fetchProfitAndLoss", never, never>, fetchProfitAndLossForTimeframe: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", forecastId?: string | undefined, fetchFullReport?: boolean | undefined, cacheOverride?: boolean | undefined], {
10
+ }, "profitAndLoss/fetchProfitAndLoss", never, never>, fetchProfitAndLossForTimeframe: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", forecastId?: string | undefined, fetchFullReport?: boolean | undefined, cacheOverride?: boolean | undefined, startDate?: string | undefined, endDate?: string | undefined], {
11
11
  forecastId: string | undefined;
12
12
  timeframe: "month" | "year" | "quarter";
13
13
  fetchFullReport: boolean;
14
14
  cacheOverride: boolean;
15
+ startDate: string | undefined;
16
+ endDate: string | undefined;
15
17
  }, "profitAndLoss/fetchProfitAndLossForTimeframe", never, never>, updateProfitAndLossForTimeframe: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
16
18
  forecastId: string | undefined;
17
19
  report: ZeniReportData<ProfitAndLossReportPayload>;
@@ -54,9 +54,16 @@ const profitAndLoss = (0, toolkit_1.createSlice)({
54
54
  },
55
55
  },
56
56
  fetchProfitAndLossForTimeframe: {
57
- prepare(timeframe, forecastId, fetchFullReport = true, cacheOverride = false) {
57
+ prepare(timeframe, forecastId, fetchFullReport = true, cacheOverride = false, startDate, endDate) {
58
58
  return {
59
- payload: { forecastId, timeframe, fetchFullReport, cacheOverride },
59
+ payload: {
60
+ forecastId,
61
+ timeframe,
62
+ fetchFullReport,
63
+ cacheOverride,
64
+ startDate,
65
+ endDate,
66
+ },
60
67
  };
61
68
  },
62
69
  reducer(draft, action) {
@@ -10,25 +10,37 @@ export type ActionType = ReturnType<typeof updateReportUIOptionCOABalancesRange>
10
10
  export declare const updateReportUIOptionCOABalancesRangeEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => import("rxjs").Observable<{
11
11
  payload: {
12
12
  selectedCOABalancesRange: import("../..").COABalancesRange;
13
+ customEndDate?: string;
14
+ customStartDate?: string;
13
15
  highlightedCOABalancesRange?: import("../..").COABalancesRangeWithThisPeriod;
16
+ isCustomDateRange?: boolean;
14
17
  };
15
18
  type: "net_burn_or_income/updateNetBurnOrIncomeCOABalancesRange";
16
19
  } | {
17
20
  payload: {
18
21
  selectedCOABalancesRange: import("../..").COABalancesRange;
22
+ customEndDate?: string;
23
+ customStartDate?: string;
19
24
  highlightedCOABalancesRange?: import("../..").COABalancesRangeWithThisPeriod;
25
+ isCustomDateRange?: boolean;
20
26
  };
21
27
  type: "operatingExpenses/updateOpExCOABalancesRange";
22
28
  } | {
23
29
  payload: {
24
30
  selectedCOABalancesRange: import("../..").COABalancesRange;
31
+ customEndDate?: string;
32
+ customStartDate?: string;
25
33
  highlightedCOABalancesRange?: import("../..").COABalancesRangeWithThisPeriod;
34
+ isCustomDateRange?: boolean;
26
35
  };
27
36
  type: "revenue/updateRevenueCOABalancesRange";
28
37
  } | {
29
38
  payload: {
30
39
  selectedCOABalancesRange: import("../..").COABalancesRange;
40
+ customEndDate?: string;
41
+ customStartDate?: string;
31
42
  highlightedCOABalancesRange?: import("../..").COABalancesRangeWithThisPeriod;
43
+ isCustomDateRange?: boolean;
32
44
  };
33
45
  type: "cashPosition/updateCashPositionCOABalancesRange";
34
46
  } | {
@@ -37,7 +49,10 @@ export declare const updateReportUIOptionCOABalancesRangeEpic: (actions$: Action
37
49
  } | {
38
50
  payload: {
39
51
  selectedCOABalancesRange: import("../..").COABalancesRange;
52
+ customEndDate?: string;
53
+ customStartDate?: string;
40
54
  highlightedCOABalancesRange?: import("../..").COABalancesRangeWithThisPeriod;
55
+ isCustomDateRange?: boolean;
41
56
  };
42
57
  type: "cashInCashOut/updateCashInCashOutCOABalancesRange";
43
58
  }>;
@@ -9,6 +9,7 @@ export declare const fetchRevenueWithForecastEpic: (actions$: ActionsObservable<
9
9
  error: import("../../zeniAPIStatus").ZeniAPIStatus<Record<string, unknown>>;
10
10
  forecastId: string | undefined;
11
11
  timeframe: "month" | "year" | "quarter";
12
+ isCustomDateRange: boolean;
12
13
  };
13
14
  type: "revenue/updateRevenueForTimeframeFailure";
14
15
  }[]>;
@@ -5,12 +5,12 @@ const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const revenueReducer_1 = require("./revenueReducer");
7
7
  const fetchRevenueEpic = (actions$, state) => actions$.pipe((0, operators_1.filter)(revenueReducer_1.fetchRevenue.match), (0, operators_1.switchMap)((action) => {
8
- const { cacheOverride, forecastId } = action.payload;
8
+ const { cacheOverride, endDate, forecastId, startDate } = action.payload;
9
9
  if (cacheOverride === true) {
10
10
  return (0, rxjs_1.from)([
11
- (0, revenueReducer_1.fetchRevenueForTimeframe)('month', forecastId),
12
- (0, revenueReducer_1.fetchRevenueForTimeframe)('quarter', forecastId),
13
- (0, revenueReducer_1.fetchRevenueForTimeframe)('year', forecastId),
11
+ (0, revenueReducer_1.fetchRevenueForTimeframe)('month', forecastId, true, false, startDate, endDate),
12
+ (0, revenueReducer_1.fetchRevenueForTimeframe)('quarter', forecastId, true, false, startDate, endDate),
13
+ (0, revenueReducer_1.fetchRevenueForTimeframe)('year', forecastId, true, false, startDate, endDate),
14
14
  ]);
15
15
  }
16
16
  else {
@@ -19,15 +19,15 @@ const fetchRevenueEpic = (actions$, state) => actions$.pipe((0, operators_1.filt
19
19
  const timeframeFetchState = revState.fetchState;
20
20
  if (timeframeFetchState['month'].fetchState !== 'In-Progress' &&
21
21
  timeframeFetchState['month'].fetchState !== 'Completed') {
22
- fetchActions.push((0, revenueReducer_1.fetchRevenueForTimeframe)('month', forecastId));
22
+ fetchActions.push((0, revenueReducer_1.fetchRevenueForTimeframe)('month', forecastId, true, false, startDate, endDate));
23
23
  }
24
24
  if (timeframeFetchState['quarter'].fetchState !== 'In-Progress' &&
25
25
  timeframeFetchState['quarter'].fetchState !== 'Completed') {
26
- fetchActions.push((0, revenueReducer_1.fetchRevenueForTimeframe)('quarter', forecastId));
26
+ fetchActions.push((0, revenueReducer_1.fetchRevenueForTimeframe)('quarter', forecastId, true, false, startDate, endDate));
27
27
  }
28
28
  if (timeframeFetchState['year'].fetchState !== 'In-Progress' &&
29
29
  timeframeFetchState['year'].fetchState !== 'Completed') {
30
- fetchActions.push((0, revenueReducer_1.fetchRevenueForTimeframe)('year', forecastId));
30
+ fetchActions.push((0, revenueReducer_1.fetchRevenueForTimeframe)('year', forecastId, true, false, startDate, endDate));
31
31
  }
32
32
  return (0, rxjs_1.from)(fetchActions);
33
33
  }
@@ -7,5 +7,6 @@ import { RootState } from '../../rootStateTypes';
7
7
  import { ZeniAPI } from '../../zeniAPI';
8
8
  import { fetchRevenueForTimeframe, updateRevenueForTimeframe, updateRevenueForTimeframeFailure, updateRevenueThisPeriod } from './revenueReducer';
9
9
  export type ActionType = ReturnType<typeof fetchRevenueForTimeframe> | ReturnType<typeof updateRevenueForTimeframe> | ReturnType<typeof updateRevenueForTimeframeFailure> | ReturnType<typeof updateSectionAccountsView> | ReturnType<typeof updateCalculatedSectionAccountsView> | ReturnType<typeof updateRevenueThisPeriod> | ReturnType<typeof updateForecast>;
10
- export declare const reportIdUniqueKey: (forecastId?: ID) => "revenue" | `revenue+${string}`;
10
+ export declare const CUSTOM_DATE_RANGE_SECTION_MARKER: ID;
11
+ export declare const reportIdUniqueKey: (forecastId?: ID, isCustomDateRange?: boolean) => "revenue" | `revenue+${string}`;
11
12
  export declare const fetchRevenueForTimeframeEpic: (actions$: ActionsObservable<ActionType>, state: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchRevenueForTimeframeEpic = exports.reportIdUniqueKey = void 0;
3
+ exports.fetchRevenueForTimeframeEpic = exports.reportIdUniqueKey = exports.CUSTOM_DATE_RANGE_SECTION_MARKER = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const forecastReducer_1 = require("../../entity/forecast/forecastReducer");
@@ -8,9 +8,15 @@ const sectionAccountsViewReducer_1 = require("../../entity/sectionAccountsView/s
8
8
  const responsePayload_1 = require("../../responsePayload");
9
9
  const reportsHelpers_1 = require("../common/reportsHelpers");
10
10
  const revenueReducer_1 = require("./revenueReducer");
11
- const reportIdUniqueKey = (forecastId) => forecastId != null
12
- ? `revenue+${forecastId}`
13
- : 'revenue';
11
+ // Reserved forecast-slot marker so custom-date section-accounts data lives under
12
+ // its own key (revenue+<marker>) and a default fetch can never overwrite it.
13
+ // Real forecast ids are UUIDs, so this never collides.
14
+ exports.CUSTOM_DATE_RANGE_SECTION_MARKER = '__custom_date_range__';
15
+ const reportIdUniqueKey = (forecastId, isCustomDateRange) => isCustomDateRange === true
16
+ ? `revenue+${exports.CUSTOM_DATE_RANGE_SECTION_MARKER}`
17
+ : forecastId != null
18
+ ? `revenue+${forecastId}`
19
+ : 'revenue';
14
20
  exports.reportIdUniqueKey = reportIdUniqueKey;
15
21
  const fetchRevenueForTimeframeEpic = (actions$, state, zeniAPI) => actions$.pipe((0, operators_1.filter)(revenueReducer_1.fetchRevenueForTimeframe.match), (0, operators_1.mergeMap)((action) => {
16
22
  const queryValue = {
@@ -22,18 +28,25 @@ const fetchRevenueForTimeframeEpic = (actions$, state, zeniAPI) => actions$.pipe
22
28
  queryValue.forecast_id = action.payload.forecastId;
23
29
  queryValue.is_forecast_vs_actual = true;
24
30
  }
31
+ if (action.payload.startDate != null && action.payload.endDate != null) {
32
+ queryValue.custom_start_date = action.payload.startDate;
33
+ queryValue.custom_end_date = action.payload.endDate;
34
+ }
25
35
  return zeniAPI
26
36
  .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/2.0/reports/revenue?query=${encodeURIComponent(JSON.stringify(queryValue))}`)
27
37
  .pipe((0, operators_1.mergeMap)((response) => {
28
38
  if (response.data != null && (0, responsePayload_1.isSuccessResponse)(response)) {
29
39
  const actions = [];
30
- actions.push((0, sectionAccountsViewReducer_1.updateSectionAccountsView)(action.payload.timeframe, 'cogs', (0, exports.reportIdUniqueKey)(action.payload.forecastId), response.data.report.cogs, response.data.report.accounts, response.data.report.account_groups, response.data.report.currency));
31
- actions.push((0, sectionAccountsViewReducer_1.updateSectionAccountsView)(action.payload.timeframe, 'income', (0, exports.reportIdUniqueKey)(action.payload.forecastId), response.data.report.income, response.data.report.accounts, response.data.report.account_groups, response.data.report.currency));
32
- actions.push((0, sectionAccountsViewReducer_1.updateCalculatedSectionAccountsView)(action.payload.timeframe, 'grossMargin', (0, exports.reportIdUniqueKey)(action.payload.forecastId), response.data.report.gross_profit, response.data.report.currency));
40
+ const isCustomDateRange = action.payload.startDate != null &&
41
+ action.payload.endDate != null;
42
+ actions.push((0, sectionAccountsViewReducer_1.updateSectionAccountsView)(action.payload.timeframe, 'cogs', (0, exports.reportIdUniqueKey)(action.payload.forecastId, isCustomDateRange), response.data.report.cogs, response.data.report.accounts, response.data.report.account_groups, response.data.report.currency));
43
+ actions.push((0, sectionAccountsViewReducer_1.updateSectionAccountsView)(action.payload.timeframe, 'income', (0, exports.reportIdUniqueKey)(action.payload.forecastId, isCustomDateRange), response.data.report.income, response.data.report.accounts, response.data.report.account_groups, response.data.report.currency));
44
+ actions.push((0, sectionAccountsViewReducer_1.updateCalculatedSectionAccountsView)(action.payload.timeframe, 'grossMargin', (0, exports.reportIdUniqueKey)(action.payload.forecastId, isCustomDateRange), response.data.report.gross_profit, response.data.report.currency));
33
45
  actions.push((0, revenueReducer_1.updateRevenueForTimeframe)({
34
46
  timeframe: action.payload.timeframe,
35
47
  forecastId: action.payload.forecastId,
36
48
  report: response.data,
49
+ isCustomDateRange,
37
50
  }));
38
51
  if (action.payload.forecastId == null &&
39
52
  action.payload.timeframe === 'month') {
@@ -48,8 +61,10 @@ const fetchRevenueForTimeframeEpic = (actions$, state, zeniAPI) => actions$.pipe
48
61
  return (0, rxjs_1.from)(actions);
49
62
  }
50
63
  else {
51
- return (0, rxjs_1.of)((0, revenueReducer_1.updateRevenueForTimeframeFailure)(response.status, action.payload.forecastId, action.payload.timeframe));
64
+ return (0, rxjs_1.of)((0, revenueReducer_1.updateRevenueForTimeframeFailure)(response.status, action.payload.forecastId, action.payload.timeframe, action.payload.startDate != null &&
65
+ action.payload.endDate != null));
52
66
  }
53
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, revenueReducer_1.updateRevenueForTimeframeFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Revenue REST API call errored out' + JSON.stringify(error)), action.payload.forecastId, action.payload.timeframe))));
67
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, revenueReducer_1.updateRevenueForTimeframeFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Revenue REST API call errored out' + JSON.stringify(error)), action.payload.forecastId, action.payload.timeframe, action.payload.startDate != null &&
68
+ action.payload.endDate != null))));
54
69
  }));
55
70
  exports.fetchRevenueForTimeframeEpic = fetchRevenueForTimeframeEpic;