@zeniai/client-epic-state 5.2.84 → 5.2.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/lib/esm/view/invoicing/createInvoice/epics/fetchCreateInvoiceFormPageEpic.js +5 -19
  2. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +4 -57
  3. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +1 -3
  4. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionDetailPageEpic.js +4 -7
  5. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionFormPageEpic.js +0 -1
  6. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.js +0 -2
  7. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +2 -6
  8. package/lib/esm/view/invoicing/invoicingCatalogListView/epics/fetchInvoicingCatalogPlanListEpic.js +3 -14
  9. package/lib/esm/view/invoicing/invoicingCatalogListView/epics/fetchInvoicingCatalogProductListEpic.js +3 -14
  10. package/lib/esm/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewReducer.js +0 -2
  11. package/lib/esm/view/invoicing/invoicingListTabCache.js +0 -8
  12. package/lib/index.d.ts +1 -1
  13. package/lib/view/invoicing/createInvoice/epics/fetchCreateInvoiceFormPageEpic.js +4 -18
  14. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.d.ts +1 -11
  15. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +4 -57
  16. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.d.ts +0 -2
  17. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +0 -2
  18. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState.d.ts +0 -13
  19. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionDetailPageEpic.js +3 -6
  20. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionFormPageEpic.js +0 -1
  21. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.d.ts +0 -2
  22. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.js +1 -4
  23. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +1 -5
  24. package/lib/view/invoicing/invoicingCatalogListView/epics/fetchInvoicingCatalogPlanListEpic.js +3 -14
  25. package/lib/view/invoicing/invoicingCatalogListView/epics/fetchInvoicingCatalogProductListEpic.js +3 -14
  26. package/lib/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewReducer.d.ts +0 -6
  27. package/lib/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewReducer.js +0 -2
  28. package/lib/view/invoicing/invoicingListTabCache.d.ts +1 -11
  29. package/lib/view/invoicing/invoicingListTabCache.js +1 -10
  30. package/package.json +1 -1
@@ -2,7 +2,7 @@ import { from } from 'rxjs';
2
2
  import { filter, mergeMap } from 'rxjs/operators';
3
3
  import { fetchInvoicingCatalogPlanList, fetchInvoicingCatalogProductList, } from '../../invoicingCatalogListView/invoicingCatalogListViewReducer';
4
4
  import { fetchInvoicingCustomerList } from '../../invoicingCustomerListView/invoicingCustomerListViewReducer';
5
- import { INVOICING_LIST_ALL_TAB, getInvoicingListTab, shouldFetchFullInvoicingList, } from '../../invoicingListTabCache';
5
+ import { INVOICING_LIST_ALL_TAB, getInvoicingListTab, } from '../../invoicingListTabCache';
6
6
  import { fetchInvoicingSettings } from '../../settingsView/settingsViewReducer';
7
7
  import { fetchCreateInvoiceFormPage } from '../createInvoiceReducer';
8
8
  /**
@@ -13,8 +13,6 @@ import { fetchCreateInvoiceFormPage } from '../createInvoiceReducer';
13
13
  const shouldFetch = (fetchStateAndError, cacheOverride) => cacheOverride ||
14
14
  (fetchStateAndError.fetchState !== 'Completed' &&
15
15
  fetchStateAndError.fetchState !== 'In-Progress');
16
- const PICKER_PLAN_FILTERS = { type: 'plan' };
17
- const PICKER_PRODUCT_FILTERS = { type: 'addon|charge' };
18
16
  /**
19
17
  * Orchestrates the create-invoice form's option sources: on
20
18
  * `fetchCreateInvoiceFormPage`, fans out to the customer, catalog plan, catalog
@@ -36,27 +34,15 @@ export const fetchCreateInvoiceFormPageEpic = (actions$, state$) => actions$.pip
36
34
  tabId: INVOICING_LIST_ALL_TAB,
37
35
  }));
38
36
  }
39
- if (shouldFetchFullInvoicingList({
40
- fetchState: catalogState.fetchState,
41
- filters: catalogState.planFilters,
42
- nextCursor: catalogState.planNextCursor,
43
- sort: catalogState.planSort,
44
- }, PICKER_PLAN_FILTERS, cacheOverride)) {
37
+ if (shouldFetch({ fetchState: catalogState.fetchState, error: catalogState.error }, cacheOverride)) {
45
38
  pageActions.push(fetchInvoicingCatalogPlanList({
46
- fetchAll: true,
47
- filters: PICKER_PLAN_FILTERS,
39
+ filters: { type: 'plan' },
48
40
  keepExistingListItems: false,
49
41
  }));
50
42
  }
51
- if (shouldFetchFullInvoicingList({
52
- fetchState: catalogState.productFetchState.fetchState,
53
- filters: catalogState.productFilters,
54
- nextCursor: catalogState.productNextCursor,
55
- sort: catalogState.productSort,
56
- }, PICKER_PRODUCT_FILTERS, cacheOverride)) {
43
+ if (shouldFetch(catalogState.productFetchState, cacheOverride)) {
57
44
  pageActions.push(fetchInvoicingCatalogProductList({
58
- fetchAll: true,
59
- filters: PICKER_PRODUCT_FILTERS,
45
+ filters: { type: 'addon|charge' },
60
46
  keepExistingListItems: false,
61
47
  }));
62
48
  }
@@ -17,25 +17,22 @@ import { invoicingSubscriptionTodayIso, toInvoicingSubscriptionBillingCycles, to
17
17
  * Sending them made every price point whose cadence the form could not express
18
18
  * — a daily plan, for instance — fail with a 422.
19
19
  */
20
- export const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress, flatFeePriceCodes = new Set()) => {
21
- const itemQuantity = (priceCode, quantity) => flatFeePriceCodes.has(priceCode)
22
- ? 1
23
- : toInvoicingSubscriptionQuantity(quantity);
20
+ export const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress) => {
24
21
  const items = [
25
22
  {
26
23
  item_price_code: localData.planPriceCode,
27
24
  item_type: 'plan',
28
- quantity: itemQuantity(localData.planPriceCode, localData.planQuantity),
25
+ quantity: toInvoicingSubscriptionQuantity(localData.planQuantity),
29
26
  },
30
27
  ...localData.addonPriceCodes.map((priceCode) => ({
31
28
  item_price_code: priceCode,
32
29
  item_type: 'addon',
33
- quantity: itemQuantity(priceCode, localData.addonQuantities[priceCode]),
30
+ quantity: toInvoicingSubscriptionQuantity(localData.addonQuantities[priceCode]),
34
31
  })),
35
32
  ...localData.chargePriceCodes.map((priceCode) => ({
36
33
  item_price_code: priceCode,
37
34
  item_type: 'charge',
38
- quantity: itemQuantity(priceCode, localData.chargeQuantities[priceCode]),
35
+ quantity: toInvoicingSubscriptionQuantity(localData.chargeQuantities[priceCode]),
39
36
  })),
40
37
  ];
41
38
  const setupFee = localData.setupFee?.amount;
@@ -62,59 +59,11 @@ export const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingA
62
59
  };
63
60
  };
64
61
  const toEstimateDate = (value) => value != null && value !== '' ? date(value) : undefined;
65
- const isItemLevelCoupon = (discount) => discount.entity_type === 'item_level_coupon';
66
- const isCoupon = (discount) => discount.entity_type === 'document_level_coupon' ||
67
- discount.entity_type === 'item_level_coupon';
68
- /**
69
- * Name the coupon behind a line's discount. Exact when the API links a coupon
70
- * row to its line (`line_item_id`); otherwise only when a single item-level
71
- * coupon applies, since then every discounted line got that one.
72
- */
73
- const lineDiscountLabel = (lineItem, discounts) => {
74
- if (lineItem.discount_amount <= 0) {
75
- return undefined;
76
- }
77
- const itemCoupons = discounts.filter(isItemLevelCoupon);
78
- const linked = lineItem.id != null
79
- ? itemCoupons.filter((coupon) => coupon.line_item_id === lineItem.id)
80
- : [];
81
- if (linked.length > 0) {
82
- return [...new Set(linked.map((coupon) => coupon.description))].join(', ');
83
- }
84
- const names = [...new Set(itemCoupons.map((coupon) => coupon.description))];
85
- return names.length === 1 ? names[0] : undefined;
86
- };
87
- /**
88
- * One row per coupon. An item-level coupon comes back once per line it
89
- * discounted, so its rows are summed; listing each would read as the same
90
- * discount taken several times.
91
- */
92
- const mergeCouponRows = (discounts) => {
93
- const rowsByCoupon = new Map();
94
- discounts.filter(isCoupon).forEach((coupon) => {
95
- // The API sends `entity_id: ""` when it has none; key those by name so
96
- // two unrelated coupons are not merged into one row.
97
- const couponKey = coupon.entity_id != null && coupon.entity_id !== ''
98
- ? coupon.entity_id
99
- : coupon.description;
100
- const key = `${coupon.entity_type}:${couponKey}`;
101
- const row = rowsByCoupon.get(key);
102
- rowsByCoupon.set(key, {
103
- amount: Math.round(((row?.amount ?? 0) + coupon.amount) * 100) / 100,
104
- description: coupon.description,
105
- });
106
- });
107
- return [...rowsByCoupon.values()];
108
- };
109
62
  const mapInvoiceEstimate = (payload, money) => payload == null
110
63
  ? undefined
111
64
  : {
112
65
  amountDue: money(payload.amount_due),
113
66
  couponDiscountTotal: money(payload.coupon_discount_total),
114
- coupons: mergeCouponRows(payload.discounts ?? []).map((coupon) => ({
115
- amount: money(coupon.amount),
116
- description: coupon.description,
117
- })),
118
67
  creditsApplied: money(payload.credits_applied),
119
68
  dueDate: toEstimateDate(payload.due_date),
120
69
  grossSubTotal: money(payload.gross_sub_total),
@@ -125,8 +74,6 @@ const mapInvoiceEstimate = (payload, money) => payload == null
125
74
  dateTo: toEstimateDate(lineItem.date_to),
126
75
  description: lineItem.description,
127
76
  discountAmount: money(lineItem.discount_amount),
128
- discountLabel: lineDiscountLabel(lineItem, payload.discounts ?? []),
129
- grossAmount: money(lineItem.gross_amount ?? lineItem.amount),
130
77
  quantity: lineItem.quantity,
131
78
  taxAmount: lineItem.tax_amount != null
132
79
  ? money(lineItem.tax_amount)
@@ -7,7 +7,7 @@ import { getInvoicingCatalogListView, getInvoicingCatalogPrices, } from '../invo
7
7
  import { getInvoicingConfigView, invoicingFieldHelpForGroup, } from '../invoicingConfigView/invoicingConfigViewSelector';
8
8
  import { getInvoicingAllCustomers } from '../invoicingCustomerListView/invoicingCustomerListViewSelector';
9
9
  import { getInvoicingFormDraftLocalData, isInvoicingFormDraftPending, } from '../invoicingFormDraft';
10
- import { initialInvoicingSubscriptionFormLocalData, invoicingPriceHasQuantity, } from './invoicingSubscriptionFormConfig';
10
+ import { initialInvoicingSubscriptionFormLocalData } from './invoicingSubscriptionFormConfig';
11
11
  import { INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE } from './invoicingSubscriptionFormConfig';
12
12
  const notStartedEstimateView = {
13
13
  creditsMayChange: false,
@@ -175,7 +175,6 @@ const toInvoicingPlanOption = (plan) => ({
175
175
  // price point and rejects a subscription that claims a different one.
176
176
  billingPeriod: plan.period,
177
177
  billingPeriodUnit: plan.periodUnit,
178
- hasQuantity: invoicingPriceHasQuantity(plan.pricingModel),
179
178
  label: plan.name ?? plan.id,
180
179
  price: invoicingUnitPrice(plan),
181
180
  productCode: plan.productCode,
@@ -187,7 +186,6 @@ const toInvoicingCatalogItemOption = (product) => ({
187
186
  // A one-time charge has no cadence, so its price is quoted flat rather than
188
187
  // per period.
189
188
  billingPeriodUnit: product.itemType === 'charge' ? undefined : product.periodUnit,
190
- hasQuantity: invoicingPriceHasQuantity(product.pricingModel),
191
189
  label: product.name ?? product.id,
192
190
  price: invoicingUnitPrice(product),
193
191
  productCode: product.productCode,
@@ -4,7 +4,7 @@ import { fetchInvoicingCouponList } from '../couponView/couponViewReducer';
4
4
  import { getInvoicingCouponListFetchState } from '../couponView/couponViewSelector';
5
5
  import { fetchInvoicingCatalogPlanList } from '../invoicingCatalogListView/invoicingCatalogListViewReducer';
6
6
  import { fetchInvoicingConfig } from '../invoicingConfigView/invoicingConfigViewReducer';
7
- import { INVOICING_LIST_ALL_TAB, shouldFetchFullInvoicingList, } from '../invoicingListTabCache';
7
+ import { INVOICING_LIST_ALL_TAB } from '../invoicingListTabCache';
8
8
  import { fetchInvoicingSubscriptionDetail, fetchInvoicingSubscriptionDetailPage, } from './editInvoicingSubscriptionDetailViewReducer';
9
9
  /**
10
10
  * Fetch unless the endpoint is already loaded or in flight — or always when the
@@ -40,14 +40,11 @@ export const fetchInvoicingSubscriptionDetailPageEpic = (actions$, state$) => ac
40
40
  // Plan and coupon lists back the names the page renders for its line
41
41
  // items; both list slices cache, so this only refetches when asked to.
42
42
  const catalogListState = state.invoicingCatalogListViewState;
43
- if (shouldFetchFullInvoicingList({
43
+ if (shouldFetch({
44
+ error: catalogListState.error,
44
45
  fetchState: catalogListState.fetchState,
45
- filters: catalogListState.planFilters,
46
- nextCursor: catalogListState.planNextCursor,
47
- sort: catalogListState.planSort,
48
- }, { type: 'plan' }, cacheOverride)) {
46
+ }, cacheOverride)) {
49
47
  pageActions.push(fetchInvoicingCatalogPlanList({
50
- fetchAll: true,
51
48
  filters: { type: 'plan' },
52
49
  keepExistingListItems: false,
53
50
  }));
@@ -20,7 +20,6 @@ export const fetchInvoicingSubscriptionFormPageEpic = (actions$) => actions$.pip
20
20
  // unfiltered list would replace the store's plans with every catalog
21
21
  // item.
22
22
  fetchInvoicingCatalogPlanList({
23
- fetchAll: true,
24
23
  filters: { type: 'plan' },
25
24
  keepExistingListItems: false,
26
25
  }),
@@ -22,8 +22,6 @@ const subscriptionItemQuantities = (subscription, itemType) => {
22
22
  * their day gets their own calendar date rather than yesterday's.
23
23
  */
24
24
  export const invoicingSubscriptionTodayIso = () => dateNow().format('YYYY-MM-DD');
25
- /** A flat fee bills its price once, so its quantity is always 1. */
26
- export const invoicingPriceHasQuantity = (pricingModel) => pricingModel !== 'flat_fee';
27
25
  /**
28
26
  * Clamp a subscription-item quantity to the minimum the API accepts. Shared by
29
27
  * the plan, add-on and charge items so none of them can bill a 0 or a fraction.
@@ -9,11 +9,10 @@ import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload
9
9
  import { resetNewAddressDataInLocalStore } from '../../addressView/addressViewReducer';
10
10
  import { invalidateInvoicingCustomerDetail } from '../editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer';
11
11
  import { invalidateInvoiceListForCustomer } from '../invoiceList/invoiceListReducer';
12
- import { getInvoicingCatalogPrices } from '../invoicingCatalogListView/invoicingCatalogListViewSelector';
13
12
  import { addInvoicingSubscriptionToList } from '../invoicingSubscriptionListView/invoicingSubscriptionListViewReducer';
14
13
  import { localDataToSaveInvoicingSubscriptionPayload, } from './editInvoicingSubscriptionDetailViewPayload';
15
14
  import { submitInvoicingSubscriptionForm, submitInvoicingSubscriptionFormFailure, submitInvoicingSubscriptionFormSuccess, syncInvoicingSubscriptionCoupons, } from './editInvoicingSubscriptionDetailViewReducer';
16
- import { INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE, invoicingPriceHasQuantity, } from './invoicingSubscriptionFormConfig';
15
+ import { INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE } from './invoicingSubscriptionFormConfig';
17
16
  const normalizeCouponCode = (value) => (value ?? '').trim().toUpperCase();
18
17
  export const isInvoicingSubscriptionCouponChanged = (previousCouponCode, nextCouponCode) => normalizeCouponCode(previousCouponCode) !==
19
18
  normalizeCouponCode(nextCouponCode);
@@ -26,10 +25,7 @@ export const invoicingSubscriptionSaveRequest = (rootState, id) => {
26
25
  // Shipping address captured via the shared Address screen is sent as an
27
26
  // object in the payload (same pattern as the customer save flow).
28
27
  const shippingAddress = rootState.addressViewState.newAddressState?.[INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE]?.addressToCreate;
29
- const flatFeePriceCodes = new Set(getInvoicingCatalogPrices(Object.values(rootState.invoicingCatalogState.itemByID))
30
- .filter((price) => !invoicingPriceHasQuantity(price.pricingModel))
31
- .flatMap((price) => price.priceCode ?? []));
32
- const data = localDataToSaveInvoicingSubscriptionPayload(localData, shippingAddress, flatFeePriceCodes);
28
+ const data = localDataToSaveInvoicingSubscriptionPayload(localData, shippingAddress);
33
29
  if (id != null) {
34
30
  delete data.coupon_ids;
35
31
  }
@@ -23,30 +23,19 @@ const buildPlanQuery = (filters, cursor, sort) => {
23
23
  return params;
24
24
  };
25
25
  export const fetchInvoicingCatalogPlanListEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingCatalogPlanList.match), switchMap((action) => {
26
- const { filters, cursor, fetchAll, keepExistingListItems, sort } = action.payload;
26
+ const { filters, cursor, keepExistingListItems, sort } = action.payload;
27
27
  const apiUrl = withQuery(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/catalog/plans`, buildPlanQuery(filters, cursor, sort));
28
28
  return zeniAPI.getJSON(apiUrl).pipe(switchMap((response) => {
29
29
  if (isSuccessResponse(response)) {
30
30
  const items = response.data?.items ?? [];
31
- const nextCursor = response.data?.next_cursor ?? null;
32
- const pageActions = [
31
+ return [
33
32
  updateInvoicingCatalogItems(items, 'merge'),
34
33
  updateInvoicingCatalogPlanList({
35
34
  ids: items.map((item) => item.id),
36
- nextCursor,
35
+ nextCursor: response.data?.next_cursor ?? null,
37
36
  keepExistingListItems,
38
37
  }),
39
38
  ];
40
- if (fetchAll && nextCursor != null && nextCursor !== cursor) {
41
- pageActions.push(fetchInvoicingCatalogPlanList({
42
- cursor: nextCursor,
43
- fetchAll,
44
- filters,
45
- keepExistingListItems: true,
46
- sort,
47
- }));
48
- }
49
- return pageActions;
50
39
  }
51
40
  return of(updateInvoicingCatalogPlanListFailure(response.status));
52
41
  }), catchError((error) => of(updateInvoicingCatalogPlanListFailure(createZeniAPIStatus('Unexpected Error', 'Fetch catalog plan list REST API call errored out ' +
@@ -23,30 +23,19 @@ const buildProductQuery = (filters, cursor, sort) => {
23
23
  return params;
24
24
  };
25
25
  export const fetchInvoicingCatalogProductListEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingCatalogProductList.match), switchMap((action) => {
26
- const { filters, cursor, fetchAll, keepExistingListItems, sort } = action.payload;
26
+ const { filters, cursor, keepExistingListItems, sort } = action.payload;
27
27
  const apiUrl = withQuery(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/catalog/plans`, buildProductQuery(filters, cursor, sort));
28
28
  return zeniAPI.getJSON(apiUrl).pipe(switchMap((response) => {
29
29
  if (isSuccessResponse(response)) {
30
30
  const items = response.data?.items ?? [];
31
- const nextCursor = response.data?.next_cursor ?? null;
32
- const pageActions = [
31
+ return [
33
32
  updateInvoicingCatalogItems(items, 'merge'),
34
33
  updateInvoicingCatalogProductList({
35
34
  ids: items.map((item) => item.id),
36
- nextCursor,
35
+ nextCursor: response.data?.next_cursor ?? null,
37
36
  keepExistingListItems,
38
37
  }),
39
38
  ];
40
- if (fetchAll && nextCursor != null && nextCursor !== cursor) {
41
- pageActions.push(fetchInvoicingCatalogProductList({
42
- cursor: nextCursor,
43
- fetchAll,
44
- filters,
45
- keepExistingListItems: true,
46
- sort,
47
- }));
48
- }
49
- return pageActions;
50
39
  }
51
40
  return of(updateInvoicingCatalogProductListFailure(response.status));
52
41
  }), catchError((error) => of(updateInvoicingCatalogProductListFailure(createZeniAPIStatus('Unexpected Error', 'Fetch catalog product list REST API call errored out ' +
@@ -36,7 +36,6 @@ const invoicingCatalogListView = createSlice({
36
36
  payload: {
37
37
  filters: payload.filters ?? {},
38
38
  cursor: payload.cursor,
39
- fetchAll: payload.fetchAll ?? false,
40
39
  keepExistingListItems: payload.keepExistingListItems ?? false,
41
40
  sort: payload.sort,
42
41
  },
@@ -71,7 +70,6 @@ const invoicingCatalogListView = createSlice({
71
70
  payload: {
72
71
  filters: payload.filters ?? {},
73
72
  cursor: payload.cursor,
74
- fetchAll: payload.fetchAll ?? false,
75
73
  keepExistingListItems: payload.keepExistingListItems ?? false,
76
74
  sort: payload.sort,
77
75
  },
@@ -33,14 +33,6 @@ export const isSameInvoicingListQuery = (a, b) => {
33
33
  a.sort?.field === b.sort?.field &&
34
34
  a.sort?.dir === b.sort?.dir);
35
35
  };
36
- /**
37
- * For a picker that searches client-side: reuse only a complete list fetched
38
- * with the picker's own query, else load every page of it.
39
- */
40
- export const shouldFetchFullInvoicingList = (list, pickerFilters, cacheOverride) => cacheOverride ||
41
- list.fetchState !== 'Completed' ||
42
- list.nextCursor != null ||
43
- !isSameInvoicingListQuery({ filters: list.filters, sort: list.sort }, { filters: pickerFilters });
44
36
  /**
45
37
  * Fetch a tab that is empty or failed; top up one that holds less than a page
46
38
  * while the server says there is more; leave a full or complete one cached.
package/lib/index.d.ts CHANGED
@@ -1130,7 +1130,7 @@ export { getInvoicingCustomerFormView } from './view/invoicing/editInvoicingCust
1130
1130
  export type { InvoicingCustomerFormView } from './view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector';
1131
1131
  export { clearInvoicingSubscriptionEstimate, fetchInvoicingSubscriptionEstimate, fetchInvoicingSubscriptionFormPage, initializeInvoicingSubscriptionAddress, resetEditInvoicingSubscriptionDetailView, submitInvoicingSubscriptionForm, updateInvoicingSubscriptionFormDraft, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewReducer';
1132
1132
  export type { SubmitInvoicingSubscriptionFormPayload, UpdateInvoicingSubscriptionFormDraftPayload, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewReducer';
1133
- export type { InvoicingSubscriptionEstimateCoupon, InvoicingSubscriptionEstimateLineItem, InvoicingSubscriptionFormLocalData, InvoicingSubscriptionInvoiceEstimate, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState';
1133
+ export type { InvoicingSubscriptionEstimateLineItem, InvoicingSubscriptionFormLocalData, InvoicingSubscriptionInvoiceEstimate, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState';
1134
1134
  export { INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE, entityToInvoicingSubscriptionFormLocalData, initialInvoicingSubscriptionFormLocalData, invoicingSubscriptionTodayIso, toInvoicingSubscriptionQuantity, } from './view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig';
1135
1135
  export { getEditInvoicingSubscriptionDetailViewState, getInvoicingSubscriptionFormView, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector';
1136
1136
  export type { EditInvoicingSubscriptionDetailView, InvoicingSubscriptionEstimateKind, InvoicingSubscriptionEstimateView, InvoicingSubscriptionFormView, InvoicingSubscriptionOption, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector';
@@ -16,8 +16,6 @@ const createInvoiceReducer_1 = require("../createInvoiceReducer");
16
16
  const shouldFetch = (fetchStateAndError, cacheOverride) => cacheOverride ||
17
17
  (fetchStateAndError.fetchState !== 'Completed' &&
18
18
  fetchStateAndError.fetchState !== 'In-Progress');
19
- const PICKER_PLAN_FILTERS = { type: 'plan' };
20
- const PICKER_PRODUCT_FILTERS = { type: 'addon|charge' };
21
19
  /**
22
20
  * Orchestrates the create-invoice form's option sources: on
23
21
  * `fetchCreateInvoiceFormPage`, fans out to the customer, catalog plan, catalog
@@ -39,27 +37,15 @@ const fetchCreateInvoiceFormPageEpic = (actions$, state$) => actions$.pipe((0, o
39
37
  tabId: invoicingListTabCache_1.INVOICING_LIST_ALL_TAB,
40
38
  }));
41
39
  }
42
- if ((0, invoicingListTabCache_1.shouldFetchFullInvoicingList)({
43
- fetchState: catalogState.fetchState,
44
- filters: catalogState.planFilters,
45
- nextCursor: catalogState.planNextCursor,
46
- sort: catalogState.planSort,
47
- }, PICKER_PLAN_FILTERS, cacheOverride)) {
40
+ if (shouldFetch({ fetchState: catalogState.fetchState, error: catalogState.error }, cacheOverride)) {
48
41
  pageActions.push((0, invoicingCatalogListViewReducer_1.fetchInvoicingCatalogPlanList)({
49
- fetchAll: true,
50
- filters: PICKER_PLAN_FILTERS,
42
+ filters: { type: 'plan' },
51
43
  keepExistingListItems: false,
52
44
  }));
53
45
  }
54
- if ((0, invoicingListTabCache_1.shouldFetchFullInvoicingList)({
55
- fetchState: catalogState.productFetchState.fetchState,
56
- filters: catalogState.productFilters,
57
- nextCursor: catalogState.productNextCursor,
58
- sort: catalogState.productSort,
59
- }, PICKER_PRODUCT_FILTERS, cacheOverride)) {
46
+ if (shouldFetch(catalogState.productFetchState, cacheOverride)) {
60
47
  pageActions.push((0, invoicingCatalogListViewReducer_1.fetchInvoicingCatalogProductList)({
61
- fetchAll: true,
62
- filters: PICKER_PRODUCT_FILTERS,
48
+ filters: { type: 'addon|charge' },
63
49
  keepExistingListItems: false,
64
50
  }));
65
51
  }
@@ -18,7 +18,7 @@ export type SaveInvoicingSubscriptionResponse = ZeniAPIResponse<InvoicingSubscri
18
18
  * Sending them made every price point whose cadence the form could not express
19
19
  * — a daily plan, for instance — fail with a 422.
20
20
  */
21
- export declare const localDataToSaveInvoicingSubscriptionPayload: (localData: InvoicingSubscriptionFormLocalData, shippingAddress?: AddressUpdatableInfo, flatFeePriceCodes?: ReadonlySet<string>) => Record<string, unknown>;
21
+ export declare const localDataToSaveInvoicingSubscriptionPayload: (localData: InvoicingSubscriptionFormLocalData, shippingAddress?: AddressUpdatableInfo) => Record<string, unknown>;
22
22
  export type RunInvoicingSubscriptionActionResponse = ZeniAPIResponse<InvoicingSubscriptionPayload>;
23
23
  /** Snake_case request bodies for subscription action endpoints. */
24
24
  export type ApplyCouponBody = {
@@ -82,17 +82,8 @@ interface InvoicingSubscriptionEstimateLineItemPayload {
82
82
  unit_amount: number;
83
83
  date_from?: string;
84
84
  date_to?: string;
85
- gross_amount?: number;
86
- id?: string;
87
85
  tax_amount?: number | null;
88
86
  }
89
- interface InvoicingSubscriptionEstimateDiscountPayload {
90
- amount: number;
91
- description: string;
92
- entity_type: string;
93
- entity_id?: string;
94
- line_item_id?: string | null;
95
- }
96
87
  interface InvoicingSubscriptionInvoiceEstimatePayload {
97
88
  amount_due: number;
98
89
  coupon_discount_total: number;
@@ -103,7 +94,6 @@ interface InvoicingSubscriptionInvoiceEstimatePayload {
103
94
  sub_total: number;
104
95
  tax: number | null;
105
96
  total: number;
106
- discounts?: InvoicingSubscriptionEstimateDiscountPayload[];
107
97
  due_date?: string;
108
98
  invoice_date?: string;
109
99
  }
@@ -20,25 +20,22 @@ const invoicingSubscriptionFormConfig_1 = require("./invoicingSubscriptionFormCo
20
20
  * Sending them made every price point whose cadence the form could not express
21
21
  * — a daily plan, for instance — fail with a 422.
22
22
  */
23
- const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress, flatFeePriceCodes = new Set()) => {
24
- const itemQuantity = (priceCode, quantity) => flatFeePriceCodes.has(priceCode)
25
- ? 1
26
- : (0, invoicingSubscriptionFormConfig_1.toInvoicingSubscriptionQuantity)(quantity);
23
+ const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress) => {
27
24
  const items = [
28
25
  {
29
26
  item_price_code: localData.planPriceCode,
30
27
  item_type: 'plan',
31
- quantity: itemQuantity(localData.planPriceCode, localData.planQuantity),
28
+ quantity: (0, invoicingSubscriptionFormConfig_1.toInvoicingSubscriptionQuantity)(localData.planQuantity),
32
29
  },
33
30
  ...localData.addonPriceCodes.map((priceCode) => ({
34
31
  item_price_code: priceCode,
35
32
  item_type: 'addon',
36
- quantity: itemQuantity(priceCode, localData.addonQuantities[priceCode]),
33
+ quantity: (0, invoicingSubscriptionFormConfig_1.toInvoicingSubscriptionQuantity)(localData.addonQuantities[priceCode]),
37
34
  })),
38
35
  ...localData.chargePriceCodes.map((priceCode) => ({
39
36
  item_price_code: priceCode,
40
37
  item_type: 'charge',
41
- quantity: itemQuantity(priceCode, localData.chargeQuantities[priceCode]),
38
+ quantity: (0, invoicingSubscriptionFormConfig_1.toInvoicingSubscriptionQuantity)(localData.chargeQuantities[priceCode]),
42
39
  })),
43
40
  ];
44
41
  const setupFee = localData.setupFee?.amount;
@@ -66,59 +63,11 @@ const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress,
66
63
  };
67
64
  exports.localDataToSaveInvoicingSubscriptionPayload = localDataToSaveInvoicingSubscriptionPayload;
68
65
  const toEstimateDate = (value) => value != null && value !== '' ? (0, zeniDayJS_1.date)(value) : undefined;
69
- const isItemLevelCoupon = (discount) => discount.entity_type === 'item_level_coupon';
70
- const isCoupon = (discount) => discount.entity_type === 'document_level_coupon' ||
71
- discount.entity_type === 'item_level_coupon';
72
- /**
73
- * Name the coupon behind a line's discount. Exact when the API links a coupon
74
- * row to its line (`line_item_id`); otherwise only when a single item-level
75
- * coupon applies, since then every discounted line got that one.
76
- */
77
- const lineDiscountLabel = (lineItem, discounts) => {
78
- if (lineItem.discount_amount <= 0) {
79
- return undefined;
80
- }
81
- const itemCoupons = discounts.filter(isItemLevelCoupon);
82
- const linked = lineItem.id != null
83
- ? itemCoupons.filter((coupon) => coupon.line_item_id === lineItem.id)
84
- : [];
85
- if (linked.length > 0) {
86
- return [...new Set(linked.map((coupon) => coupon.description))].join(', ');
87
- }
88
- const names = [...new Set(itemCoupons.map((coupon) => coupon.description))];
89
- return names.length === 1 ? names[0] : undefined;
90
- };
91
- /**
92
- * One row per coupon. An item-level coupon comes back once per line it
93
- * discounted, so its rows are summed; listing each would read as the same
94
- * discount taken several times.
95
- */
96
- const mergeCouponRows = (discounts) => {
97
- const rowsByCoupon = new Map();
98
- discounts.filter(isCoupon).forEach((coupon) => {
99
- // The API sends `entity_id: ""` when it has none; key those by name so
100
- // two unrelated coupons are not merged into one row.
101
- const couponKey = coupon.entity_id != null && coupon.entity_id !== ''
102
- ? coupon.entity_id
103
- : coupon.description;
104
- const key = `${coupon.entity_type}:${couponKey}`;
105
- const row = rowsByCoupon.get(key);
106
- rowsByCoupon.set(key, {
107
- amount: Math.round(((row?.amount ?? 0) + coupon.amount) * 100) / 100,
108
- description: coupon.description,
109
- });
110
- });
111
- return [...rowsByCoupon.values()];
112
- };
113
66
  const mapInvoiceEstimate = (payload, money) => payload == null
114
67
  ? undefined
115
68
  : {
116
69
  amountDue: money(payload.amount_due),
117
70
  couponDiscountTotal: money(payload.coupon_discount_total),
118
- coupons: mergeCouponRows(payload.discounts ?? []).map((coupon) => ({
119
- amount: money(coupon.amount),
120
- description: coupon.description,
121
- })),
122
71
  creditsApplied: money(payload.credits_applied),
123
72
  dueDate: toEstimateDate(payload.due_date),
124
73
  grossSubTotal: money(payload.gross_sub_total),
@@ -129,8 +78,6 @@ const mapInvoiceEstimate = (payload, money) => payload == null
129
78
  dateTo: toEstimateDate(lineItem.date_to),
130
79
  description: lineItem.description,
131
80
  discountAmount: money(lineItem.discount_amount),
132
- discountLabel: lineDiscountLabel(lineItem, payload.discounts ?? []),
133
- grossAmount: money(lineItem.gross_amount ?? lineItem.amount),
134
81
  quantity: lineItem.quantity,
135
82
  taxAmount: lineItem.tax_amount != null
136
83
  ? money(lineItem.tax_amount)
@@ -147,8 +147,6 @@ export interface InvoicingSubscriptionOption {
147
147
  billingCycles?: number;
148
148
  billingPeriod?: number;
149
149
  billingPeriodUnit?: string;
150
- /** Catalog options only: false for a flat fee, which takes no quantity. */
151
- hasQuantity?: boolean;
152
150
  price?: Amount;
153
151
  productCode?: string;
154
152
  subtitle?: string;
@@ -182,7 +182,6 @@ const toInvoicingPlanOption = (plan) => ({
182
182
  // price point and rejects a subscription that claims a different one.
183
183
  billingPeriod: plan.period,
184
184
  billingPeriodUnit: plan.periodUnit,
185
- hasQuantity: (0, invoicingSubscriptionFormConfig_1.invoicingPriceHasQuantity)(plan.pricingModel),
186
185
  label: plan.name ?? plan.id,
187
186
  price: invoicingUnitPrice(plan),
188
187
  productCode: plan.productCode,
@@ -194,7 +193,6 @@ const toInvoicingCatalogItemOption = (product) => ({
194
193
  // A one-time charge has no cadence, so its price is quoted flat rather than
195
194
  // per period.
196
195
  billingPeriodUnit: product.itemType === 'charge' ? undefined : product.periodUnit,
197
- hasQuantity: (0, invoicingSubscriptionFormConfig_1.invoicingPriceHasQuantity)(product.pricingModel),
198
196
  label: product.name ?? product.id,
199
197
  price: invoicingUnitPrice(product),
200
198
  productCode: product.productCode,
@@ -41,32 +41,19 @@ export interface InvoicingSubscriptionFormLocalData {
41
41
  setupFee?: Amount;
42
42
  }
43
43
  export interface InvoicingSubscriptionEstimateLineItem {
44
- /** After the line's own (item-level) coupons. */
45
44
  amount: Amount;
46
45
  description: string;
47
- /** Item-level coupons on this line; invoice-level coupons are not spread here. */
48
46
  discountAmount: Amount;
49
- /** Before any coupon, so the lines add up to `grossSubTotal`. */
50
- grossAmount: Amount;
51
47
  quantity: number;
52
48
  unitAmount: Amount;
53
49
  dateFrom?: ZeniDate;
54
50
  dateTo?: ZeniDate;
55
- /** The coupon behind `discountAmount`, when it can be told; see the mapper. */
56
- discountLabel?: string;
57
51
  taxAmount?: Amount;
58
52
  }
59
- /** A coupon the estimate applies, named, for the totals. */
60
- export interface InvoicingSubscriptionEstimateCoupon {
61
- amount: Amount;
62
- description: string;
63
- }
64
53
  /** An invoice the save would raise now, or the next one it would raise later. */
65
54
  export interface InvoicingSubscriptionInvoiceEstimate {
66
55
  amountDue: Amount;
67
56
  couponDiscountTotal: Amount;
68
- /** Item- and invoice-level coupons, one row each; they sum to `couponDiscountTotal`. */
69
- coupons: InvoicingSubscriptionEstimateCoupon[];
70
57
  /** Refundable credits plus excess payments; promotional credits are separate. */
71
58
  creditsApplied: Amount;
72
59
  grossSubTotal: Amount;
@@ -43,14 +43,11 @@ const fetchInvoicingSubscriptionDetailPageEpic = (actions$, state$) => actions$.
43
43
  // Plan and coupon lists back the names the page renders for its line
44
44
  // items; both list slices cache, so this only refetches when asked to.
45
45
  const catalogListState = state.invoicingCatalogListViewState;
46
- if ((0, invoicingListTabCache_1.shouldFetchFullInvoicingList)({
46
+ if (shouldFetch({
47
+ error: catalogListState.error,
47
48
  fetchState: catalogListState.fetchState,
48
- filters: catalogListState.planFilters,
49
- nextCursor: catalogListState.planNextCursor,
50
- sort: catalogListState.planSort,
51
- }, { type: 'plan' }, cacheOverride)) {
49
+ }, cacheOverride)) {
52
50
  pageActions.push((0, invoicingCatalogListViewReducer_1.fetchInvoicingCatalogPlanList)({
53
- fetchAll: true,
54
51
  filters: { type: 'plan' },
55
52
  keepExistingListItems: false,
56
53
  }));
@@ -23,7 +23,6 @@ const fetchInvoicingSubscriptionFormPageEpic = (actions$) => actions$.pipe((0, o
23
23
  // unfiltered list would replace the store's plans with every catalog
24
24
  // item.
25
25
  (0, invoicingCatalogListViewReducer_1.fetchInvoicingCatalogPlanList)({
26
- fetchAll: true,
27
26
  filters: { type: 'plan' },
28
27
  keepExistingListItems: false,
29
28
  }),
@@ -8,8 +8,6 @@ export declare const INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE: "invoicing_su
8
8
  * their day gets their own calendar date rather than yesterday's.
9
9
  */
10
10
  export declare const invoicingSubscriptionTodayIso: () => string;
11
- /** A flat fee bills its price once, so its quantity is always 1. */
12
- export declare const invoicingPriceHasQuantity: (pricingModel?: string) => boolean;
13
11
  /**
14
12
  * Clamp a subscription-item quantity to the minimum the API accepts. Shared by
15
13
  * the plan, add-on and charge items so none of them can bill a 0 or a fraction.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.entityToInvoicingSubscriptionFormLocalData = exports.initialInvoicingSubscriptionFormLocalData = exports.toInvoicingSubscriptionBillingCycles = exports.toInvoicingSubscriptionQuantity = exports.invoicingPriceHasQuantity = exports.invoicingSubscriptionTodayIso = exports.INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE = void 0;
3
+ exports.entityToInvoicingSubscriptionFormLocalData = exports.initialInvoicingSubscriptionFormLocalData = exports.toInvoicingSubscriptionBillingCycles = exports.toInvoicingSubscriptionQuantity = exports.invoicingSubscriptionTodayIso = exports.INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE = void 0;
4
4
  const zeniDayJS_1 = require("../../../zeniDayJS");
5
5
  /** `AddressType` key used when the subscription form opens the shared Address screen. */
6
6
  exports.INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE = 'invoicing_subscription_shipping_address';
@@ -26,9 +26,6 @@ const subscriptionItemQuantities = (subscription, itemType) => {
26
26
  */
27
27
  const invoicingSubscriptionTodayIso = () => (0, zeniDayJS_1.dateNow)().format('YYYY-MM-DD');
28
28
  exports.invoicingSubscriptionTodayIso = invoicingSubscriptionTodayIso;
29
- /** A flat fee bills its price once, so its quantity is always 1. */
30
- const invoicingPriceHasQuantity = (pricingModel) => pricingModel !== 'flat_fee';
31
- exports.invoicingPriceHasQuantity = invoicingPriceHasQuantity;
32
29
  /**
33
30
  * Clamp a subscription-item quantity to the minimum the API accepts. Shared by
34
31
  * the plan, add-on and charge items so none of them can bill a 0 or a fraction.
@@ -12,7 +12,6 @@ const responsePayload_1 = require("../../../responsePayload");
12
12
  const addressViewReducer_1 = require("../../addressView/addressViewReducer");
13
13
  const editInvoicingCustomerDetailViewReducer_1 = require("../editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer");
14
14
  const invoiceListReducer_1 = require("../invoiceList/invoiceListReducer");
15
- const invoicingCatalogListViewSelector_1 = require("../invoicingCatalogListView/invoicingCatalogListViewSelector");
16
15
  const invoicingSubscriptionListViewReducer_1 = require("../invoicingSubscriptionListView/invoicingSubscriptionListViewReducer");
17
16
  const editInvoicingSubscriptionDetailViewPayload_1 = require("./editInvoicingSubscriptionDetailViewPayload");
18
17
  const editInvoicingSubscriptionDetailViewReducer_1 = require("./editInvoicingSubscriptionDetailViewReducer");
@@ -30,10 +29,7 @@ const invoicingSubscriptionSaveRequest = (rootState, id) => {
30
29
  // Shipping address captured via the shared Address screen is sent as an
31
30
  // object in the payload (same pattern as the customer save flow).
32
31
  const shippingAddress = rootState.addressViewState.newAddressState?.[invoicingSubscriptionFormConfig_1.INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE]?.addressToCreate;
33
- const flatFeePriceCodes = new Set((0, invoicingCatalogListViewSelector_1.getInvoicingCatalogPrices)(Object.values(rootState.invoicingCatalogState.itemByID))
34
- .filter((price) => !(0, invoicingSubscriptionFormConfig_1.invoicingPriceHasQuantity)(price.pricingModel))
35
- .flatMap((price) => price.priceCode ?? []));
36
- const data = (0, editInvoicingSubscriptionDetailViewPayload_1.localDataToSaveInvoicingSubscriptionPayload)(localData, shippingAddress, flatFeePriceCodes);
32
+ const data = (0, editInvoicingSubscriptionDetailViewPayload_1.localDataToSaveInvoicingSubscriptionPayload)(localData, shippingAddress);
37
33
  if (id != null) {
38
34
  delete data.coupon_ids;
39
35
  }
@@ -26,30 +26,19 @@ const buildPlanQuery = (filters, cursor, sort) => {
26
26
  return params;
27
27
  };
28
28
  const fetchInvoicingCatalogPlanListEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingCatalogListViewReducer_1.fetchInvoicingCatalogPlanList.match), (0, operators_1.switchMap)((action) => {
29
- const { filters, cursor, fetchAll, keepExistingListItems, sort } = action.payload;
29
+ const { filters, cursor, keepExistingListItems, sort } = action.payload;
30
30
  const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/catalog/plans`, buildPlanQuery(filters, cursor, sort));
31
31
  return zeniAPI.getJSON(apiUrl).pipe((0, operators_1.switchMap)((response) => {
32
32
  if ((0, responsePayload_1.isSuccessResponse)(response)) {
33
33
  const items = response.data?.items ?? [];
34
- const nextCursor = response.data?.next_cursor ?? null;
35
- const pageActions = [
34
+ return [
36
35
  (0, invoicingCatalogReducer_1.updateInvoicingCatalogItems)(items, 'merge'),
37
36
  (0, invoicingCatalogListViewReducer_1.updateInvoicingCatalogPlanList)({
38
37
  ids: items.map((item) => item.id),
39
- nextCursor,
38
+ nextCursor: response.data?.next_cursor ?? null,
40
39
  keepExistingListItems,
41
40
  }),
42
41
  ];
43
- if (fetchAll && nextCursor != null && nextCursor !== cursor) {
44
- pageActions.push((0, invoicingCatalogListViewReducer_1.fetchInvoicingCatalogPlanList)({
45
- cursor: nextCursor,
46
- fetchAll,
47
- filters,
48
- keepExistingListItems: true,
49
- sort,
50
- }));
51
- }
52
- return pageActions;
53
42
  }
54
43
  return (0, rxjs_1.of)((0, invoicingCatalogListViewReducer_1.updateInvoicingCatalogPlanListFailure)(response.status));
55
44
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingCatalogListViewReducer_1.updateInvoicingCatalogPlanListFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch catalog plan list REST API call errored out ' +
@@ -26,30 +26,19 @@ const buildProductQuery = (filters, cursor, sort) => {
26
26
  return params;
27
27
  };
28
28
  const fetchInvoicingCatalogProductListEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingCatalogListViewReducer_1.fetchInvoicingCatalogProductList.match), (0, operators_1.switchMap)((action) => {
29
- const { filters, cursor, fetchAll, keepExistingListItems, sort } = action.payload;
29
+ const { filters, cursor, keepExistingListItems, sort } = action.payload;
30
30
  const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/catalog/plans`, buildProductQuery(filters, cursor, sort));
31
31
  return zeniAPI.getJSON(apiUrl).pipe((0, operators_1.switchMap)((response) => {
32
32
  if ((0, responsePayload_1.isSuccessResponse)(response)) {
33
33
  const items = response.data?.items ?? [];
34
- const nextCursor = response.data?.next_cursor ?? null;
35
- const pageActions = [
34
+ return [
36
35
  (0, invoicingCatalogReducer_1.updateInvoicingCatalogItems)(items, 'merge'),
37
36
  (0, invoicingCatalogListViewReducer_1.updateInvoicingCatalogProductList)({
38
37
  ids: items.map((item) => item.id),
39
- nextCursor,
38
+ nextCursor: response.data?.next_cursor ?? null,
40
39
  keepExistingListItems,
41
40
  }),
42
41
  ];
43
- if (fetchAll && nextCursor != null && nextCursor !== cursor) {
44
- pageActions.push((0, invoicingCatalogListViewReducer_1.fetchInvoicingCatalogProductList)({
45
- cursor: nextCursor,
46
- fetchAll,
47
- filters,
48
- keepExistingListItems: true,
49
- sort,
50
- }));
51
- }
52
- return pageActions;
53
42
  }
54
43
  return (0, rxjs_1.of)((0, invoicingCatalogListViewReducer_1.updateInvoicingCatalogProductListFailure)(response.status));
55
44
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingCatalogListViewReducer_1.updateInvoicingCatalogProductListFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch catalog product list REST API call errored out ' +
@@ -6,15 +6,12 @@ import { InvoicingCatalogListViewState, InvoicingCatalogPlanFilters, InvoicingCa
6
6
  export declare const initialState: InvoicingCatalogListViewState;
7
7
  export declare const fetchInvoicingCatalogPlanList: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
8
8
  cursor?: string;
9
- /** Keep requesting the next page until the list is complete. */
10
- fetchAll?: boolean;
11
9
  filters?: InvoicingCatalogPlanFilters;
12
10
  keepExistingListItems?: boolean;
13
11
  sort?: InvoicingListSort;
14
12
  }], {
15
13
  filters: InvoicingCatalogPlanFilters;
16
14
  cursor: string | undefined;
17
- fetchAll: boolean;
18
15
  keepExistingListItems: boolean;
19
16
  sort: InvoicingListSort | undefined;
20
17
  }, "invoicingCatalogListView/fetchInvoicingCatalogPlanList", never, never>, updateInvoicingCatalogPlanList: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
@@ -23,15 +20,12 @@ export declare const fetchInvoicingCatalogPlanList: import("@reduxjs/toolkit").A
23
20
  nextCursor: string | null;
24
21
  }, "invoicingCatalogListView/updateInvoicingCatalogPlanList">, updateInvoicingCatalogPlanListFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingCatalogListView/updateInvoicingCatalogPlanListFailure">, fetchInvoicingCatalogProductList: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
25
22
  cursor?: string;
26
- /** Keep requesting the next page until the list is complete. */
27
- fetchAll?: boolean;
28
23
  filters?: InvoicingCatalogProductFilters;
29
24
  keepExistingListItems?: boolean;
30
25
  sort?: InvoicingListSort;
31
26
  }], {
32
27
  filters: InvoicingCatalogProductFilters;
33
28
  cursor: string | undefined;
34
- fetchAll: boolean;
35
29
  keepExistingListItems: boolean;
36
30
  sort: InvoicingListSort | undefined;
37
31
  }, "invoicingCatalogListView/fetchInvoicingCatalogProductList", never, never>, updateInvoicingCatalogProductList: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
@@ -40,7 +40,6 @@ const invoicingCatalogListView = (0, toolkit_1.createSlice)({
40
40
  payload: {
41
41
  filters: payload.filters ?? {},
42
42
  cursor: payload.cursor,
43
- fetchAll: payload.fetchAll ?? false,
44
43
  keepExistingListItems: payload.keepExistingListItems ?? false,
45
44
  sort: payload.sort,
46
45
  },
@@ -75,7 +74,6 @@ const invoicingCatalogListView = (0, toolkit_1.createSlice)({
75
74
  payload: {
76
75
  filters: payload.filters ?? {},
77
76
  cursor: payload.cursor,
78
- fetchAll: payload.fetchAll ?? false,
79
77
  keepExistingListItems: payload.keepExistingListItems ?? false,
80
78
  sort: payload.sort,
81
79
  },
@@ -1,4 +1,4 @@
1
- import { FetchState, FetchStateAndError, ID } from '../../commonStateTypes/common';
1
+ import { FetchStateAndError, ID } from '../../commonStateTypes/common';
2
2
  import { ZeniAPIStatus } from '../../responsePayload';
3
3
  import { InvoicingListSort } from './invoicingApiHelper';
4
4
  /**
@@ -42,16 +42,6 @@ export declare const isSameInvoicingListQuery: (a: {
42
42
  filters: object;
43
43
  sort?: InvoicingListSort;
44
44
  }) => boolean;
45
- /**
46
- * For a picker that searches client-side: reuse only a complete list fetched
47
- * with the picker's own query, else load every page of it.
48
- */
49
- export declare const shouldFetchFullInvoicingList: (list: {
50
- fetchState: FetchState;
51
- filters: object;
52
- nextCursor: string | null;
53
- sort?: InvoicingListSort;
54
- }, pickerFilters: object, cacheOverride: boolean) => boolean;
55
45
  /** What opening a tab should fetch, if anything. */
56
46
  export type InvoicingListTabFetch = {
57
47
  kind: 'none';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.shouldFetchFullInvoicingList = exports.isSameInvoicingListQuery = exports.invoicingListStatusParam = exports.invoicingListFetchTab = exports.invoicingListSourceTab = exports.getInvoicingListTab = exports.INVOICING_LIST_ALL_TAB = void 0;
3
+ exports.isSameInvoicingListQuery = exports.invoicingListStatusParam = exports.invoicingListFetchTab = exports.invoicingListSourceTab = exports.getInvoicingListTab = exports.INVOICING_LIST_ALL_TAB = void 0;
4
4
  exports.planInvoicingListTabFetch = planInvoicingListTabFetch;
5
5
  exports.startInvoicingListTabFetch = startInvoicingListTabFetch;
6
6
  exports.completeInvoicingListTabFetch = completeInvoicingListTabFetch;
@@ -46,15 +46,6 @@ const isSameInvoicingListQuery = (a, b) => {
46
46
  a.sort?.dir === b.sort?.dir);
47
47
  };
48
48
  exports.isSameInvoicingListQuery = isSameInvoicingListQuery;
49
- /**
50
- * For a picker that searches client-side: reuse only a complete list fetched
51
- * with the picker's own query, else load every page of it.
52
- */
53
- const shouldFetchFullInvoicingList = (list, pickerFilters, cacheOverride) => cacheOverride ||
54
- list.fetchState !== 'Completed' ||
55
- list.nextCursor != null ||
56
- !(0, exports.isSameInvoicingListQuery)({ filters: list.filters, sort: list.sort }, { filters: pickerFilters });
57
- exports.shouldFetchFullInvoicingList = shouldFetchFullInvoicingList;
58
49
  /**
59
50
  * Fetch a tab that is empty or failed; top up one that holds less than a page
60
51
  * while the server says there is more; leave a full or complete one cached.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.2.84",
3
+ "version": "5.2.86",
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",