@zeniai/client-epic-state 5.2.93 → 5.2.94-betaNB1
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/entity/reconciliationReport/reconciliationReportPayload.d.ts +1 -0
- package/lib/entity/reconciliationReport/reconciliationReportReducer.js +1 -0
- package/lib/entity/reconciliationReport/reconciliationReportState.d.ts +4 -2
- package/lib/entity/reconciliationReport/reconciliationReportState.js +4 -1
- package/lib/esm/commonStateTypes/timeframeTick.js +1 -0
- package/lib/esm/entity/reconciliationReport/reconciliationReportReducer.js +1 -0
- package/lib/esm/entity/reconciliationReport/reconciliationReportState.js +4 -1
- 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
|
@@ -10,18 +10,22 @@ export declare const defaultPeriods: {
|
|
|
10
10
|
};
|
|
11
11
|
export declare const initialRevState: RevenueState;
|
|
12
12
|
export declare const initialState: RevenueWithForecastState;
|
|
13
|
-
export declare const fetchRevenue: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[fetchFullReport?: any, forecastId?: string | undefined, cacheOverride?: any], {
|
|
13
|
+
export declare const fetchRevenue: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[fetchFullReport?: any, forecastId?: string | undefined, cacheOverride?: any, startDate?: string | undefined, endDate?: string | undefined], {
|
|
14
14
|
fetchFullReport: any;
|
|
15
15
|
forecastId: string | undefined;
|
|
16
16
|
cacheOverride: any;
|
|
17
|
+
startDate: string | undefined;
|
|
18
|
+
endDate: string | undefined;
|
|
17
19
|
}, "revenue/fetchRevenue", never, never>, fetchRevenueWithForecast: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[cacheOverride?: boolean | undefined, forecastId?: string | undefined], {
|
|
18
20
|
cacheOverride: boolean;
|
|
19
21
|
forecastId: string | undefined;
|
|
20
|
-
}, "revenue/fetchRevenueWithForecast", never, never>, fetchRevenueForTimeframe: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", forecastId?: string | undefined, fetchFullReport?: boolean | undefined, cacheOverride?: boolean | undefined], {
|
|
22
|
+
}, "revenue/fetchRevenueWithForecast", never, never>, fetchRevenueForTimeframe: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", forecastId?: string | undefined, fetchFullReport?: boolean | undefined, cacheOverride?: boolean | undefined, startDate?: string | undefined, endDate?: string | undefined], {
|
|
21
23
|
forecastId: string | undefined;
|
|
22
24
|
timeframe: "month" | "year" | "quarter";
|
|
23
25
|
fetchFullReport: boolean;
|
|
24
26
|
cacheOverride: boolean;
|
|
27
|
+
startDate: string | undefined;
|
|
28
|
+
endDate: string | undefined;
|
|
25
29
|
}, "revenue/fetchRevenueForTimeframe", never, never>, waitForForecastListThenFetchRevenueWithForecast: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[cacheOverride?: boolean | undefined, forecastId?: string | undefined], {
|
|
26
30
|
cacheOverride: boolean;
|
|
27
31
|
forecastId: string | undefined;
|
|
@@ -29,17 +33,22 @@ export declare const fetchRevenue: import("@reduxjs/toolkit").ActionCreatorWithP
|
|
|
29
33
|
forecastId: string | undefined;
|
|
30
34
|
report: ZeniReportData<RevenueReportPayload>;
|
|
31
35
|
timeframe: "month" | "quarter" | "year";
|
|
32
|
-
|
|
36
|
+
isCustomDateRange?: boolean;
|
|
37
|
+
}, "revenue/updateRevenueForTimeframe">, updateRevenueForTimeframeFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[error: ZeniAPIStatus<Record<string, unknown>>, forecastId: string | undefined, timeframe: "month" | "year" | "quarter", isCustomDateRange?: boolean | undefined], {
|
|
33
38
|
error: ZeniAPIStatus<Record<string, unknown>>;
|
|
34
39
|
forecastId: string | undefined;
|
|
35
40
|
timeframe: "month" | "year" | "quarter";
|
|
41
|
+
isCustomDateRange: boolean;
|
|
36
42
|
}, "revenue/updateRevenueForTimeframeFailure", never, never>, updateRevenueAdditionalBalancesSelection: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
37
43
|
additionalBalances: COABalanceType[];
|
|
38
44
|
isCompareModeOn: boolean;
|
|
39
45
|
maxNumOfPeriodsToHighlight: number;
|
|
40
46
|
}, "revenue/updateRevenueAdditionalBalancesSelection">, updateRevenueCOABalancesRange: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
41
47
|
selectedCOABalancesRange: COABalancesRange;
|
|
48
|
+
customEndDate?: string;
|
|
49
|
+
customStartDate?: string;
|
|
42
50
|
highlightedCOABalancesRange?: COABalancesRangeWithThisPeriod;
|
|
51
|
+
isCustomDateRange?: boolean;
|
|
43
52
|
}, "revenue/updateRevenueCOABalancesRange">, updateRevenueThisPeriod: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
44
53
|
thisPeriod: TimeframeTick | undefined;
|
|
45
54
|
}, "revenue/updateRevenueThisPeriod">, updateRevenueDownloadState: import("@reduxjs/toolkit").ActionCreatorWithPayload<FetchState, "revenue/updateRevenueDownloadState">, updateRevenueTimeFrame: import("@reduxjs/toolkit").ActionCreatorWithPayload<"month" | "year" | "quarter", "revenue/updateRevenueTimeFrame">, updateRevenueUIState: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
@@ -73,8 +73,16 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
73
73
|
initialState: exports.initialState,
|
|
74
74
|
reducers: {
|
|
75
75
|
fetchRevenue: {
|
|
76
|
-
prepare(fetchFullReport = false, forecastId, cacheOverride = false) {
|
|
77
|
-
return {
|
|
76
|
+
prepare(fetchFullReport = false, forecastId, cacheOverride = false, startDate, endDate) {
|
|
77
|
+
return {
|
|
78
|
+
payload: {
|
|
79
|
+
fetchFullReport,
|
|
80
|
+
forecastId,
|
|
81
|
+
cacheOverride,
|
|
82
|
+
startDate,
|
|
83
|
+
endDate,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
78
86
|
},
|
|
79
87
|
reducer(
|
|
80
88
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -85,22 +93,49 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
85
93
|
},
|
|
86
94
|
},
|
|
87
95
|
fetchRevenueForTimeframe: {
|
|
88
|
-
prepare(timeframe, forecastId, fetchFullReport = true, cacheOverride = false) {
|
|
96
|
+
prepare(timeframe, forecastId, fetchFullReport = true, cacheOverride = false, startDate, endDate) {
|
|
89
97
|
return {
|
|
90
|
-
payload: {
|
|
98
|
+
payload: {
|
|
99
|
+
forecastId,
|
|
100
|
+
timeframe,
|
|
101
|
+
fetchFullReport,
|
|
102
|
+
cacheOverride,
|
|
103
|
+
startDate,
|
|
104
|
+
endDate,
|
|
105
|
+
},
|
|
91
106
|
};
|
|
92
107
|
},
|
|
93
108
|
reducer(draft, action) {
|
|
94
109
|
const timeframe = action.payload.timeframe;
|
|
95
110
|
const revState = getState(draft, draft.uiState.isForecastModeOn, action.payload.forecastId);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
111
|
+
// Route by the fetch's own dates, not the global flag: a custom fetch
|
|
112
|
+
// (carries start/end) marks customFetchState so the shared fetchState the
|
|
113
|
+
// dashboard reads is never left In-Progress by a detail-screen fetch.
|
|
114
|
+
const isCustomDateRange = action.payload.startDate != null && action.payload.endDate != null;
|
|
115
|
+
if (isCustomDateRange) {
|
|
116
|
+
const customFetchState = {
|
|
117
|
+
...(revState.customFetchState ?? {
|
|
118
|
+
month: { fetchState: 'Not-Started', error: undefined },
|
|
119
|
+
quarter: { fetchState: 'Not-Started', error: undefined },
|
|
120
|
+
year: { fetchState: 'Not-Started', error: undefined },
|
|
121
|
+
}),
|
|
122
|
+
};
|
|
123
|
+
customFetchState[timeframe] = {
|
|
124
|
+
fetchState: 'In-Progress',
|
|
125
|
+
error: undefined,
|
|
126
|
+
};
|
|
127
|
+
updateState(draft, action.payload.forecastId, { customFetchState });
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
const fetchState = {
|
|
131
|
+
...revState.fetchState,
|
|
132
|
+
};
|
|
133
|
+
fetchState[timeframe] = {
|
|
134
|
+
fetchState: 'In-Progress',
|
|
135
|
+
error: undefined,
|
|
136
|
+
};
|
|
137
|
+
updateState(draft, action.payload.forecastId, { fetchState });
|
|
138
|
+
}
|
|
104
139
|
},
|
|
105
140
|
},
|
|
106
141
|
fetchRevenueWithForecast: {
|
|
@@ -130,28 +165,47 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
130
165
|
},
|
|
131
166
|
},
|
|
132
167
|
updateRevenueForTimeframe(draft, action) {
|
|
133
|
-
doUpdateRevenue(draft, action.payload.forecastId, action.payload.timeframe, action.payload.report);
|
|
168
|
+
doUpdateRevenue(draft, action.payload.forecastId, action.payload.timeframe, action.payload.report, action.payload.isCustomDateRange === true);
|
|
134
169
|
},
|
|
135
170
|
updateRevenueForTimeframeFailure: {
|
|
136
|
-
prepare(error, forecastId, timeframe) {
|
|
171
|
+
prepare(error, forecastId, timeframe, isCustomDateRange = false) {
|
|
137
172
|
return {
|
|
138
173
|
payload: {
|
|
139
174
|
error,
|
|
140
175
|
forecastId,
|
|
141
176
|
timeframe,
|
|
177
|
+
isCustomDateRange,
|
|
142
178
|
},
|
|
143
179
|
};
|
|
144
180
|
},
|
|
145
181
|
reducer(draft, action) {
|
|
146
182
|
const revState = getState(draft, draft.uiState.isForecastModeOn, action.payload.forecastId);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
183
|
+
// Route the error like the request/success: a custom (dated) fetch's
|
|
184
|
+
// failure lands in customFetchState so the shared default the dashboard
|
|
185
|
+
// reads isn't marked Error, and the detail's customFetchState isn't left
|
|
186
|
+
// stuck In-Progress.
|
|
187
|
+
if (action.payload.isCustomDateRange === true) {
|
|
188
|
+
const customFetchState = revState.customFetchState ?? {
|
|
189
|
+
month: { fetchState: 'Not-Started', error: undefined },
|
|
190
|
+
quarter: { fetchState: 'Not-Started', error: undefined },
|
|
191
|
+
year: { fetchState: 'Not-Started', error: undefined },
|
|
192
|
+
};
|
|
193
|
+
customFetchState[action.payload.timeframe] = {
|
|
194
|
+
fetchState: 'Error',
|
|
195
|
+
error: action.payload.error,
|
|
196
|
+
};
|
|
197
|
+
updateState(draft, action.payload.forecastId, { customFetchState });
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
const fetchState = {
|
|
201
|
+
...revState.fetchState,
|
|
202
|
+
};
|
|
203
|
+
fetchState[action.payload.timeframe] = {
|
|
204
|
+
fetchState: 'Error',
|
|
205
|
+
error: action.payload.error,
|
|
206
|
+
};
|
|
207
|
+
updateState(draft, action.payload.forecastId, { fetchState });
|
|
208
|
+
}
|
|
155
209
|
},
|
|
156
210
|
},
|
|
157
211
|
updateRevenueAdditionalBalancesSelection(draft, action) {
|
|
@@ -170,7 +224,9 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
170
224
|
? true
|
|
171
225
|
: false;
|
|
172
226
|
// Note: We don't want to update selected & highlighted ranges in Ui State when forecast is ON
|
|
173
|
-
if (dataAvailable != null &&
|
|
227
|
+
if (dataAvailable != null &&
|
|
228
|
+
draft.uiState.isForecastModeOn === false &&
|
|
229
|
+
draft.uiState.customTimeframe == null) {
|
|
174
230
|
const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(revenueReport.firstMonthOfFY, timeframe, [income, cogs, grossMargin], dataAvailable);
|
|
175
231
|
const thisPeriod = (0, thisPeriodHelpers_1.extractThisPeriod)(revenueReport.firstMonthOfFY, timeframe, selectedCOABalancesRange, coaBalances);
|
|
176
232
|
if (thisPeriod != null &&
|
|
@@ -199,6 +255,48 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
199
255
|
}
|
|
200
256
|
},
|
|
201
257
|
updateRevenueCOABalancesRange(draft, action) {
|
|
258
|
+
if (action.payload.isCustomDateRange != null) {
|
|
259
|
+
if (action.payload.isCustomDateRange === true) {
|
|
260
|
+
// Convert the string dates the action carries to ZeniDate values and
|
|
261
|
+
// store as a single customTimeframe. Presence signals custom-mode active.
|
|
262
|
+
draft.uiState.customTimeframe =
|
|
263
|
+
action.payload.customStartDate != null &&
|
|
264
|
+
action.payload.customEndDate != null
|
|
265
|
+
? {
|
|
266
|
+
startDate: (0, zeniDayJS_1.date)(action.payload.customStartDate),
|
|
267
|
+
endDate: (0, zeniDayJS_1.date)(action.payload.customEndDate),
|
|
268
|
+
}
|
|
269
|
+
: undefined;
|
|
270
|
+
// Invalidate the shared default-window fetchState so dashboardEpic
|
|
271
|
+
// refetches the default data on the next dashboard visit — the custom
|
|
272
|
+
// fetch writes into the shared section store, and this lets the card
|
|
273
|
+
// self-heal without a reload. The detail screen reads customFetchState.
|
|
274
|
+
draft.revenue.fetchState = {
|
|
275
|
+
month: { fetchState: 'Not-Started', error: undefined },
|
|
276
|
+
quarter: { fetchState: 'Not-Started', error: undefined },
|
|
277
|
+
year: { fetchState: 'Not-Started', error: undefined },
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
draft.uiState.customTimeframe = undefined;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// A custom date range drives the visible window directly: honor the exact
|
|
285
|
+
// numberOfPeriods + thisPeriod from the payload instead of re-deriving
|
|
286
|
+
// (which clamps the range to the available/non-zero periods).
|
|
287
|
+
if (draft.uiState.customTimeframe != null) {
|
|
288
|
+
draft.uiState.selectedCOABalancesRange =
|
|
289
|
+
action.payload.selectedCOABalancesRange;
|
|
290
|
+
if (action.payload.highlightedCOABalancesRange != null) {
|
|
291
|
+
// Clamp the highlight to the same cap the non-custom path enforces so
|
|
292
|
+
// a wide custom range doesn't highlight all N periods at once.
|
|
293
|
+
draft.uiState.highlightedCOABalancesRange = {
|
|
294
|
+
...action.payload.highlightedCOABalancesRange,
|
|
295
|
+
numberOfPeriods: Math.min(action.payload.highlightedCOABalancesRange.numberOfPeriods, draft.uiState.maxNumOfPeriodsToHighlight),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
202
300
|
// Note: When thisPeriod changes the selected and highlighted balances ranges should be calculated based on full report period.
|
|
203
301
|
const revenueReport = getState(draft, undefined, undefined);
|
|
204
302
|
const { income, cogs, grossMargin, dataAvailable } = revenueReport;
|
|
@@ -242,6 +340,13 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
242
340
|
}
|
|
243
341
|
},
|
|
244
342
|
updateRevenueThisPeriod(draft, action) {
|
|
343
|
+
// In custom-date mode the picker drives the window; skip re-deriving the
|
|
344
|
+
// selected/highlighted ranges from the default dataAvailable (the epic
|
|
345
|
+
// re-dispatches the default thisPeriod on every month response, which
|
|
346
|
+
// would otherwise clamp the custom window back to the default).
|
|
347
|
+
if (draft.uiState.customTimeframe != null) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
245
350
|
// Note: When thisPeriod changes the selected and highlighted balances ranges should be calculated based on full report period.
|
|
246
351
|
const revenueReport = getState(draft, undefined, undefined);
|
|
247
352
|
const { income, cogs, grossMargin, dataAvailable } = revenueReport;
|
|
@@ -291,7 +396,7 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
291
396
|
draft.uiState.maxNumOfPeriodsToHighlight =
|
|
292
397
|
exports.initialState.uiState.maxNumOfPeriodsToHighlight;
|
|
293
398
|
}
|
|
294
|
-
if (dataAvailable != null) {
|
|
399
|
+
if (dataAvailable != null && draft.uiState.customTimeframe == null) {
|
|
295
400
|
const timeframe = draft.uiState.timeframe;
|
|
296
401
|
const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(revenueReport.firstMonthOfFY, timeframe, [income, cogs, grossMargin], dataAvailable);
|
|
297
402
|
const selectionRanges = (0, getSelectedAndHighlightedRanges_1.getInitialSelectedAndHighlightedRanges)({
|
|
@@ -346,37 +451,75 @@ const revenue = (0, toolkit_1.createSlice)({
|
|
|
346
451
|
});
|
|
347
452
|
_a = revenue.actions, exports.fetchRevenue = _a.fetchRevenue, exports.fetchRevenueWithForecast = _a.fetchRevenueWithForecast, exports.fetchRevenueForTimeframe = _a.fetchRevenueForTimeframe, exports.waitForForecastListThenFetchRevenueWithForecast = _a.waitForForecastListThenFetchRevenueWithForecast, exports.updateRevenueForTimeframe = _a.updateRevenueForTimeframe, exports.updateRevenueForTimeframeFailure = _a.updateRevenueForTimeframeFailure, exports.updateRevenueAdditionalBalancesSelection = _a.updateRevenueAdditionalBalancesSelection, exports.updateRevenueCOABalancesRange = _a.updateRevenueCOABalancesRange, exports.updateRevenueThisPeriod = _a.updateRevenueThisPeriod, exports.updateRevenueDownloadState = _a.updateRevenueDownloadState, exports.updateRevenueTimeFrame = _a.updateRevenueTimeFrame, exports.updateRevenueUIState = _a.updateRevenueUIState, exports.revenueToggleForecastMode = _a.revenueToggleForecastMode;
|
|
348
453
|
exports.default = revenue.reducer;
|
|
349
|
-
const doUpdateRevenue = (draft, forecastId, timeframe, revReport) => {
|
|
454
|
+
const doUpdateRevenue = (draft, forecastId, timeframe, revReport, isCustomDateRange) => {
|
|
350
455
|
const revenue = getState(draft, draft.uiState.isForecastModeOn, forecastId);
|
|
351
456
|
const report = (0, viewAndReportPayloadv2_1.mapReportPayloadV2ToReportV2)(revReport.report);
|
|
352
457
|
const { income, cogs, insights, currency } = revReport.report;
|
|
353
458
|
const incomeCOABalance = (0, coaBalancePayload_1.mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod)(income, currency, timeframe);
|
|
354
459
|
const cogsCOABalance = (0, coaBalancePayload_1.mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod)(cogs, currency, timeframe);
|
|
355
460
|
const grossMarginCOABalance = (0, coaBalancePayload_1.mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod)(revReport.report.gross_profit, currency, timeframe);
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if (
|
|
461
|
+
// Route custom-date results (identified by the fetch's own dates, not the
|
|
462
|
+
// global flag) to the separate slots so the dashboard card (which reads
|
|
463
|
+
// income/cogs/grossMargin) keeps the default window.
|
|
464
|
+
if (isCustomDateRange) {
|
|
465
|
+
revenue.customIncome = Object.assign({}, revenue.customIncome, incomeCOABalance);
|
|
466
|
+
revenue.customCogs = Object.assign({}, revenue.customCogs, cogsCOABalance);
|
|
467
|
+
revenue.customGrossMargin = Object.assign({}, revenue.customGrossMargin, grossMarginCOABalance);
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
revenue.income = Object.assign({}, revenue.income, incomeCOABalance);
|
|
471
|
+
revenue.cogs = Object.assign({}, revenue.cogs, cogsCOABalance);
|
|
472
|
+
revenue.grossMargin = Object.assign({}, revenue.grossMargin, grossMarginCOABalance);
|
|
473
|
+
}
|
|
474
|
+
// Insights are shared (read by the dashboard card); a custom slice must not
|
|
475
|
+
// overwrite them.
|
|
476
|
+
if (timeframe === 'month' && insights != null && !isCustomDateRange) {
|
|
360
477
|
// we will get insights only in the month timeframe api
|
|
361
478
|
revenue.insights = (0, insightSummaryPayload_1.mapInsightsPayloadtoInsightsState)(insights);
|
|
362
479
|
}
|
|
363
480
|
const isIncomeEmpty = (0, reportsHelpers_1.isCOABalanceGroupedByPeriodEmptyForTimeframe)(incomeCOABalance, timeframe);
|
|
364
481
|
const isCogsEmpty = (0, reportsHelpers_1.isCOABalanceGroupedByPeriodEmptyForTimeframe)(cogsCOABalance, timeframe);
|
|
482
|
+
// Derive dataAvailable from the slot this fetch actually populated.
|
|
365
483
|
const cogsOrIncome = isIncomeEmpty
|
|
366
484
|
? isCogsEmpty
|
|
367
|
-
?
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
485
|
+
? isCustomDateRange
|
|
486
|
+
? revenue.customGrossMargin
|
|
487
|
+
: revenue.grossMargin
|
|
488
|
+
: isCustomDateRange
|
|
489
|
+
? revenue.customCogs
|
|
490
|
+
: revenue.cogs
|
|
491
|
+
: isCustomDateRange
|
|
492
|
+
? revenue.customIncome
|
|
493
|
+
: revenue.income;
|
|
494
|
+
// Don't let a custom slice shrink the shared dataAvailable the dashboard uses
|
|
495
|
+
// for its period count; a default fetch always updates it, a custom one only
|
|
496
|
+
// populates it on first load (when nothing has set it yet).
|
|
497
|
+
if (!isCustomDateRange || revenue.dataAvailable == null) {
|
|
498
|
+
revenue.dataAvailable =
|
|
499
|
+
report.dataAvailable ?? (0, dataAvailable_1.getDataAvailableDateRange)(cogsOrIncome ?? {});
|
|
500
|
+
}
|
|
373
501
|
revenue.firstMonthOfFY = report.firstMonthOfFY;
|
|
374
502
|
revenue.bookCloseDate = report.bookCloseDate;
|
|
375
|
-
|
|
376
|
-
|
|
503
|
+
// Mark the matching fetchState Completed. A custom fetch uses customFetchState so
|
|
504
|
+
// dashboardEpic's Completed check on the default fetchState is untouched.
|
|
505
|
+
if (isCustomDateRange) {
|
|
506
|
+
const customFetchState = revenue.customFetchState ?? {
|
|
507
|
+
month: { fetchState: 'Not-Started', error: undefined },
|
|
508
|
+
quarter: { fetchState: 'Not-Started', error: undefined },
|
|
509
|
+
year: { fetchState: 'Not-Started', error: undefined },
|
|
510
|
+
};
|
|
511
|
+
customFetchState[timeframe] = { fetchState: 'Completed', error: undefined };
|
|
512
|
+
revenue.customFetchState = customFetchState;
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
revenue.fetchState[timeframe].fetchState = 'Completed';
|
|
516
|
+
revenue.fetchState[timeframe].error = undefined;
|
|
517
|
+
}
|
|
377
518
|
if (revenue.dataAvailable != null &&
|
|
378
|
-
forecastId == null // Note: We don't want to update selected & highlighted ranges in Ui State when forecast is ON
|
|
379
|
-
|
|
519
|
+
forecastId == null && // Note: We don't want to update selected & highlighted ranges in Ui State when forecast is ON
|
|
520
|
+
// A custom date range drives the window; don't reset it to the default on
|
|
521
|
+
// every report receipt (this is what clamped wide ranges back to 8).
|
|
522
|
+
draft.uiState.customTimeframe == null) {
|
|
380
523
|
const timeframe = draft.uiState.timeframe;
|
|
381
524
|
const coaBalances = (0, getSelectedAndHighlightedRanges_1.getAvailableCOABalancesWithMostRecentNonZeroBalance)(revenue.firstMonthOfFY, timeframe, [revenue.income, revenue.cogs, revenue.grossMargin], revenue.dataAvailable);
|
|
382
525
|
const selectionRanges = (0, getSelectedAndHighlightedRanges_1.getInitialSelectedAndHighlightedRanges)({
|
|
@@ -8,7 +8,7 @@ import { RootState } from '../../rootStateTypes';
|
|
|
8
8
|
import { ForecastListState } from '../forecastList/forecastListState';
|
|
9
9
|
import { RevenueReport, RevenueUIStateSelectorView } from '../revenue/revenueSelectorTypes';
|
|
10
10
|
import { RevenueWithForecastState } from './revenueState';
|
|
11
|
-
export declare const getRevenueReport: (filter: COABalancesFilter, accountState: AccountState, accountGroupState: AccountGroupState, sectionsState: SectionAccountsViewState, forecastListState: ForecastListState, revenueWithForecastState: RevenueWithForecastState, forecastState: ForecastState, forecastId?: ID) => RevenueReport;
|
|
11
|
+
export declare const getRevenueReport: (filter: COABalancesFilter, accountState: AccountState, accountGroupState: AccountGroupState, sectionsState: SectionAccountsViewState, forecastListState: ForecastListState, revenueWithForecastState: RevenueWithForecastState, forecastState: ForecastState, forecastId?: ID, readCustomRangeSlot?: boolean) => RevenueReport;
|
|
12
12
|
export declare const getRevenueUIState: (state: RootState) => RevenueUIStateSelectorView;
|
|
13
13
|
export declare const getRevenueForSelectedRange: (state: RootState) => RevenueReport;
|
|
14
14
|
export declare const getRevenueForHighlightedRange: (state: RootState) => RevenueReport;
|
|
@@ -16,14 +16,26 @@ const revenueSelectorTypes_1 = require("../revenue/revenueSelectorTypes");
|
|
|
16
16
|
const revenueForTimeframeEpic_1 = require("./revenueForTimeframeEpic");
|
|
17
17
|
const revenueHelper_1 = require("./revenueHelper");
|
|
18
18
|
const revenueReducer_1 = require("./revenueReducer");
|
|
19
|
-
const getRevenueReport = (filter, accountState, accountGroupState, sectionsState, forecastListState, revenueWithForecastState, forecastState, forecastId) => {
|
|
19
|
+
const getRevenueReport = (filter, accountState, accountGroupState, sectionsState, forecastListState, revenueWithForecastState, forecastState, forecastId, readCustomRangeSlot) => {
|
|
20
20
|
const revState = (0, revenueReducer_1.getState)(revenueWithForecastState, revenueWithForecastState.uiState.isForecastModeOn, forecastId);
|
|
21
|
+
// The detail screen opts into customFetchState so its Completed check fires
|
|
22
|
+
// off the custom fetch; the dashboard (no flag) reads the shared fetchState,
|
|
23
|
+
// which custom-mode activation reset to Not-Started so dashboardEpic refetches.
|
|
24
|
+
const activeFetchState = readCustomRangeSlot === true &&
|
|
25
|
+
revenueWithForecastState.uiState.customTimeframe != null &&
|
|
26
|
+
revState.customFetchState != null
|
|
27
|
+
? revState.customFetchState
|
|
28
|
+
: revState.fetchState;
|
|
21
29
|
const fetchState = (0, reduceFetchState_1.reduceAnyFetchState)([
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
activeFetchState.month,
|
|
31
|
+
activeFetchState.quarter,
|
|
32
|
+
activeFetchState.year,
|
|
25
33
|
]);
|
|
26
|
-
|
|
34
|
+
// Custom detail reads the isolated custom section-accounts slot; dashboard
|
|
35
|
+
// (no flag) reads the default slot, so a default fetch can't clobber it.
|
|
36
|
+
const useCustomRange = readCustomRangeSlot === true &&
|
|
37
|
+
revenueWithForecastState.uiState.customTimeframe != null;
|
|
38
|
+
const reportId = (0, revenueForTimeframeEpic_1.reportIdUniqueKey)(forecastId, useCustomRange);
|
|
27
39
|
const sections = {};
|
|
28
40
|
const calculatedSections = {};
|
|
29
41
|
let allTimeframeTicks = [];
|
|
@@ -49,16 +61,16 @@ const getRevenueReport = (filter, accountState, accountGroupState, sectionsState
|
|
|
49
61
|
const timeframe = revenueWithForecastState.uiState.timeframe;
|
|
50
62
|
// To get incomeBalances without forecast init.
|
|
51
63
|
const incomeBalance = (0, sectionAccountsViewSelector_1.getSectionBalances)(sectionsState, {
|
|
52
|
-
reportId: (0, revenueForTimeframeEpic_1.reportIdUniqueKey)(), // reportId without forecastId init to fetch Accouts incomeBalances
|
|
64
|
+
reportId: (0, revenueForTimeframeEpic_1.reportIdUniqueKey)(undefined, useCustomRange), // reportId without forecastId init to fetch Accouts incomeBalances
|
|
53
65
|
sectionId: 'income',
|
|
54
66
|
});
|
|
55
67
|
// To get cogsBalance without forecast init.
|
|
56
68
|
const cogsBalance = (0, sectionAccountsViewSelector_1.getSectionBalances)(sectionsState, {
|
|
57
|
-
reportId: (0, revenueForTimeframeEpic_1.reportIdUniqueKey)(), // reportId without forecastId init to fetch Accouts cogsBalance
|
|
69
|
+
reportId: (0, revenueForTimeframeEpic_1.reportIdUniqueKey)(undefined, useCustomRange), // reportId without forecastId init to fetch Accouts cogsBalance
|
|
58
70
|
sectionId: 'cogs',
|
|
59
71
|
});
|
|
60
72
|
const grossMarginBalances = (0, sectionAccountsViewSelector_1.getSectionBalances)(sectionsState, {
|
|
61
|
-
reportId: (0, revenueForTimeframeEpic_1.reportIdUniqueKey)(), // reportId without forecastId init to fetch Accouts cogsBalance
|
|
73
|
+
reportId: (0, revenueForTimeframeEpic_1.reportIdUniqueKey)(undefined, useCustomRange), // reportId without forecastId init to fetch Accouts cogsBalance
|
|
62
74
|
sectionId: 'grossMargin',
|
|
63
75
|
});
|
|
64
76
|
const incomeOrCogs = incomeBalance != null
|
|
@@ -100,6 +112,8 @@ const getRevenueReport = (filter, accountState, accountGroupState, sectionsState
|
|
|
100
112
|
allTimeframeTicks,
|
|
101
113
|
insights: revenueWithForecastState.revenue.insights ?? [], // Picking insights from RevenueState in both foregast mode on and off
|
|
102
114
|
availableNumberOfPeriods: (0, dataAvailable_1.getNumberOfPeriods)(revState.firstMonthOfFY, filter.timeframe, revState.dataAvailable),
|
|
115
|
+
// Surface the saved custom timeframe so the detail picker can restore them.
|
|
116
|
+
customTimeframe: revenueWithForecastState.uiState.customTimeframe,
|
|
103
117
|
};
|
|
104
118
|
};
|
|
105
119
|
exports.getRevenueReport = getRevenueReport;
|
|
@@ -157,7 +171,10 @@ exports.getRevenueForSelectedRange = (0, toolkit_1.createSelector)((state) => st
|
|
|
157
171
|
selectedForecast?.id != null &&
|
|
158
172
|
(0, exports.getRevenueReportFetchState)(selectedForecast.id, revenueWithForecastState).fetchState === 'Completed'
|
|
159
173
|
? getRevenueWithForecastOnDataAvailableDateRange(noFilter, selectedForecast?.id, accountState, accountGroupState, sectionAccountsViewState, forecastListState, revenueWithForecastState, forecastState)
|
|
160
|
-
: (0, exports.getRevenueReport)(noFilter, accountState, accountGroupState, sectionAccountsViewState, forecastListState, revenueWithForecastState, forecastState, selectedForecast?.id
|
|
174
|
+
: (0, exports.getRevenueReport)(noFilter, accountState, accountGroupState, sectionAccountsViewState, forecastListState, revenueWithForecastState, forecastState, selectedForecast?.id,
|
|
175
|
+
// Detail selectors read the custom slot when the detail is in custom
|
|
176
|
+
// mode; the dashboard's getRevenueForLast4Periods does not.
|
|
177
|
+
revenueWithForecastState.uiState.customTimeframe != null);
|
|
161
178
|
});
|
|
162
179
|
exports.getRevenueForHighlightedRange = (0, toolkit_1.createSelector)((state) => state.accountGroupState, (state) => state.accountState, (state) => state.revenueState, (state) => state.forecastState, (state) => state.forecastListState, (state) => state.sectionAccountsViewState, (accountGroupState, accountState, revenueWithForecastState, forecastState, forecastListState, sectionsState) => {
|
|
163
180
|
const { timeframe, highlightedCOABalancesRange, selectedAdditionalBalances, maxNumOfPeriodsToHighlight, isForecastModeOn, selectedForecast, } = revenueWithForecastState.uiState;
|
|
@@ -168,7 +185,10 @@ exports.getRevenueForHighlightedRange = (0, toolkit_1.createSelector)((state) =>
|
|
|
168
185
|
(0, exports.getRevenueReportFetchState)(selectedForecast.id, revenueWithForecastState)
|
|
169
186
|
.fetchState === 'Completed'
|
|
170
187
|
? getRevenueWithForecastOnDataAvailableDateRange(filter, selectedForecast?.id, accountState, accountGroupState, sectionsState, forecastListState, revenueWithForecastState, forecastState)
|
|
171
|
-
: (0, exports.getRevenueReport)(filter, accountState, accountGroupState, sectionsState, forecastListState, revenueWithForecastState, forecastState, selectedForecast?.id
|
|
188
|
+
: (0, exports.getRevenueReport)(filter, accountState, accountGroupState, sectionsState, forecastListState, revenueWithForecastState, forecastState, selectedForecast?.id,
|
|
189
|
+
// Detail selectors read the custom slot when the detail is in custom
|
|
190
|
+
// mode; the dashboard's getRevenueForLast4Periods does not.
|
|
191
|
+
revenueWithForecastState.uiState.customTimeframe != null);
|
|
172
192
|
});
|
|
173
193
|
/**
|
|
174
194
|
* Get Revenue with forecast data overlaid on actuals.
|
|
@@ -19,6 +19,14 @@ export interface RevenueState extends Report {
|
|
|
19
19
|
};
|
|
20
20
|
insights: InsightSummary[];
|
|
21
21
|
cogs?: COABalanceGroupedByPeriod;
|
|
22
|
+
customCogs?: COABalanceGroupedByPeriod;
|
|
23
|
+
customFetchState?: {
|
|
24
|
+
month: FetchStateAndError;
|
|
25
|
+
quarter: FetchStateAndError;
|
|
26
|
+
year: FetchStateAndError;
|
|
27
|
+
};
|
|
28
|
+
customGrossMargin?: COABalanceGroupedByPeriod;
|
|
29
|
+
customIncome?: COABalanceGroupedByPeriod;
|
|
22
30
|
forecastId?: ID;
|
|
23
31
|
grossMargin?: COABalanceGroupedByPeriod;
|
|
24
32
|
income?: COABalanceGroupedByPeriod;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.94-betaNB1",
|
|
4
4
|
"description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/esm/index.js",
|