@zeniai/client-epic-state 5.2.79 → 5.2.80
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/entity/invoicing/dunningCase/dunningCasePayload.d.ts +2 -0
- package/lib/entity/invoicing/dunningCase/dunningCasePayload.js +1 -0
- package/lib/entity/invoicing/dunningCase/dunningCaseState.d.ts +2 -0
- package/lib/esm/entity/invoicing/dunningCase/dunningCasePayload.js +1 -0
- package/lib/esm/view/invoicing/invoicingDunningCaseDetailView/fetchInvoicingDunningCaseDetailPageEpic.js +6 -0
- package/lib/esm/view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector.js +4 -1
- package/lib/esm/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListPageEpic.js +7 -0
- package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js +23 -1
- package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js +3 -0
- package/lib/index.d.ts +1 -1
- package/lib/view/invoicing/invoicingDunningCaseDetailView/fetchInvoicingDunningCaseDetailPageEpic.d.ts +2 -1
- package/lib/view/invoicing/invoicingDunningCaseDetailView/fetchInvoicingDunningCaseDetailPageEpic.js +6 -0
- package/lib/view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector.d.ts +3 -0
- package/lib/view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector.js +4 -1
- package/lib/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListPageEpic.d.ts +2 -1
- package/lib/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListPageEpic.js +7 -0
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.d.ts +18 -2
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js +25 -2
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.d.ts +2 -2
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js +3 -0
- package/package.json +1 -1
|
@@ -21,6 +21,8 @@ export interface InvoicingDunningCasePayload {
|
|
|
21
21
|
next_retry?: string;
|
|
22
22
|
paused_reason?: string;
|
|
23
23
|
paused_until?: string;
|
|
24
|
+
/** The dunning schedule step a retry runs next. */
|
|
25
|
+
schedule_step?: number | null;
|
|
24
26
|
subscription_id?: string;
|
|
25
27
|
}
|
|
26
28
|
export declare const mapInvoicingDunningCasePayloadToState: (payload: InvoicingDunningCasePayload) => InvoicingDunningCase;
|
|
@@ -30,6 +30,7 @@ const mapInvoicingDunningCasePayloadToState = (payload) => {
|
|
|
30
30
|
nextRetry: payload.next_retry != null ? (0, zeniDayJS_1.date)(payload.next_retry) : undefined,
|
|
31
31
|
pausedReason: payload.paused_reason,
|
|
32
32
|
pausedUntil: payload.paused_until != null ? (0, zeniDayJS_1.date)(payload.paused_until) : undefined,
|
|
33
|
+
scheduleStep: payload.schedule_step ?? undefined,
|
|
33
34
|
subscriptionID: payload.subscription_id,
|
|
34
35
|
};
|
|
35
36
|
};
|
|
@@ -22,6 +22,8 @@ export interface InvoicingDunningCase {
|
|
|
22
22
|
nextRetry?: ZeniDate;
|
|
23
23
|
pausedReason?: string;
|
|
24
24
|
pausedUntil?: ZeniDate;
|
|
25
|
+
/** The dunning schedule step a retry runs next. */
|
|
26
|
+
scheduleStep?: number;
|
|
25
27
|
subscriptionID?: ID;
|
|
26
28
|
}
|
|
27
29
|
export interface InvoicingDunningCaseState {
|
|
@@ -27,6 +27,7 @@ export const mapInvoicingDunningCasePayloadToState = (payload) => {
|
|
|
27
27
|
nextRetry: payload.next_retry != null ? date(payload.next_retry) : undefined,
|
|
28
28
|
pausedReason: payload.paused_reason,
|
|
29
29
|
pausedUntil: payload.paused_until != null ? date(payload.paused_until) : undefined,
|
|
30
|
+
scheduleStep: payload.schedule_step ?? undefined,
|
|
30
31
|
subscriptionID: payload.subscription_id,
|
|
31
32
|
};
|
|
32
33
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { EMPTY, from } from 'rxjs';
|
|
2
2
|
import { filter, mergeMap, withLatestFrom } from 'rxjs/operators';
|
|
3
|
+
import { fetchInvoicingSettings } from '../settingsView/settingsViewReducer';
|
|
4
|
+
import { getInvoicingSettingsFetchState } from '../settingsView/settingsViewSelector';
|
|
3
5
|
import { fetchInvoicingDunningCaseDetail, fetchInvoicingDunningCaseDetailPage, fetchInvoicingDunningEmailPreviewPage, } from './invoicingDunningCaseDetailViewReducer';
|
|
4
6
|
/**
|
|
5
7
|
* Fetch unless the record is already loaded or in flight — or always when the
|
|
@@ -25,5 +27,9 @@ export const fetchInvoicingDunningCaseDetailPageEpic = (actions$, state$) => act
|
|
|
25
27
|
pageActions.push(fetchInvoicingDunningCaseDetail({ id }));
|
|
26
28
|
}
|
|
27
29
|
pageActions.push(fetchInvoicingDunningEmailPreviewPage({ id, cacheOverride }));
|
|
30
|
+
// The current step is labelled from the settings schedule.
|
|
31
|
+
if (shouldFetch(getInvoicingSettingsFetchState(state), false)) {
|
|
32
|
+
pageActions.push(fetchInvoicingSettings());
|
|
33
|
+
}
|
|
28
34
|
return pageActions.length > 0 ? from(pageActions) : EMPTY;
|
|
29
35
|
}));
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getInvoicingDunningCaseById as getInvoicingDunningCaseByIdFromState } from '../../../entity/invoicing/dunningCase/dunningCaseSelector';
|
|
2
2
|
import { getInvoiceById } from '../../../entity/invoicing/invoice/invoiceSelector';
|
|
3
3
|
import { invoicingFieldHelpForGroup } from '../invoicingConfigView/invoicingConfigViewSelector';
|
|
4
|
+
import { toInvoicingDunningCaseStep, } from '../invoicingDunningCaseListView/invoicingDunningCaseListViewSelector';
|
|
5
|
+
import { getInvoicingSettings } from '../settingsView/settingsViewSelector';
|
|
4
6
|
const EMAIL_PREVIEW_NOT_STARTED = {
|
|
5
7
|
error: undefined,
|
|
6
8
|
fetchState: 'Not-Started',
|
|
@@ -16,10 +18,11 @@ export const getInvoicingDunningCaseDetail = (state, invoicingDunningCaseID) =>
|
|
|
16
18
|
: undefined,
|
|
17
19
|
fieldHelp: invoicingFieldHelpForGroup(state, 'dunning'),
|
|
18
20
|
actionState: state.invoicingDunningCaseDetailViewState.actionStateById[invoicingDunningCaseID] ?? { error: undefined, fetchState: 'Not-Started' },
|
|
19
|
-
dunningCase
|
|
21
|
+
dunningCase,
|
|
20
22
|
emailPreview: id === invoicingDunningCaseID ? emailPreview : EMAIL_PREVIEW_NOT_STARTED,
|
|
21
23
|
fetchState,
|
|
22
24
|
error,
|
|
25
|
+
step: toInvoicingDunningCaseStep(dunningCase?.scheduleStep, getInvoicingSettings(state)?.dunning_schedule, state.invoicingConfigViewState.dunningScheduleActionOptions),
|
|
23
26
|
version: 1.0,
|
|
24
27
|
};
|
|
25
28
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { concat, from } from 'rxjs';
|
|
2
2
|
import { filter, mergeMap } from 'rxjs/operators';
|
|
3
3
|
import { getInvoicingListTab, invoicingListSourceTab, planInvoicingListTabFetch, } from '../../invoicingListTabCache';
|
|
4
|
+
import { fetchInvoicingSettings } from '../../settingsView/settingsViewReducer';
|
|
5
|
+
import { getInvoicingSettingsFetchState } from '../../settingsView/settingsViewSelector';
|
|
4
6
|
import { fetchInvoicingDunningCaseCounts, fetchInvoicingDunningCaseList, fetchInvoicingDunningCaseListPage, } from '../invoicingDunningCaseListViewReducer';
|
|
5
7
|
/**
|
|
6
8
|
* Fetch unless the endpoint is already loaded or in flight — or always when the
|
|
@@ -36,5 +38,10 @@ export const fetchInvoicingDunningCaseListPageEpic = (actions$, state$) => actio
|
|
|
36
38
|
if (shouldFetch(state.countsFetchState, cacheOverride)) {
|
|
37
39
|
pageActions.push(fetchInvoicingDunningCaseCounts());
|
|
38
40
|
}
|
|
41
|
+
// The step column labels steps from the settings schedule; a search or
|
|
42
|
+
// sort change does not touch settings, so only a missing load fetches.
|
|
43
|
+
if (shouldFetch(getInvoicingSettingsFetchState(state$.value), false)) {
|
|
44
|
+
pageActions.push(fetchInvoicingSettings());
|
|
45
|
+
}
|
|
39
46
|
return concat(from(pageActions));
|
|
40
47
|
}));
|
package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js
CHANGED
|
@@ -3,12 +3,30 @@ import { getInvoicingDunningCasesByIds } from '../../../entity/invoicing/dunning
|
|
|
3
3
|
import { getInvoicingListTab, invoicingListSourceTab, } from '../invoicingListTabCache';
|
|
4
4
|
import { invoicingTabIdsFromConfig } from '../invoicingTabHelper';
|
|
5
5
|
import { ALL_INVOICING_DUNNING_CASE_TAB_IDS, INVOICING_DUNNING_CASE_COLUMNS, } from './invoicingDunningCaseListViewState';
|
|
6
|
+
/**
|
|
7
|
+
* Join a case's `scheduleStep` with the tenant's dunning schedule and the
|
|
8
|
+
* config's action labels. The step alone is still shown when settings have not
|
|
9
|
+
* loaded or the schedule no longer has that step.
|
|
10
|
+
*/
|
|
11
|
+
export const toInvoicingDunningCaseStep = (scheduleStep, schedule, actionOptions) => {
|
|
12
|
+
if (scheduleStep == null) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const action = schedule?.find((entry) => entry.step === scheduleStep)?.action;
|
|
16
|
+
return {
|
|
17
|
+
actionName: action != null
|
|
18
|
+
? actionOptions.find((option) => option.code === action)?.name
|
|
19
|
+
: undefined,
|
|
20
|
+
step: scheduleStep,
|
|
21
|
+
totalSteps: schedule != null && schedule.length > 0 ? schedule.length : undefined,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
6
24
|
/**
|
|
7
25
|
* Memoized so the denormalized `dunningCases` array (and the wrapping view
|
|
8
26
|
* object) keep referential identity until the dunning-case entity slice or the
|
|
9
27
|
* list-view slice actually change.
|
|
10
28
|
*/
|
|
11
|
-
export const getInvoicingDunningCaseListView = createSelector((state) => state.invoicingDunningCaseState, (state) => state.invoicingDunningCaseListViewState, (state) => state.invoicingConfigViewState.dunningCaseStatusOptions, (dunningCaseState, listViewState, statusOptions) => {
|
|
29
|
+
export const getInvoicingDunningCaseListView = createSelector((state) => state.invoicingDunningCaseState, (state) => state.invoicingDunningCaseListViewState, (state) => state.invoicingConfigViewState.dunningCaseStatusOptions, (state) => state.invoicingSettingsViewState.settings?.dunning_schedule, (state) => state.invoicingConfigViewState.dunningScheduleActionOptions, (dunningCaseState, listViewState, statusOptions, schedule, actionOptions) => {
|
|
12
30
|
const { activeTab } = listViewState;
|
|
13
31
|
const tab = getInvoicingListTab(listViewState.byTab, invoicingListSourceTab(activeTab));
|
|
14
32
|
const dunningCases = getInvoicingDunningCasesByIds(dunningCaseState, tab.ids);
|
|
@@ -28,6 +46,10 @@ export const getInvoicingDunningCaseListView = createSelector((state) => state.i
|
|
|
28
46
|
statusOptions,
|
|
29
47
|
}),
|
|
30
48
|
sort: listViewState.sort,
|
|
49
|
+
stepById: Object.fromEntries(dunningCases.flatMap((dunningCase) => {
|
|
50
|
+
const step = toInvoicingDunningCaseStep(dunningCase.scheduleStep, schedule, actionOptions);
|
|
51
|
+
return step != null ? [[dunningCase.id, step]] : [];
|
|
52
|
+
})),
|
|
31
53
|
version: 1.0,
|
|
32
54
|
};
|
|
33
55
|
});
|
package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js
CHANGED
|
@@ -3,6 +3,7 @@ export const ALL_INVOICING_DUNNING_CASE_SORT_KEYS = [
|
|
|
3
3
|
'customer',
|
|
4
4
|
'invoice',
|
|
5
5
|
'attempts',
|
|
6
|
+
'step',
|
|
6
7
|
'next_retry',
|
|
7
8
|
'days_past_due',
|
|
8
9
|
'failureReason',
|
|
@@ -14,6 +15,8 @@ export const INVOICING_DUNNING_CASE_COLUMNS = [
|
|
|
14
15
|
{ key: 'customer', sortable: true },
|
|
15
16
|
{ key: 'invoice', sortable: true },
|
|
16
17
|
{ key: 'attempts', sortable: true },
|
|
18
|
+
// The list API does not sort on `schedule_step`.
|
|
19
|
+
{ key: 'step', sortable: false },
|
|
17
20
|
{ key: 'next_retry', sortable: true },
|
|
18
21
|
{ key: 'days_past_due', sortable: true },
|
|
19
22
|
{ key: 'failureReason', sortable: false },
|
package/lib/index.d.ts
CHANGED
|
@@ -1219,7 +1219,7 @@ export { fetchInvoicingDunningCaseCounts, fetchInvoicingDunningCaseList, fetchIn
|
|
|
1219
1219
|
export { ALL_INVOICING_DUNNING_CASE_SORT_KEYS, ALL_INVOICING_DUNNING_CASE_TAB_IDS, INVOICING_DUNNING_CASE_COLUMNS, } from './view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState';
|
|
1220
1220
|
export type { InvoicingDunningCaseColumnConfig, InvoicingDunningCaseFilters, InvoicingDunningCaseSortKey, InvoicingDunningCaseTabId, } from './view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState';
|
|
1221
1221
|
export { getInvoicingDunningCaseListView } from './view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector';
|
|
1222
|
-
export type { InvoicingDunningCaseListView } from './view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector';
|
|
1222
|
+
export type { InvoicingDunningCaseListView, InvoicingDunningCaseStep, } from './view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector';
|
|
1223
1223
|
export { clearInvoicingDunningCaseDetailView, fetchInvoicingDunningCaseDetail, fetchInvoicingDunningCaseDetailPage, fetchInvoicingDunningEmailPreviewPage, invalidateInvoicingDunningEmailPreview, } from './view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewReducer';
|
|
1224
1224
|
export { getInvoicingDunningCaseById, getInvoicingDunningCaseDetail, getInvoicingDunningEmailPreview, } from './view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector';
|
|
1225
1225
|
export type { InvoicingDunningCaseDetailView } from './view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import { RootState } from '../../../rootStateTypes';
|
|
4
|
+
import { fetchInvoicingSettings } from '../settingsView/settingsViewReducer';
|
|
4
5
|
import { fetchInvoicingDunningCaseDetail, fetchInvoicingDunningCaseDetailPage, fetchInvoicingDunningEmailPreviewPage } from './invoicingDunningCaseDetailViewReducer';
|
|
5
|
-
export type ActionType = ReturnType<typeof fetchInvoicingDunningCaseDetailPage> | ReturnType<typeof fetchInvoicingDunningCaseDetail> | ReturnType<typeof fetchInvoicingDunningEmailPreviewPage>;
|
|
6
|
+
export type ActionType = ReturnType<typeof fetchInvoicingDunningCaseDetailPage> | ReturnType<typeof fetchInvoicingDunningCaseDetail> | ReturnType<typeof fetchInvoicingDunningEmailPreviewPage> | ReturnType<typeof fetchInvoicingSettings>;
|
|
6
7
|
/**
|
|
7
8
|
* Orchestrates the dunning case detail page: the case record, plus a warm of
|
|
8
9
|
* the email composer's preview so the dialog paints with content on first
|
package/lib/view/invoicing/invoicingDunningCaseDetailView/fetchInvoicingDunningCaseDetailPageEpic.js
CHANGED
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.fetchInvoicingDunningCaseDetailPageEpic = void 0;
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
|
+
const settingsViewReducer_1 = require("../settingsView/settingsViewReducer");
|
|
7
|
+
const settingsViewSelector_1 = require("../settingsView/settingsViewSelector");
|
|
6
8
|
const invoicingDunningCaseDetailViewReducer_1 = require("./invoicingDunningCaseDetailViewReducer");
|
|
7
9
|
/**
|
|
8
10
|
* Fetch unless the record is already loaded or in flight — or always when the
|
|
@@ -28,6 +30,10 @@ const fetchInvoicingDunningCaseDetailPageEpic = (actions$, state$) => actions$.p
|
|
|
28
30
|
pageActions.push((0, invoicingDunningCaseDetailViewReducer_1.fetchInvoicingDunningCaseDetail)({ id }));
|
|
29
31
|
}
|
|
30
32
|
pageActions.push((0, invoicingDunningCaseDetailViewReducer_1.fetchInvoicingDunningEmailPreviewPage)({ id, cacheOverride }));
|
|
33
|
+
// The current step is labelled from the settings schedule.
|
|
34
|
+
if (shouldFetch((0, settingsViewSelector_1.getInvoicingSettingsFetchState)(state), false)) {
|
|
35
|
+
pageActions.push((0, settingsViewReducer_1.fetchInvoicingSettings)());
|
|
36
|
+
}
|
|
31
37
|
return pageActions.length > 0 ? (0, rxjs_1.from)(pageActions) : rxjs_1.EMPTY;
|
|
32
38
|
}));
|
|
33
39
|
exports.fetchInvoicingDunningCaseDetailPageEpic = fetchInvoicingDunningCaseDetailPageEpic;
|
|
@@ -4,6 +4,7 @@ import { InvoicingDunningCase } from '../../../entity/invoicing/dunningCase/dunn
|
|
|
4
4
|
import { InvoicingInvoice } from '../../../entity/invoicing/invoice/invoiceState';
|
|
5
5
|
import type { InvoicingFieldHelpByCode } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
6
6
|
import { RootState } from '../../../rootStateTypes';
|
|
7
|
+
import { InvoicingDunningCaseStep } from '../invoicingDunningCaseListView/invoicingDunningCaseListViewSelector';
|
|
7
8
|
import { InvoicingDunningEmailPreviewState } from './invoicingDunningCaseDetailViewState';
|
|
8
9
|
/**
|
|
9
10
|
* Read-only view for the dunning case detail page: the dunning case entity + its
|
|
@@ -24,6 +25,8 @@ export interface InvoicingDunningCaseDetailView extends SelectorView {
|
|
|
24
25
|
* selector rather than pairing this with the invoice detail view.
|
|
25
26
|
*/
|
|
26
27
|
linkedInvoice?: InvoicingInvoice;
|
|
28
|
+
/** The schedule step a retry runs next; absent when the case has none. */
|
|
29
|
+
step?: InvoicingDunningCaseStep;
|
|
27
30
|
}
|
|
28
31
|
export declare const getInvoicingDunningCaseById: (state: RootState, id: string) => InvoicingDunningCase | undefined;
|
|
29
32
|
export declare const getInvoicingDunningCaseDetail: (state: RootState, invoicingDunningCaseID: ID) => InvoicingDunningCaseDetailView;
|
package/lib/view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector.js
CHANGED
|
@@ -4,6 +4,8 @@ exports.getInvoicingDunningEmailPreview = exports.getInvoicingDunningCaseDetail
|
|
|
4
4
|
const dunningCaseSelector_1 = require("../../../entity/invoicing/dunningCase/dunningCaseSelector");
|
|
5
5
|
const invoiceSelector_1 = require("../../../entity/invoicing/invoice/invoiceSelector");
|
|
6
6
|
const invoicingConfigViewSelector_1 = require("../invoicingConfigView/invoicingConfigViewSelector");
|
|
7
|
+
const invoicingDunningCaseListViewSelector_1 = require("../invoicingDunningCaseListView/invoicingDunningCaseListViewSelector");
|
|
8
|
+
const settingsViewSelector_1 = require("../settingsView/settingsViewSelector");
|
|
7
9
|
const EMAIL_PREVIEW_NOT_STARTED = {
|
|
8
10
|
error: undefined,
|
|
9
11
|
fetchState: 'Not-Started',
|
|
@@ -20,10 +22,11 @@ const getInvoicingDunningCaseDetail = (state, invoicingDunningCaseID) => {
|
|
|
20
22
|
: undefined,
|
|
21
23
|
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'dunning'),
|
|
22
24
|
actionState: state.invoicingDunningCaseDetailViewState.actionStateById[invoicingDunningCaseID] ?? { error: undefined, fetchState: 'Not-Started' },
|
|
23
|
-
dunningCase
|
|
25
|
+
dunningCase,
|
|
24
26
|
emailPreview: id === invoicingDunningCaseID ? emailPreview : EMAIL_PREVIEW_NOT_STARTED,
|
|
25
27
|
fetchState,
|
|
26
28
|
error,
|
|
29
|
+
step: (0, invoicingDunningCaseListViewSelector_1.toInvoicingDunningCaseStep)(dunningCase?.scheduleStep, (0, settingsViewSelector_1.getInvoicingSettings)(state)?.dunning_schedule, state.invoicingConfigViewState.dunningScheduleActionOptions),
|
|
27
30
|
version: 1.0,
|
|
28
31
|
};
|
|
29
32
|
};
|
|
@@ -2,12 +2,13 @@ import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import { updateInvoicingDunningCases } from '../../../../entity/invoicing/dunningCase/dunningCaseReducer';
|
|
4
4
|
import { RootState } from '../../../../rootStateTypes';
|
|
5
|
+
import { fetchInvoicingSettings } from '../../settingsView/settingsViewReducer';
|
|
5
6
|
import { fetchInvoicingDunningCaseCounts, fetchInvoicingDunningCaseList, fetchInvoicingDunningCaseListPage, updateInvoicingDunningCaseCounts, updateInvoicingDunningCaseCountsFailure, updateInvoicingDunningCaseList, updateInvoicingDunningCaseListFailure } from '../invoicingDunningCaseListViewReducer';
|
|
6
7
|
/**
|
|
7
8
|
* Aggregate of every action emitted across the dunning-case list view epics.
|
|
8
9
|
* Wired into the root action union for this view.
|
|
9
10
|
*/
|
|
10
|
-
export type ActionType = ReturnType<typeof fetchInvoicingDunningCaseList> | ReturnType<typeof fetchInvoicingDunningCaseListPage> | ReturnType<typeof fetchInvoicingDunningCaseCounts> | ReturnType<typeof updateInvoicingDunningCaseList> | ReturnType<typeof updateInvoicingDunningCaseListFailure> | ReturnType<typeof updateInvoicingDunningCaseCounts> | ReturnType<typeof updateInvoicingDunningCaseCountsFailure> | ReturnType<typeof updateInvoicingDunningCases>;
|
|
11
|
+
export type ActionType = ReturnType<typeof fetchInvoicingDunningCaseList> | ReturnType<typeof fetchInvoicingDunningCaseListPage> | ReturnType<typeof fetchInvoicingDunningCaseCounts> | ReturnType<typeof updateInvoicingDunningCaseList> | ReturnType<typeof updateInvoicingDunningCaseListFailure> | ReturnType<typeof updateInvoicingDunningCaseCounts> | ReturnType<typeof updateInvoicingDunningCaseCountsFailure> | ReturnType<typeof updateInvoicingDunningCases> | ReturnType<typeof fetchInvoicingSettings>;
|
|
11
12
|
/**
|
|
12
13
|
* Orchestrates the dunning cases list page: on `fetchInvoicingDunningCaseListPage`,
|
|
13
14
|
* fans out to the list and counts fetches, skipping any whose data is
|
|
@@ -4,6 +4,8 @@ exports.fetchInvoicingDunningCaseListPageEpic = void 0;
|
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
6
|
const invoicingListTabCache_1 = require("../../invoicingListTabCache");
|
|
7
|
+
const settingsViewReducer_1 = require("../../settingsView/settingsViewReducer");
|
|
8
|
+
const settingsViewSelector_1 = require("../../settingsView/settingsViewSelector");
|
|
7
9
|
const invoicingDunningCaseListViewReducer_1 = require("../invoicingDunningCaseListViewReducer");
|
|
8
10
|
/**
|
|
9
11
|
* Fetch unless the endpoint is already loaded or in flight — or always when the
|
|
@@ -39,6 +41,11 @@ const fetchInvoicingDunningCaseListPageEpic = (actions$, state$) => actions$.pip
|
|
|
39
41
|
if (shouldFetch(state.countsFetchState, cacheOverride)) {
|
|
40
42
|
pageActions.push((0, invoicingDunningCaseListViewReducer_1.fetchInvoicingDunningCaseCounts)());
|
|
41
43
|
}
|
|
44
|
+
// The step column labels steps from the settings schedule; a search or
|
|
45
|
+
// sort change does not touch settings, so only a missing load fetches.
|
|
46
|
+
if (shouldFetch((0, settingsViewSelector_1.getInvoicingSettingsFetchState)(state$.value), false)) {
|
|
47
|
+
pageActions.push((0, settingsViewReducer_1.fetchInvoicingSettings)());
|
|
48
|
+
}
|
|
42
49
|
return (0, rxjs_1.concat)((0, rxjs_1.from)(pageActions));
|
|
43
50
|
}));
|
|
44
51
|
exports.fetchInvoicingDunningCaseListPageEpic = fetchInvoicingDunningCaseListPageEpic;
|
package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { FetchStateAndError } from '../../../commonStateTypes/common';
|
|
1
|
+
import { FetchStateAndError, ID } from '../../../commonStateTypes/common';
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
3
|
import { InvoicingDunningCase } from '../../../entity/invoicing/dunningCase/dunningCaseState';
|
|
4
|
-
import { InvoicingListCounts, InvoicingNamedOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
4
|
+
import { InvoicingDunningActionOption, InvoicingDunningScheduleStepPayload, InvoicingListCounts, InvoicingNamedOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
5
5
|
import { RootState } from '../../../rootStateTypes';
|
|
6
6
|
import { InvoicingListSort } from '../invoicingApiHelper';
|
|
7
7
|
import { InvoicingDunningCaseColumnConfig, InvoicingDunningCaseFilters, InvoicingDunningCaseTabId } from './invoicingDunningCaseListViewState';
|
|
@@ -14,9 +14,25 @@ export interface InvoicingDunningCaseListView extends SelectorView {
|
|
|
14
14
|
filters: InvoicingDunningCaseFilters;
|
|
15
15
|
/** Config status/type list; the page labels tabs and badges from it. */
|
|
16
16
|
statusOptions: InvoicingNamedOption[];
|
|
17
|
+
/** Each listed case's schedule step, keyed by case id; absent when unknown. */
|
|
18
|
+
stepById: Record<ID, InvoicingDunningCaseStep>;
|
|
17
19
|
tabIds: InvoicingDunningCaseTabId[];
|
|
18
20
|
sort?: InvoicingListSort;
|
|
19
21
|
}
|
|
22
|
+
/** The dunning schedule step a case's retry runs next, for display. */
|
|
23
|
+
export interface InvoicingDunningCaseStep {
|
|
24
|
+
step: number;
|
|
25
|
+
/** The configured step's action, e.g. "Email and retry". */
|
|
26
|
+
actionName?: string;
|
|
27
|
+
/** How many steps the tenant's schedule has, when settings are loaded. */
|
|
28
|
+
totalSteps?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Join a case's `scheduleStep` with the tenant's dunning schedule and the
|
|
32
|
+
* config's action labels. The step alone is still shown when settings have not
|
|
33
|
+
* loaded or the schedule no longer has that step.
|
|
34
|
+
*/
|
|
35
|
+
export declare const toInvoicingDunningCaseStep: (scheduleStep: number | undefined, schedule: InvoicingDunningScheduleStepPayload[] | undefined, actionOptions: InvoicingDunningActionOption[]) => InvoicingDunningCaseStep | undefined;
|
|
20
36
|
/**
|
|
21
37
|
* Memoized so the denormalized `dunningCases` array (and the wrapping view
|
|
22
38
|
* object) keep referential identity until the dunning-case entity slice or the
|
package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getInvoicingDunningCaseListView = void 0;
|
|
3
|
+
exports.getInvoicingDunningCaseListView = exports.toInvoicingDunningCaseStep = void 0;
|
|
4
4
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
5
5
|
const dunningCaseSelector_1 = require("../../../entity/invoicing/dunningCase/dunningCaseSelector");
|
|
6
6
|
const invoicingListTabCache_1 = require("../invoicingListTabCache");
|
|
7
7
|
const invoicingTabHelper_1 = require("../invoicingTabHelper");
|
|
8
8
|
const invoicingDunningCaseListViewState_1 = require("./invoicingDunningCaseListViewState");
|
|
9
|
+
/**
|
|
10
|
+
* Join a case's `scheduleStep` with the tenant's dunning schedule and the
|
|
11
|
+
* config's action labels. The step alone is still shown when settings have not
|
|
12
|
+
* loaded or the schedule no longer has that step.
|
|
13
|
+
*/
|
|
14
|
+
const toInvoicingDunningCaseStep = (scheduleStep, schedule, actionOptions) => {
|
|
15
|
+
if (scheduleStep == null) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const action = schedule?.find((entry) => entry.step === scheduleStep)?.action;
|
|
19
|
+
return {
|
|
20
|
+
actionName: action != null
|
|
21
|
+
? actionOptions.find((option) => option.code === action)?.name
|
|
22
|
+
: undefined,
|
|
23
|
+
step: scheduleStep,
|
|
24
|
+
totalSteps: schedule != null && schedule.length > 0 ? schedule.length : undefined,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
exports.toInvoicingDunningCaseStep = toInvoicingDunningCaseStep;
|
|
9
28
|
/**
|
|
10
29
|
* Memoized so the denormalized `dunningCases` array (and the wrapping view
|
|
11
30
|
* object) keep referential identity until the dunning-case entity slice or the
|
|
12
31
|
* list-view slice actually change.
|
|
13
32
|
*/
|
|
14
|
-
exports.getInvoicingDunningCaseListView = (0, toolkit_1.createSelector)((state) => state.invoicingDunningCaseState, (state) => state.invoicingDunningCaseListViewState, (state) => state.invoicingConfigViewState.dunningCaseStatusOptions, (dunningCaseState, listViewState, statusOptions) => {
|
|
33
|
+
exports.getInvoicingDunningCaseListView = (0, toolkit_1.createSelector)((state) => state.invoicingDunningCaseState, (state) => state.invoicingDunningCaseListViewState, (state) => state.invoicingConfigViewState.dunningCaseStatusOptions, (state) => state.invoicingSettingsViewState.settings?.dunning_schedule, (state) => state.invoicingConfigViewState.dunningScheduleActionOptions, (dunningCaseState, listViewState, statusOptions, schedule, actionOptions) => {
|
|
15
34
|
const { activeTab } = listViewState;
|
|
16
35
|
const tab = (0, invoicingListTabCache_1.getInvoicingListTab)(listViewState.byTab, (0, invoicingListTabCache_1.invoicingListSourceTab)(activeTab));
|
|
17
36
|
const dunningCases = (0, dunningCaseSelector_1.getInvoicingDunningCasesByIds)(dunningCaseState, tab.ids);
|
|
@@ -31,6 +50,10 @@ exports.getInvoicingDunningCaseListView = (0, toolkit_1.createSelector)((state)
|
|
|
31
50
|
statusOptions,
|
|
32
51
|
}),
|
|
33
52
|
sort: listViewState.sort,
|
|
53
|
+
stepById: Object.fromEntries(dunningCases.flatMap((dunningCase) => {
|
|
54
|
+
const step = (0, exports.toInvoicingDunningCaseStep)(dunningCase.scheduleStep, schedule, actionOptions);
|
|
55
|
+
return step != null ? [[dunningCase.id, step]] : [];
|
|
56
|
+
})),
|
|
34
57
|
version: 1.0,
|
|
35
58
|
};
|
|
36
59
|
});
|
package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import { InvoicingListByTab } from '../invoicingListTabCache';
|
|
|
5
5
|
export interface InvoicingDunningCaseFilters {
|
|
6
6
|
search?: string;
|
|
7
7
|
}
|
|
8
|
-
export declare const ALL_INVOICING_DUNNING_CASE_SORT_KEYS: readonly ["customer", "invoice", "attempts", "next_retry", "days_past_due", "failureReason", "status", "amount"];
|
|
9
|
-
export declare const toInvoicingDunningCaseSortKey: (v: string) => "status" | "invoice" | "amount" | "customer" | "attempts" | "next_retry" | "days_past_due" | "failureReason";
|
|
8
|
+
export declare const ALL_INVOICING_DUNNING_CASE_SORT_KEYS: readonly ["customer", "invoice", "attempts", "step", "next_retry", "days_past_due", "failureReason", "status", "amount"];
|
|
9
|
+
export declare const toInvoicingDunningCaseSortKey: (v: string) => "status" | "invoice" | "amount" | "customer" | "attempts" | "step" | "next_retry" | "days_past_due" | "failureReason";
|
|
10
10
|
export type InvoicingDunningCaseSortKey = ReturnType<typeof toInvoicingDunningCaseSortKey>;
|
|
11
11
|
/**
|
|
12
12
|
* Structural column descriptor owned by CES so the dunning-list column set,
|
package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.ALL_INVOICING_DUNNING_CASE_SORT_KEYS = [
|
|
|
6
6
|
'customer',
|
|
7
7
|
'invoice',
|
|
8
8
|
'attempts',
|
|
9
|
+
'step',
|
|
9
10
|
'next_retry',
|
|
10
11
|
'days_past_due',
|
|
11
12
|
'failureReason',
|
|
@@ -18,6 +19,8 @@ exports.INVOICING_DUNNING_CASE_COLUMNS = [
|
|
|
18
19
|
{ key: 'customer', sortable: true },
|
|
19
20
|
{ key: 'invoice', sortable: true },
|
|
20
21
|
{ key: 'attempts', sortable: true },
|
|
22
|
+
// The list API does not sort on `schedule_step`.
|
|
23
|
+
{ key: 'step', sortable: false },
|
|
21
24
|
{ key: 'next_retry', sortable: true },
|
|
22
25
|
{ key: 'days_past_due', sortable: true },
|
|
23
26
|
{ key: 'failureReason', sortable: false },
|
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.80",
|
|
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",
|