@zeniai/client-epic-state 5.1.69 → 5.1.70-betaRD1
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/jeSchedules/jeSchedulesPayload.d.ts +2 -0
- package/lib/entity/jeSchedules/jeSchedulesPayload.js +2 -0
- package/lib/entity/jeSchedules/jeSchedulesSelector.d.ts +4 -0
- package/lib/entity/jeSchedules/jeSchedulesSelector.js +11 -1
- package/lib/entity/jeSchedules/jeSchedulesState.d.ts +2 -0
- package/lib/entity/transaction/payloadTypes/scheduleTransactionPayload.d.ts +2 -0
- package/lib/entity/transaction/payloadTypes/scheduleTransactionPayload.js +2 -0
- package/lib/entity/transaction/stateTypes/scheduleTransaction.d.ts +2 -0
- package/lib/epic.d.ts +5 -1
- package/lib/epic.js +5 -1
- package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +2 -0
- package/lib/esm/entity/jeSchedules/jeSchedulesSelector.js +11 -1
- package/lib/esm/entity/transaction/payloadTypes/scheduleTransactionPayload.js +2 -0
- package/lib/esm/epic.js +5 -1
- package/lib/esm/index.js +14 -11
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +15 -2
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.js +21 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.js +110 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.js +73 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +22 -0
- package/lib/esm/view/expenseAutomationView/helpers/newScheduleLocalDataHelper.js +140 -0
- package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +126 -6
- package/lib/esm/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.js +1 -0
- package/lib/esm/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.js +70 -0
- package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +78 -11
- package/lib/esm/view/expenseAutomationView/types/jeSchedulesViewState.js +3 -6
- package/lib/esm/view/invoicing/couponView/couponViewEpics.js +0 -3
- package/lib/esm/view/invoicing/couponView/couponViewReducer.js +7 -1
- package/lib/esm/view/invoicing/couponView/couponViewSelector.js +27 -14
- package/lib/esm/view/invoicing/invoiceList/fetchInvoiceListEpic.js +7 -5
- package/lib/esm/view/invoicing/invoiceList/fetchInvoiceListPageEpic.js +2 -1
- package/lib/esm/view/invoicing/invoiceList/invoiceListReducer.js +62 -36
- package/lib/esm/view/invoicing/invoiceList/invoiceListSelector.js +19 -15
- package/lib/esm/view/invoicing/invoiceList/invoiceListState.js +10 -0
- package/lib/esm/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListEpic.js +0 -3
- package/lib/esm/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewReducer.js +7 -1
- package/lib/esm/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewSelector.js +23 -13
- package/lib/esm/view/invoicing/invoicingCustomerDetailView/fetchInvoicingCustomerDetailPageEpic.js +3 -2
- package/lib/esm/view/invoicing/invoicingCustomerDetailView/invoicingCustomerDetailViewSelector.js +1 -1
- package/lib/esm/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListEpic.js +0 -3
- package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.js +7 -1
- package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewSelector.js +25 -12
- package/lib/esm/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListEpic.js +0 -3
- package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.js +7 -1
- package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js +23 -13
- package/lib/esm/view/invoicing/invoicingSubscriptionListView/epics/fetchInvoicingSubscriptionListEpic.js +0 -3
- package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.js +7 -1
- package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.js +22 -12
- package/lib/esm/view/invoicing/invoicingTransactionListView/epics/fetchInvoicingTransactionListEpic.js +7 -5
- package/lib/esm/view/invoicing/invoicingTransactionListView/epics/fetchInvoicingTransactionListPageEpic.js +2 -1
- package/lib/esm/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewReducer.js +56 -25
- package/lib/esm/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewSelector.js +15 -11
- package/lib/esm/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewState.js +10 -0
- package/lib/index.d.ts +16 -13
- package/lib/index.js +73 -48
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +14 -1
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.d.ts +8 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/initializeNewScheduleEpic.js +25 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.d.ts +45 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/saveNewScheduleEpic.js +114 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.d.ts +8 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/newSchedule/searchTransactionsForNewScheduleEpic.js +77 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.d.ts +6 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/switchJESchedulesTabEpic.js +26 -0
- package/lib/view/expenseAutomationView/helpers/newScheduleLocalDataHelper.d.ts +36 -0
- package/lib/view/expenseAutomationView/helpers/newScheduleLocalDataHelper.js +145 -0
- package/lib/view/expenseAutomationView/payload/jeSchedulesPayload.d.ts +1 -0
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +38 -8
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +128 -7
- package/lib/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.d.ts +25 -0
- package/lib/view/expenseAutomationView/selectorTypes/jeNewScheduleViewSelectorTypes.js +2 -0
- package/lib/view/expenseAutomationView/selectorTypes/jeSchedulesSelectorTypes.d.ts +29 -4
- package/lib/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.d.ts +10 -0
- package/lib/view/expenseAutomationView/selectors/jeNewScheduleViewSelector.js +75 -0
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.d.ts +1 -0
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +80 -11
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +52 -6
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.js +5 -8
- package/lib/view/invoicing/couponView/couponViewEpics.js +0 -3
- package/lib/view/invoicing/couponView/couponViewReducer.d.ts +1 -1
- package/lib/view/invoicing/couponView/couponViewReducer.js +8 -2
- package/lib/view/invoicing/couponView/couponViewSelector.d.ts +1 -0
- package/lib/view/invoicing/couponView/couponViewSelector.js +27 -14
- package/lib/view/invoicing/couponView/couponViewState.d.ts +2 -1
- package/lib/view/invoicing/invoiceList/fetchInvoiceListEpic.d.ts +1 -1
- package/lib/view/invoicing/invoiceList/fetchInvoiceListEpic.js +7 -5
- package/lib/view/invoicing/invoiceList/fetchInvoiceListPageEpic.js +2 -1
- package/lib/view/invoicing/invoiceList/invoiceListReducer.d.ts +5 -4
- package/lib/view/invoicing/invoiceList/invoiceListReducer.js +63 -37
- package/lib/view/invoicing/invoiceList/invoiceListSelector.d.ts +1 -0
- package/lib/view/invoicing/invoiceList/invoiceListSelector.js +19 -15
- package/lib/view/invoicing/invoiceList/invoiceListState.d.ts +20 -7
- package/lib/view/invoicing/invoiceList/invoiceListState.js +13 -1
- package/lib/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListEpic.js +0 -3
- package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewReducer.js +8 -2
- package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewSelector.d.ts +1 -0
- package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewSelector.js +23 -13
- package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewState.d.ts +2 -1
- package/lib/view/invoicing/invoicingCustomerDetailView/fetchInvoicingCustomerDetailPageEpic.js +3 -2
- package/lib/view/invoicing/invoicingCustomerDetailView/invoicingCustomerDetailViewSelector.js +1 -1
- package/lib/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListEpic.js +0 -3
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.js +8 -2
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewSelector.d.ts +1 -0
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewSelector.js +25 -12
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.d.ts +2 -1
- package/lib/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListEpic.js +0 -3
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.js +8 -2
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.d.ts +1 -0
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js +23 -13
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.d.ts +2 -1
- package/lib/view/invoicing/invoicingSubscriptionListView/epics/fetchInvoicingSubscriptionListEpic.js +0 -3
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.js +8 -2
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.d.ts +1 -0
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.js +22 -12
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewState.d.ts +3 -1
- package/lib/view/invoicing/invoicingTransactionListView/epics/fetchInvoicingTransactionListEpic.d.ts +1 -1
- package/lib/view/invoicing/invoicingTransactionListView/epics/fetchInvoicingTransactionListEpic.js +7 -5
- package/lib/view/invoicing/invoicingTransactionListView/epics/fetchInvoicingTransactionListPageEpic.js +2 -1
- package/lib/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewReducer.js +57 -26
- package/lib/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewSelector.d.ts +1 -0
- package/lib/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewSelector.js +15 -11
- package/lib/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewState.d.ts +18 -4
- package/lib/view/invoicing/invoicingTransactionListView/invoicingTransactionListViewState.js +13 -1
- package/package.json +1 -1
|
@@ -6,10 +6,10 @@ import { updateInvoices } from '../../../entity/invoicing/invoice/invoiceReducer
|
|
|
6
6
|
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
7
7
|
import { INVOICING_LIST_PAGE_SIZE, applyListSortParams, withQuery, } from '../invoicingApiHelper';
|
|
8
8
|
import { fetchInvoiceList, updateInvoiceList, updateInvoiceListFailure, } from './invoiceListReducer';
|
|
9
|
-
const buildInvoiceListQuery = (filters, cursor, sort) => {
|
|
9
|
+
const buildInvoiceListQuery = (filters, status, cursor, sort) => {
|
|
10
10
|
const params = new URLSearchParams();
|
|
11
|
-
if (
|
|
12
|
-
params.set('status',
|
|
11
|
+
if (status != null && status.length > 0) {
|
|
12
|
+
params.set('status', status);
|
|
13
13
|
}
|
|
14
14
|
if (filters.customerId != null) {
|
|
15
15
|
params.set('customer_id', filters.customerId);
|
|
@@ -33,9 +33,11 @@ const buildInvoiceListQuery = (filters, cursor, sort) => {
|
|
|
33
33
|
applyListSortParams(params, sort);
|
|
34
34
|
return params;
|
|
35
35
|
};
|
|
36
|
-
export const fetchInvoiceListEpic = (actions$,
|
|
36
|
+
export const fetchInvoiceListEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchInvoiceList.match), switchMap((action) => {
|
|
37
37
|
const { filters, cursor, keepExistingListItems, sort } = action.payload;
|
|
38
|
-
const
|
|
38
|
+
const { activeTab } = state$.value.invoicingInvoiceListState;
|
|
39
|
+
const status = activeTab !== 'all' ? activeTab : undefined;
|
|
40
|
+
const apiUrl = withQuery(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/invoices`, buildInvoiceListQuery(filters, status, cursor, sort));
|
|
39
41
|
return zeniAPI.getJSON(apiUrl).pipe(switchMap((response) => {
|
|
40
42
|
if (isSuccessResponse(response)) {
|
|
41
43
|
const items = response.data?.items ?? [];
|
|
@@ -16,8 +16,9 @@ const shouldFetch = (fetchStateAndError, cacheOverride) => cacheOverride ||
|
|
|
16
16
|
export const fetchInvoiceListPageEpic = (actions$, state$) => actions$.pipe(filter(fetchInvoiceListPage.match), mergeMap((action) => {
|
|
17
17
|
const { cacheOverride, filters, sort } = action.payload;
|
|
18
18
|
const state = state$.value.invoicingInvoiceListState;
|
|
19
|
+
const activeTabState = state.invoiceByTab[state.activeTab];
|
|
19
20
|
const pageActions = [];
|
|
20
|
-
if (shouldFetch({ fetchState:
|
|
21
|
+
if (shouldFetch({ fetchState: activeTabState.fetchState, error: activeTabState.error }, cacheOverride)) {
|
|
21
22
|
pageActions.push(fetchInvoiceList({ filters, sort }));
|
|
22
23
|
}
|
|
23
24
|
if (shouldFetch(state.countsFetchState, cacheOverride)) {
|
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
+
import { ALL_INVOICING_INVOICE_TAB_IDS, makeInvoiceByTab, } from './invoiceListState';
|
|
2
3
|
/**
|
|
3
|
-
* Whether two invoice-list queries
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Whether two invoice-list queries share the same base (tab-independent) query.
|
|
5
|
+
* The status tab is server-side per-tab, so it is excluded here — when the base
|
|
6
|
+
* query changes (search / customer / subscription / dates / sort) every per-tab
|
|
7
|
+
* cache is stale and the reducer resets them all.
|
|
6
8
|
*/
|
|
7
9
|
export const sameInvoiceListQuery = (a, b) => a.filters.customerId === b.filters.customerId &&
|
|
8
10
|
a.filters.subscriptionId === b.filters.subscriptionId &&
|
|
9
|
-
a.filters.status === b.filters.status &&
|
|
10
11
|
a.filters.search === b.filters.search &&
|
|
11
12
|
a.filters.dateFrom === b.filters.dateFrom &&
|
|
12
13
|
a.filters.dateTo === b.filters.dateTo &&
|
|
13
14
|
a.sort?.field === b.sort?.field &&
|
|
14
15
|
a.sort?.dir === b.sort?.dir;
|
|
16
|
+
/**
|
|
17
|
+
* Narrow an invoice status to a status tab id when one exists. Statuses like
|
|
18
|
+
* `draft` / `posted` / `pending` have no dedicated tab, so a newly created
|
|
19
|
+
* invoice in one of those states only lands in the `all` tab.
|
|
20
|
+
*/
|
|
21
|
+
const statusToTabId = (status) => ALL_INVOICING_INVOICE_TAB_IDS.includes(status)
|
|
22
|
+
? status
|
|
23
|
+
: undefined;
|
|
15
24
|
export const initialState = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
invoiceIds: [],
|
|
19
|
-
nextCursor: null,
|
|
25
|
+
activeTab: 'all',
|
|
26
|
+
invoiceByTab: makeInvoiceByTab(),
|
|
20
27
|
filters: {},
|
|
21
28
|
counts: { all: 0 },
|
|
22
29
|
countsFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
23
30
|
kpis: undefined,
|
|
24
31
|
kpisFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
25
|
-
hasValidState() {
|
|
26
|
-
return this.fetchState === 'Completed';
|
|
27
|
-
},
|
|
28
32
|
};
|
|
29
33
|
const invoiceList = createSlice({
|
|
30
34
|
name: 'invoicingInvoiceList',
|
|
@@ -32,14 +36,15 @@ const invoiceList = createSlice({
|
|
|
32
36
|
reducers: {
|
|
33
37
|
fetchInvoiceList: {
|
|
34
38
|
reducer(draft, action) {
|
|
39
|
+
const tab = draft.invoiceByTab[draft.activeTab];
|
|
35
40
|
if (!action.payload.keepExistingListItems) {
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
tab.invoiceIds = [];
|
|
42
|
+
tab.nextCursor = null;
|
|
38
43
|
}
|
|
39
44
|
draft.filters = action.payload.filters;
|
|
40
45
|
draft.sort = action.payload.sort;
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
tab.fetchState = 'In-Progress';
|
|
47
|
+
tab.error = undefined;
|
|
43
48
|
},
|
|
44
49
|
prepare(payload) {
|
|
45
50
|
return {
|
|
@@ -54,13 +59,11 @@ const invoiceList = createSlice({
|
|
|
54
59
|
},
|
|
55
60
|
fetchInvoiceListPage: {
|
|
56
61
|
reducer(draft, action) {
|
|
57
|
-
// A different query invalidates
|
|
58
|
-
// epic's shouldFetch refetches instead of showing
|
|
59
|
-
//
|
|
62
|
+
// A different base query invalidates every tab's cache — reset so the
|
|
63
|
+
// page epic's shouldFetch refetches the active tab instead of showing
|
|
64
|
+
// rows fetched under a stale search/customer/subscription/dates/sort.
|
|
60
65
|
if (!sameInvoiceListQuery(draft, action.payload)) {
|
|
61
|
-
draft.
|
|
62
|
-
draft.nextCursor = null;
|
|
63
|
-
draft.fetchState = 'Not-Started';
|
|
66
|
+
draft.invoiceByTab = makeInvoiceByTab();
|
|
64
67
|
}
|
|
65
68
|
draft.filters = action.payload.filters;
|
|
66
69
|
draft.sort = action.payload.sort;
|
|
@@ -76,17 +79,19 @@ const invoiceList = createSlice({
|
|
|
76
79
|
},
|
|
77
80
|
},
|
|
78
81
|
updateInvoiceList(draft, action) {
|
|
82
|
+
const tab = draft.invoiceByTab[draft.activeTab];
|
|
79
83
|
const newIds = action.payload.invoices.map((invoice) => invoice.id);
|
|
80
|
-
|
|
81
|
-
? [...new Set([...
|
|
84
|
+
tab.invoiceIds = action.payload.keepExistingListItems
|
|
85
|
+
? [...new Set([...tab.invoiceIds, ...newIds])]
|
|
82
86
|
: newIds;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
tab.nextCursor = action.payload.nextCursor;
|
|
88
|
+
tab.fetchState = 'Completed';
|
|
89
|
+
tab.error = undefined;
|
|
86
90
|
},
|
|
87
91
|
updateInvoiceListFailure(draft, action) {
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
const tab = draft.invoiceByTab[draft.activeTab];
|
|
93
|
+
tab.fetchState = 'Error';
|
|
94
|
+
tab.error = action.payload;
|
|
90
95
|
},
|
|
91
96
|
fetchInvoiceCounts(draft) {
|
|
92
97
|
draft.countsFetchState.fetchState = 'In-Progress';
|
|
@@ -117,24 +122,45 @@ const invoiceList = createSlice({
|
|
|
117
122
|
updateInvoiceListFilters(draft, action) {
|
|
118
123
|
draft.filters = action.payload;
|
|
119
124
|
},
|
|
125
|
+
// Select a status tab. The view dispatches the follow-up fetchInvoiceListPage
|
|
126
|
+
// so the page epic fetches the tab when its cache is empty and reuses it when
|
|
127
|
+
// already loaded.
|
|
128
|
+
setInvoiceActiveTab(draft, action) {
|
|
129
|
+
draft.activeTab = action.payload;
|
|
130
|
+
},
|
|
120
131
|
// Reflect a newly created invoice in the cached list + tab counts so the
|
|
121
|
-
// invoices page shows it without refetching
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
132
|
+
// invoices page shows it without refetching. Prepends the id to the `all`
|
|
133
|
+
// tab and its status tab (dedup via includes), and bumps the `all` total and
|
|
134
|
+
// the per-status count key the tabs read. KPIs are money aggregates, so they
|
|
135
|
+
// are left untouched and refetched lazily.
|
|
125
136
|
addInvoiceToList(draft, action) {
|
|
126
137
|
const { id, status } = action.payload;
|
|
127
|
-
|
|
138
|
+
const allTab = draft.invoiceByTab['all'];
|
|
139
|
+
if (allTab.invoiceIds.includes(id)) {
|
|
128
140
|
return;
|
|
129
141
|
}
|
|
130
|
-
|
|
142
|
+
allTab.invoiceIds = [id, ...allTab.invoiceIds];
|
|
143
|
+
const statusTab = statusToTabId(status);
|
|
144
|
+
if (statusTab != null) {
|
|
145
|
+
const tab = draft.invoiceByTab[statusTab];
|
|
146
|
+
if (!tab.invoiceIds.includes(id)) {
|
|
147
|
+
tab.invoiceIds = [id, ...tab.invoiceIds];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
131
150
|
draft.counts.all += 1;
|
|
132
151
|
draft.counts[status] = (draft.counts[status] ?? 0) + 1;
|
|
133
152
|
},
|
|
134
153
|
clearInvoiceList(draft) {
|
|
135
|
-
|
|
154
|
+
draft.activeTab = 'all';
|
|
155
|
+
draft.invoiceByTab = makeInvoiceByTab();
|
|
156
|
+
draft.filters = {};
|
|
157
|
+
draft.sort = undefined;
|
|
158
|
+
draft.counts = { all: 0 };
|
|
159
|
+
draft.countsFetchState = { fetchState: 'Not-Started', error: undefined };
|
|
160
|
+
draft.kpis = undefined;
|
|
161
|
+
draft.kpisFetchState = { fetchState: 'Not-Started', error: undefined };
|
|
136
162
|
},
|
|
137
163
|
},
|
|
138
164
|
});
|
|
139
|
-
export const { fetchInvoiceList, fetchInvoiceListPage, updateInvoiceList, updateInvoiceListFailure, fetchInvoiceCounts, updateInvoiceCounts, updateInvoiceCountsFailure, fetchInvoiceKPIs, updateInvoiceKPIs, updateInvoiceKPIsFailure, updateInvoiceListFilters, addInvoiceToList, clearInvoiceList, } = invoiceList.actions;
|
|
165
|
+
export const { fetchInvoiceList, fetchInvoiceListPage, updateInvoiceList, updateInvoiceListFailure, fetchInvoiceCounts, updateInvoiceCounts, updateInvoiceCountsFailure, fetchInvoiceKPIs, updateInvoiceKPIs, updateInvoiceKPIsFailure, updateInvoiceListFilters, setInvoiceActiveTab, addInvoiceToList, clearInvoiceList, } = invoiceList.actions;
|
|
140
166
|
export default invoiceList.reducer;
|
|
@@ -6,18 +6,22 @@ import { INVOICING_INVOICE_TABS, } from './invoiceListState';
|
|
|
6
6
|
* array (and the wrapping view object) keep referential identity until the
|
|
7
7
|
* invoice entity slice or the list-view slice actually change.
|
|
8
8
|
*/
|
|
9
|
-
export const getInvoiceListView = createSelector((state) => state.invoicingInvoiceState, (state) => state.invoicingInvoiceListState, (invoiceState, listViewState) =>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
export const getInvoiceListView = createSelector((state) => state.invoicingInvoiceState, (state) => state.invoicingInvoiceListState, (invoiceState, listViewState) => {
|
|
10
|
+
const activeTabState = listViewState.invoiceByTab[listViewState.activeTab];
|
|
11
|
+
return {
|
|
12
|
+
activeTab: listViewState.activeTab,
|
|
13
|
+
invoices: activeTabState.invoiceIds
|
|
14
|
+
.map((id) => invoiceState.invoiceByID[id])
|
|
15
|
+
.filter((item) => item != null),
|
|
16
|
+
counts: listViewState.counts,
|
|
17
|
+
countsFetchState: listViewState.countsFetchState,
|
|
18
|
+
filters: listViewState.filters,
|
|
19
|
+
kpis: listViewState.kpis,
|
|
20
|
+
kpisFetchState: listViewState.kpisFetchState,
|
|
21
|
+
nextCursor: activeTabState.nextCursor,
|
|
22
|
+
tabIds: INVOICING_INVOICE_TABS,
|
|
23
|
+
fetchState: activeTabState.fetchState,
|
|
24
|
+
error: activeTabState.error,
|
|
25
|
+
version: 1.0,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
@@ -17,3 +17,13 @@ export const toInvoicingInvoiceTabId = (v) => stringToUnion(v, ALL_INVOICING_INV
|
|
|
17
17
|
export const INVOICING_INVOICE_TABS = [
|
|
18
18
|
...ALL_INVOICING_INVOICE_TAB_IDS,
|
|
19
19
|
];
|
|
20
|
+
export const makeInvoiceTabState = () => ({
|
|
21
|
+
invoiceIds: [],
|
|
22
|
+
nextCursor: null,
|
|
23
|
+
fetchState: 'Not-Started',
|
|
24
|
+
error: undefined,
|
|
25
|
+
});
|
|
26
|
+
export const makeInvoiceByTab = () => ALL_INVOICING_INVOICE_TAB_IDS.reduce((acc, tabId) => {
|
|
27
|
+
acc[tabId] = makeInvoiceTabState();
|
|
28
|
+
return acc;
|
|
29
|
+
}, {});
|
package/lib/esm/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListEpic.js
CHANGED
|
@@ -6,9 +6,6 @@ import { INVOICING_LIST_PAGE_SIZE, applyListSortParams, withQuery, } from '../..
|
|
|
6
6
|
import { fetchInvoicingCreditNoteList, updateInvoicingCreditNoteList, updateInvoicingCreditNoteListFailure, } from '../invoicingCreditNoteListViewReducer';
|
|
7
7
|
const buildQuery = (filters, cursor, sort) => {
|
|
8
8
|
const params = new URLSearchParams();
|
|
9
|
-
if (filters.status != null && filters.status.length > 0) {
|
|
10
|
-
params.set('status', filters.status);
|
|
11
|
-
}
|
|
12
9
|
if (filters.customerId != null) {
|
|
13
10
|
params.set('customer_id', filters.customerId);
|
|
14
11
|
}
|
package/lib/esm/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewReducer.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
|
|
2
2
|
export const initialState = {
|
|
3
3
|
fetchState: 'Not-Started',
|
|
4
4
|
error: undefined,
|
|
5
|
+
activeTab: 'all',
|
|
5
6
|
ids: [],
|
|
6
7
|
nextCursor: null,
|
|
7
8
|
filters: {},
|
|
@@ -80,10 +81,15 @@ const invoicingCreditNoteListView = createSlice({
|
|
|
80
81
|
updateInvoicingCreditNoteFilters(draft, action) {
|
|
81
82
|
draft.filters = action.payload;
|
|
82
83
|
},
|
|
84
|
+
// Select a status tab. The list API ignores `status` (returns all statuses),
|
|
85
|
+
// so the selector filters rows to this tab client-side — no refetch needed.
|
|
86
|
+
setInvoicingCreditNoteActiveTab(draft, action) {
|
|
87
|
+
draft.activeTab = action.payload;
|
|
88
|
+
},
|
|
83
89
|
clearInvoicingCreditNoteListView(draft) {
|
|
84
90
|
Object.assign(draft, initialState);
|
|
85
91
|
},
|
|
86
92
|
},
|
|
87
93
|
});
|
|
88
|
-
export const { fetchInvoicingCreditNoteList, fetchInvoicingCreditNoteListPage, updateInvoicingCreditNoteList, updateInvoicingCreditNoteListFailure, fetchInvoicingCreditNoteCounts, updateInvoicingCreditNoteCounts, updateInvoicingCreditNoteCountsFailure, updateInvoicingCreditNoteFilters, clearInvoicingCreditNoteListView, } = invoicingCreditNoteListView.actions;
|
|
94
|
+
export const { fetchInvoicingCreditNoteList, fetchInvoicingCreditNoteListPage, updateInvoicingCreditNoteList, updateInvoicingCreditNoteListFailure, fetchInvoicingCreditNoteCounts, updateInvoicingCreditNoteCounts, updateInvoicingCreditNoteCountsFailure, updateInvoicingCreditNoteFilters, setInvoicingCreditNoteActiveTab, clearInvoicingCreditNoteListView, } = invoicingCreditNoteListView.actions;
|
|
89
95
|
export default invoicingCreditNoteListView.reducer;
|
package/lib/esm/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewSelector.js
CHANGED
|
@@ -6,16 +6,26 @@ import { INVOICING_CREDIT_NOTE_COLUMNS, INVOICING_CREDIT_NOTE_TABS, } from './in
|
|
|
6
6
|
* object) keep referential identity until the credit-note entity slice or the
|
|
7
7
|
* list-view slice actually change.
|
|
8
8
|
*/
|
|
9
|
-
export const getInvoicingCreditNoteListView = createSelector((state) => state.invoicingCreditNoteState, (state) => state.invoicingCreditNoteListViewState, (creditNoteState, listViewState) =>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
export const getInvoicingCreditNoteListView = createSelector((state) => state.invoicingCreditNoteState, (state) => state.invoicingCreditNoteListViewState, (creditNoteState, listViewState) => {
|
|
10
|
+
const { activeTab } = listViewState;
|
|
11
|
+
const allCreditNotes = getInvoicingCreditNotesByIds(creditNoteState, listViewState.ids);
|
|
12
|
+
// The list API ignores `status`, so it returns every status; filter to the
|
|
13
|
+
// active tab client-side ('all' shows everything).
|
|
14
|
+
const creditNotes = activeTab === 'all'
|
|
15
|
+
? allCreditNotes
|
|
16
|
+
: allCreditNotes.filter((creditNote) => creditNote.status === activeTab);
|
|
17
|
+
return {
|
|
18
|
+
activeTab,
|
|
19
|
+
columns: INVOICING_CREDIT_NOTE_COLUMNS,
|
|
20
|
+
creditNotes,
|
|
21
|
+
count: listViewState.counts,
|
|
22
|
+
countsFetchState: listViewState.countsFetchState,
|
|
23
|
+
filters: listViewState.filters,
|
|
24
|
+
nextCursor: listViewState.nextCursor,
|
|
25
|
+
tabIds: INVOICING_CREDIT_NOTE_TABS,
|
|
26
|
+
fetchState: listViewState.fetchState,
|
|
27
|
+
error: listViewState.error,
|
|
28
|
+
sort: listViewState.sort,
|
|
29
|
+
version: 1.0,
|
|
30
|
+
};
|
|
31
|
+
});
|
package/lib/esm/view/invoicing/invoicingCustomerDetailView/fetchInvoicingCustomerDetailPageEpic.js
CHANGED
|
@@ -20,6 +20,7 @@ export const fetchInvoicingCustomerDetailPageEpic = (actions$, state$) => action
|
|
|
20
20
|
const { cacheOverride, id } = action.payload;
|
|
21
21
|
const customerDetail = state$.value.invoicingCustomerDetailViewState.detailById[id];
|
|
22
22
|
const invoiceListState = state$.value.invoicingInvoiceListState;
|
|
23
|
+
const invoiceListTabState = invoiceListState.invoiceByTab[invoiceListState.activeTab];
|
|
23
24
|
const settingsState = state$.value.invoicingSettingsViewState;
|
|
24
25
|
const pageActions = [];
|
|
25
26
|
if (shouldFetch({
|
|
@@ -33,8 +34,8 @@ export const fetchInvoicingCustomerDetailPageEpic = (actions$, state$) => action
|
|
|
33
34
|
const invoiceListIsForCustomer = invoiceListState.filters.customerId === id;
|
|
34
35
|
if (!invoiceListIsForCustomer ||
|
|
35
36
|
shouldFetch({
|
|
36
|
-
fetchState:
|
|
37
|
-
error:
|
|
37
|
+
fetchState: invoiceListTabState.fetchState,
|
|
38
|
+
error: invoiceListTabState.error,
|
|
38
39
|
}, cacheOverride)) {
|
|
39
40
|
pageActions.push(fetchInvoiceList({ filters: { customerId: id } }));
|
|
40
41
|
}
|
package/lib/esm/view/invoicing/invoicingCustomerDetailView/invoicingCustomerDetailViewSelector.js
CHANGED
|
@@ -10,7 +10,7 @@ export const getInvoicingCustomerDetail = (state, invoicingCustomerID) => {
|
|
|
10
10
|
const settings = getInvoicingSettings(state);
|
|
11
11
|
return {
|
|
12
12
|
invoicingCustomer: getInvoicingCustomerById(invoicingCustomerState, invoicingCustomerID),
|
|
13
|
-
invoices: getInvoicesByIds(state.invoicingInvoiceState, state.invoicingInvoiceListState.invoiceIds),
|
|
13
|
+
invoices: getInvoicesByIds(state.invoicingInvoiceState, state.invoicingInvoiceListState.invoiceByTab[state.invoicingInvoiceListState.activeTab].invoiceIds),
|
|
14
14
|
setupIntent: getInvoicingSetupIntent(state),
|
|
15
15
|
setupIntentFetchState: getInvoicingSetupIntentFetchState(state),
|
|
16
16
|
plaidLinkToken: getInvoicingPlaidLinkToken(state),
|
package/lib/esm/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListEpic.js
CHANGED
|
@@ -11,9 +11,6 @@ const buildQuery = (filters, cursor, sort) => {
|
|
|
11
11
|
if (filters.search != null && filters.search.length > 0) {
|
|
12
12
|
params.set('search', filters.search);
|
|
13
13
|
}
|
|
14
|
-
if (filters.status != null && filters.status.length > 0) {
|
|
15
|
-
params.set('status', filters.status);
|
|
16
|
-
}
|
|
17
14
|
params.set('limit', String(INVOICING_LIST_PAGE_SIZE));
|
|
18
15
|
if (cursor != null) {
|
|
19
16
|
params.set('cursor', cursor);
|
package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
|
|
2
2
|
export const initialState = {
|
|
3
3
|
fetchState: 'Not-Started',
|
|
4
4
|
error: undefined,
|
|
5
|
+
activeTab: 'all',
|
|
5
6
|
ids: [],
|
|
6
7
|
nextCursor: null,
|
|
7
8
|
filters: {},
|
|
@@ -80,6 +81,11 @@ const invoicingCustomerListView = createSlice({
|
|
|
80
81
|
updateInvoicingCustomerFilters(draft, action) {
|
|
81
82
|
draft.filters = action.payload;
|
|
82
83
|
},
|
|
84
|
+
// Select a status tab. The list API ignores `status` (returns all statuses),
|
|
85
|
+
// so the selector filters rows to this tab client-side — no refetch needed.
|
|
86
|
+
setInvoicingCustomerActiveTab(draft, action) {
|
|
87
|
+
draft.activeTab = action.payload;
|
|
88
|
+
},
|
|
83
89
|
// Reflect a newly created customer in the cached list + tab counts so the
|
|
84
90
|
// customer page shows the new row without refetching from the server. The
|
|
85
91
|
// per-status count key mirrors the customer `status` value the counts map
|
|
@@ -101,5 +107,5 @@ const invoicingCustomerListView = createSlice({
|
|
|
101
107
|
},
|
|
102
108
|
},
|
|
103
109
|
});
|
|
104
|
-
export const { fetchInvoicingCustomerList, fetchInvoicingCustomerListPage, updateInvoicingCustomerList, updateInvoicingCustomerListFailure, fetchInvoicingCustomerCounts, updateInvoicingCustomerCounts, updateInvoicingCustomerCountsFailure, updateInvoicingCustomerFilters, addInvoicingCustomerToList, clearInvoicingCustomerListView, } = invoicingCustomerListView.actions;
|
|
110
|
+
export const { fetchInvoicingCustomerList, fetchInvoicingCustomerListPage, updateInvoicingCustomerList, updateInvoicingCustomerListFailure, fetchInvoicingCustomerCounts, updateInvoicingCustomerCounts, updateInvoicingCustomerCountsFailure, updateInvoicingCustomerFilters, setInvoicingCustomerActiveTab, addInvoicingCustomerToList, clearInvoicingCustomerListView, } = invoicingCustomerListView.actions;
|
|
105
111
|
export default invoicingCustomerListView.reducer;
|
package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewSelector.js
CHANGED
|
@@ -7,15 +7,28 @@ import { INVOICING_CUSTOMER_COLUMNS, INVOICING_CUSTOMER_TABS, } from './invoicin
|
|
|
7
7
|
* slice actually change. Without this, the connected list page re-rendered on
|
|
8
8
|
* every unrelated redux action because a fresh array was built each call.
|
|
9
9
|
*/
|
|
10
|
-
export const getInvoicingCustomerListView = createSelector((state) => state.invoicingCustomerState, (state) => state.invoicingCustomerListViewState, (customerState, listViewState) =>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
10
|
+
export const getInvoicingCustomerListView = createSelector((state) => state.invoicingCustomerState, (state) => state.invoicingCustomerListViewState, (customerState, listViewState) => {
|
|
11
|
+
const { activeTab } = listViewState;
|
|
12
|
+
const allCustomers = getInvoicingCustomersByIds(customerState, listViewState.ids);
|
|
13
|
+
// The list API ignores `status`, so it returns every status; filter to the
|
|
14
|
+
// active tab client-side ('all' shows everything, 'at_risk' keys off the
|
|
15
|
+
// `isAtRisk` flag, the rest match the customer `status`).
|
|
16
|
+
const customers = activeTab === 'all'
|
|
17
|
+
? allCustomers
|
|
18
|
+
: activeTab === 'at_risk'
|
|
19
|
+
? allCustomers.filter((customer) => customer.isAtRisk === true)
|
|
20
|
+
: allCustomers.filter((customer) => customer.status === activeTab);
|
|
21
|
+
return {
|
|
22
|
+
activeTab,
|
|
23
|
+
columns: INVOICING_CUSTOMER_COLUMNS,
|
|
24
|
+
customers,
|
|
25
|
+
fetchState: listViewState.fetchState,
|
|
26
|
+
error: listViewState.error,
|
|
27
|
+
nextCursor: listViewState.nextCursor,
|
|
28
|
+
filters: listViewState.filters,
|
|
29
|
+
count: listViewState.counts,
|
|
30
|
+
countsFetchState: listViewState.countsFetchState,
|
|
31
|
+
tabIds: INVOICING_CUSTOMER_TABS,
|
|
32
|
+
sort: listViewState.sort,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
@@ -6,9 +6,6 @@ import { INVOICING_LIST_PAGE_SIZE, applyListSortParams, withQuery, } from '../..
|
|
|
6
6
|
import { fetchInvoicingDunningCaseList, updateInvoicingDunningCaseList, updateInvoicingDunningCaseListFailure, } from '../invoicingDunningCaseListViewReducer';
|
|
7
7
|
const buildQuery = (filters, cursor, sort) => {
|
|
8
8
|
const params = new URLSearchParams();
|
|
9
|
-
if (filters.status != null && filters.status.length > 0) {
|
|
10
|
-
params.set('status', filters.status);
|
|
11
|
-
}
|
|
12
9
|
if (filters.search != null && filters.search.length > 0) {
|
|
13
10
|
params.set('search', filters.search);
|
|
14
11
|
}
|
package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
|
|
2
2
|
export const initialState = {
|
|
3
3
|
fetchState: 'Not-Started',
|
|
4
4
|
error: undefined,
|
|
5
|
+
activeTab: 'all',
|
|
5
6
|
ids: [],
|
|
6
7
|
nextCursor: null,
|
|
7
8
|
filters: {},
|
|
@@ -80,10 +81,15 @@ const invoicingDunningCaseListView = createSlice({
|
|
|
80
81
|
updateInvoicingDunningCaseFilters(draft, action) {
|
|
81
82
|
draft.filters = action.payload;
|
|
82
83
|
},
|
|
84
|
+
// Select a status tab. The list API ignores `status` (returns all statuses),
|
|
85
|
+
// so the selector filters rows to this tab client-side — no refetch needed.
|
|
86
|
+
setInvoicingDunningCaseActiveTab(draft, action) {
|
|
87
|
+
draft.activeTab = action.payload;
|
|
88
|
+
},
|
|
83
89
|
clearInvoicingDunningCaseListView(draft) {
|
|
84
90
|
Object.assign(draft, initialState);
|
|
85
91
|
},
|
|
86
92
|
},
|
|
87
93
|
});
|
|
88
|
-
export const { fetchInvoicingDunningCaseList, fetchInvoicingDunningCaseListPage, updateInvoicingDunningCaseList, updateInvoicingDunningCaseListFailure, fetchInvoicingDunningCaseCounts, updateInvoicingDunningCaseCounts, updateInvoicingDunningCaseCountsFailure, updateInvoicingDunningCaseFilters, clearInvoicingDunningCaseListView, } = invoicingDunningCaseListView.actions;
|
|
94
|
+
export const { fetchInvoicingDunningCaseList, fetchInvoicingDunningCaseListPage, updateInvoicingDunningCaseList, updateInvoicingDunningCaseListFailure, fetchInvoicingDunningCaseCounts, updateInvoicingDunningCaseCounts, updateInvoicingDunningCaseCountsFailure, updateInvoicingDunningCaseFilters, setInvoicingDunningCaseActiveTab, clearInvoicingDunningCaseListView, } = invoicingDunningCaseListView.actions;
|
|
89
95
|
export default invoicingDunningCaseListView.reducer;
|
package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js
CHANGED
|
@@ -6,16 +6,26 @@ import { INVOICING_DUNNING_CASE_COLUMNS, INVOICING_DUNNING_CASE_TABS, } from './
|
|
|
6
6
|
* object) keep referential identity until the dunning-case entity slice or the
|
|
7
7
|
* list-view slice actually change.
|
|
8
8
|
*/
|
|
9
|
-
export const getInvoicingDunningCaseListView = createSelector((state) => state.invoicingDunningCaseState, (state) => state.invoicingDunningCaseListViewState, (dunningCaseState, listViewState) =>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
export const getInvoicingDunningCaseListView = createSelector((state) => state.invoicingDunningCaseState, (state) => state.invoicingDunningCaseListViewState, (dunningCaseState, listViewState) => {
|
|
10
|
+
const { activeTab } = listViewState;
|
|
11
|
+
const allDunningCases = getInvoicingDunningCasesByIds(dunningCaseState, listViewState.ids);
|
|
12
|
+
// The list API ignores `status`, so it returns every status; filter to the
|
|
13
|
+
// active tab client-side ('all' shows everything).
|
|
14
|
+
const dunningCases = activeTab === 'all'
|
|
15
|
+
? allDunningCases
|
|
16
|
+
: allDunningCases.filter((dunningCase) => dunningCase.status === activeTab);
|
|
17
|
+
return {
|
|
18
|
+
activeTab,
|
|
19
|
+
columns: INVOICING_DUNNING_CASE_COLUMNS,
|
|
20
|
+
dunningCases,
|
|
21
|
+
count: listViewState.counts,
|
|
22
|
+
countsFetchState: listViewState.countsFetchState,
|
|
23
|
+
filters: listViewState.filters,
|
|
24
|
+
nextCursor: listViewState.nextCursor,
|
|
25
|
+
fetchState: listViewState.fetchState,
|
|
26
|
+
error: listViewState.error,
|
|
27
|
+
tabIds: INVOICING_DUNNING_CASE_TABS,
|
|
28
|
+
sort: listViewState.sort,
|
|
29
|
+
version: 1.0,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
@@ -8,9 +8,6 @@ import { INVOICING_LIST_PAGE_SIZE, applyListSortParams, withQuery, } from '../..
|
|
|
8
8
|
import { fetchInvoicingSubscriptionList, updateInvoicingSubscriptionList, updateInvoicingSubscriptionListFailure, } from '../invoicingSubscriptionListViewReducer';
|
|
9
9
|
const buildQuery = (filters, cursor, sort) => {
|
|
10
10
|
const params = new URLSearchParams();
|
|
11
|
-
if (filters.status != null && filters.status.length > 0) {
|
|
12
|
-
params.set('status', filters.status);
|
|
13
|
-
}
|
|
14
11
|
if (filters.customerId != null) {
|
|
15
12
|
params.set('customer_id', filters.customerId);
|
|
16
13
|
}
|
package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
|
|
2
2
|
export const initialState = {
|
|
3
3
|
fetchState: 'Not-Started',
|
|
4
4
|
error: undefined,
|
|
5
|
+
activeTab: 'all',
|
|
5
6
|
ids: [],
|
|
6
7
|
nextCursor: null,
|
|
7
8
|
filters: {},
|
|
@@ -80,6 +81,11 @@ const invoicingSubscriptionListView = createSlice({
|
|
|
80
81
|
updateInvoicingSubscriptionFilters(draft, action) {
|
|
81
82
|
draft.filters = action.payload;
|
|
82
83
|
},
|
|
84
|
+
// Select a status tab. The list API ignores `status` (returns all statuses),
|
|
85
|
+
// so the selector filters rows to this tab client-side — no refetch needed.
|
|
86
|
+
setInvoicingSubscriptionActiveTab(draft, action) {
|
|
87
|
+
draft.activeTab = action.payload;
|
|
88
|
+
},
|
|
83
89
|
// Reflect a newly created subscription in the cached list + tab counts so the
|
|
84
90
|
// subscription page shows it without refetching from the server. The status
|
|
85
91
|
// doubles as the per-tab count key (tab ids mirror InvoicingSubscriptionStatus).
|
|
@@ -99,5 +105,5 @@ const invoicingSubscriptionListView = createSlice({
|
|
|
99
105
|
},
|
|
100
106
|
},
|
|
101
107
|
});
|
|
102
|
-
export const { fetchInvoicingSubscriptionList, fetchInvoicingSubscriptionListPage, updateInvoicingSubscriptionList, updateInvoicingSubscriptionListFailure, fetchInvoicingSubscriptionCounts, updateInvoicingSubscriptionCounts, updateInvoicingSubscriptionCountsFailure, updateInvoicingSubscriptionFilters, addInvoicingSubscriptionToList, clearInvoicingSubscriptionListView, } = invoicingSubscriptionListView.actions;
|
|
108
|
+
export const { fetchInvoicingSubscriptionList, fetchInvoicingSubscriptionListPage, updateInvoicingSubscriptionList, updateInvoicingSubscriptionListFailure, fetchInvoicingSubscriptionCounts, updateInvoicingSubscriptionCounts, updateInvoicingSubscriptionCountsFailure, updateInvoicingSubscriptionFilters, setInvoicingSubscriptionActiveTab, addInvoicingSubscriptionToList, clearInvoicingSubscriptionListView, } = invoicingSubscriptionListView.actions;
|
|
103
109
|
export default invoicingSubscriptionListView.reducer;
|
|
@@ -8,15 +8,25 @@ import { INVOICING_SUBSCRIPTION_COLUMNS, INVOICING_SUBSCRIPTION_TABS, } from './
|
|
|
8
8
|
* re-rendered on every unrelated redux action because a fresh array was built
|
|
9
9
|
* each call.
|
|
10
10
|
*/
|
|
11
|
-
export const getInvoicingSubscriptionListView = createSelector((state) => state.invoicingSubscriptionState, (state) => state.invoicingSubscriptionListViewState, (subscriptionState, listViewState) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
export const getInvoicingSubscriptionListView = createSelector((state) => state.invoicingSubscriptionState, (state) => state.invoicingSubscriptionListViewState, (subscriptionState, listViewState) => {
|
|
12
|
+
const { activeTab } = listViewState;
|
|
13
|
+
const allSubscriptions = getInvoicingSubscriptionsByIds(subscriptionState, listViewState.ids);
|
|
14
|
+
// The list API ignores `status`, so it returns every status; filter to the
|
|
15
|
+
// active tab client-side ('all' shows everything).
|
|
16
|
+
const subscriptions = activeTab === 'all'
|
|
17
|
+
? allSubscriptions
|
|
18
|
+
: allSubscriptions.filter((subscription) => subscription.status === activeTab);
|
|
19
|
+
return {
|
|
20
|
+
activeTab,
|
|
21
|
+
columns: INVOICING_SUBSCRIPTION_COLUMNS,
|
|
22
|
+
subscriptions,
|
|
23
|
+
fetchState: listViewState.fetchState,
|
|
24
|
+
error: listViewState.error,
|
|
25
|
+
nextCursor: listViewState.nextCursor,
|
|
26
|
+
filters: listViewState.filters,
|
|
27
|
+
count: listViewState.counts,
|
|
28
|
+
countsFetchState: listViewState.countsFetchState,
|
|
29
|
+
tabIds: INVOICING_SUBSCRIPTION_TABS,
|
|
30
|
+
sort: listViewState.sort,
|
|
31
|
+
};
|
|
32
|
+
});
|