@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.
- package/lib/commonStateTypes/timeframeTick.d.ts +1 -0
- package/lib/commonStateTypes/timeframeTick.js +1 -0
- package/lib/commonStateTypes/viewAndReport/reportUIState.d.ts +2 -0
- package/lib/commonStateTypes/viewAndReport/viewAndReport.d.ts +2 -0
- package/lib/esm/commonStateTypes/timeframeTick.js +1 -0
- package/lib/esm/view/balanceSheet/balanceSheetForTimeframeEpic.js +4 -0
- package/lib/esm/view/balanceSheet/balanceSheetReducer.js +8 -2
- package/lib/esm/view/cashFlow/cashFlowForTimeframeEpic.js +4 -0
- package/lib/esm/view/cashFlow/cashFlowReducer.js +2 -2
- package/lib/esm/view/cashInCashOut/cashInCashOutEpic.js +22 -14
- package/lib/esm/view/cashInCashOut/cashInCashOutReducer.js +161 -41
- package/lib/esm/view/cashInCashOut/cashInCashOutSelector.js +42 -15
- package/lib/esm/view/cashPosition/cashPositionEpic.js +21 -13
- package/lib/esm/view/cashPosition/cashPositionReducer.js +155 -44
- package/lib/esm/view/cashPosition/cashPositionSelector.js +28 -9
- package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeEpic.js +7 -7
- package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.js +25 -10
- package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeReducer.js +184 -40
- package/lib/esm/view/netBurnOrIncome/netBurnOrIncomeSelector.js +26 -8
- package/lib/esm/view/opEx/opExEpic.js +7 -7
- package/lib/esm/view/opEx/opExForTimeFrameEpic.js +21 -6
- package/lib/esm/view/opEx/opExReducer.js +169 -32
- package/lib/esm/view/opEx/opExSelector.js +28 -10
- package/lib/esm/view/profitAndLoss/profitAndLossForTimeframeEpic.js +4 -0
- package/lib/esm/view/profitAndLoss/profitAndLossReducer.js +9 -2
- package/lib/esm/view/revenue/revenueEpic.js +7 -7
- package/lib/esm/view/revenue/revenueForTimeframeEpic.js +23 -8
- package/lib/esm/view/revenue/revenueReducer.js +183 -40
- package/lib/esm/view/revenue/revenueSelector.js +30 -10
- package/lib/view/balanceSheet/balanceSheetForTimeframeEpic.js +4 -0
- package/lib/view/balanceSheet/balanceSheetReducer.d.ts +3 -1
- package/lib/view/balanceSheet/balanceSheetReducer.js +8 -2
- package/lib/view/cashFlow/cashFlowForTimeframeEpic.js +4 -0
- package/lib/view/cashFlow/cashFlowReducer.d.ts +3 -1
- package/lib/view/cashFlow/cashFlowReducer.js +2 -2
- package/lib/view/cashInCashOut/cashInCashOutEpic.d.ts +8 -2
- package/lib/view/cashInCashOut/cashInCashOutEpic.js +22 -14
- package/lib/view/cashInCashOut/cashInCashOutReducer.d.ts +13 -1
- package/lib/view/cashInCashOut/cashInCashOutReducer.js +161 -41
- package/lib/view/cashInCashOut/cashInCashOutSelector.d.ts +2 -1
- package/lib/view/cashInCashOut/cashInCashOutSelector.js +42 -15
- package/lib/view/cashInCashOut/cashInCashOutState.d.ts +5 -1
- package/lib/view/cashPosition/cashPositionEpic.d.ts +8 -2
- package/lib/view/cashPosition/cashPositionEpic.js +21 -13
- package/lib/view/cashPosition/cashPositionReducer.d.ts +13 -2
- package/lib/view/cashPosition/cashPositionReducer.js +155 -44
- package/lib/view/cashPosition/cashPositionSelector.d.ts +2 -1
- package/lib/view/cashPosition/cashPositionSelector.js +28 -9
- package/lib/view/cashPosition/cashPositionState.d.ts +5 -1
- package/lib/view/financeStatement/financeStatementEpic.d.ts +6 -0
- package/lib/view/netBurnOrIncome/fetchNetBurnOrIncomeWithForecastEpic.d.ts +1 -0
- package/lib/view/netBurnOrIncome/netBurnOrIncomeEpic.js +7 -7
- package/lib/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.d.ts +2 -1
- package/lib/view/netBurnOrIncome/netBurnOrIncomeForTimeframeEpic.js +26 -11
- package/lib/view/netBurnOrIncome/netBurnOrIncomeReducer.d.ts +12 -3
- package/lib/view/netBurnOrIncome/netBurnOrIncomeReducer.js +184 -40
- package/lib/view/netBurnOrIncome/netBurnOrIncomeSelector.d.ts +1 -1
- package/lib/view/netBurnOrIncome/netBurnOrIncomeSelector.js +26 -8
- package/lib/view/netBurnOrIncome/netBurnOrIncomeState.d.ts +8 -0
- package/lib/view/opEx/fetchOpExWithForecastEpic.d.ts +1 -0
- package/lib/view/opEx/opExEpic.js +7 -7
- package/lib/view/opEx/opExForTimeFrameEpic.d.ts +2 -1
- package/lib/view/opEx/opExForTimeFrameEpic.js +22 -7
- package/lib/view/opEx/opExReducer.d.ts +12 -3
- package/lib/view/opEx/opExReducer.js +168 -31
- package/lib/view/opEx/opExSelector.d.ts +1 -1
- package/lib/view/opEx/opExSelector.js +28 -10
- package/lib/view/opEx/opExState.d.ts +6 -0
- package/lib/view/profitAndLoss/profitAndLossForTimeframeEpic.js +4 -0
- package/lib/view/profitAndLoss/profitAndLossReducer.d.ts +3 -1
- package/lib/view/profitAndLoss/profitAndLossReducer.js +9 -2
- package/lib/view/reportUIOptions/updateReportUIOptionCOABalancesRangeEpic.d.ts +15 -0
- package/lib/view/revenue/fetchRevenueWithForecastEpic.d.ts +1 -0
- package/lib/view/revenue/revenueEpic.js +7 -7
- package/lib/view/revenue/revenueForTimeframeEpic.d.ts +2 -1
- package/lib/view/revenue/revenueForTimeframeEpic.js +24 -9
- package/lib/view/revenue/revenueReducer.d.ts +12 -3
- package/lib/view/revenue/revenueReducer.js +182 -39
- package/lib/view/revenue/revenueSelector.d.ts +1 -1
- package/lib/view/revenue/revenueSelector.js +30 -10
- package/lib/view/revenue/revenueState.d.ts +8 -0
- 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 {
|
|
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: {
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
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
|
-
|
|
353
|
-
|
|
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
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
363
|
-
|
|
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
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
activeFetchState.month,
|
|
92
|
+
activeFetchState.quarter,
|
|
93
|
+
activeFetchState.year,
|
|
84
94
|
]);
|
|
85
|
-
|
|
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: {
|
|
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
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
actions.push((0, sectionAccountsViewReducer_1.
|
|
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;
|