@zeniai/client-epic-state 5.1.91 → 5.1.92-beta0NB

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 (93) hide show
  1. package/lib/entity/accountRecon/accountReconReducer.js +4 -0
  2. package/lib/entity/accountRecon/accountReconState.d.ts +4 -1
  3. package/lib/entity/accountRecon/accountReconState.js +1 -0
  4. package/lib/entity/snackbar/snackbarApiError.d.ts +8 -0
  5. package/lib/entity/snackbar/snackbarApiError.js +15 -0
  6. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  7. package/lib/entity/snackbar/snackbarTypes.js +1 -0
  8. package/lib/epic.d.ts +4 -1
  9. package/lib/epic.js +4 -1
  10. package/lib/esm/entity/accountRecon/accountReconReducer.js +4 -0
  11. package/lib/esm/entity/accountRecon/accountReconState.js +1 -0
  12. package/lib/esm/entity/snackbar/snackbarApiError.js +11 -0
  13. package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
  14. package/lib/esm/epic.js +4 -1
  15. package/lib/esm/index.js +4 -4
  16. package/lib/esm/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +43 -0
  17. package/lib/esm/view/expenseAutomationView/epics/accountRecon/parseCombinedStatementEpic.js +31 -0
  18. package/lib/esm/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +15 -18
  19. package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.js +68 -0
  20. package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +10 -10
  21. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  22. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +8 -2
  23. package/lib/esm/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +20 -5
  24. package/lib/esm/view/expenseAutomationView/payload/reconciliationPayload.js +135 -0
  25. package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +119 -16
  26. package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +28 -7
  27. package/lib/esm/view/expenseAutomationView/selectors/statementParseViewSelector.js +43 -10
  28. package/lib/esm/view/expenseAutomationView/types/reconciliationViewState.js +15 -1
  29. package/lib/esm/view/invoicing/createCreditNote/createCreditNoteEpic.js +2 -0
  30. package/lib/esm/view/invoicing/createInvoice/createInvoiceEpic.js +2 -0
  31. package/lib/esm/view/invoicing/discountAction/discountActionEpic.js +6 -3
  32. package/lib/esm/view/invoicing/dunningAction/dunningActionEpic.js +6 -3
  33. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +5 -4
  34. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +3 -0
  35. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +2 -0
  36. package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +2 -0
  37. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +2 -0
  38. package/lib/esm/view/invoicing/invoiceAction/invoiceActionEpic.js +7 -3
  39. package/lib/esm/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +2 -0
  40. package/lib/esm/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +2 -0
  41. package/lib/esm/view/invoicing/issueCreditNote/issueCreditNoteEpic.js +2 -0
  42. package/lib/esm/view/invoicing/recordPayment/recordPaymentEpic.js +3 -0
  43. package/lib/esm/view/invoicing/settingsView/settingsViewEpics.js +6 -3
  44. package/lib/esm/view/invoicing/settingsView/settingsViewSelector.js +52 -0
  45. package/lib/esm/view/invoicing/subscriptionAction/subscriptionActionEpic.js +6 -3
  46. package/lib/esm/view/vendorTabView/vendorTabViewReducer.js +1 -1
  47. package/lib/index.d.ts +7 -7
  48. package/lib/index.js +51 -46
  49. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.d.ts +34 -0
  50. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +47 -0
  51. package/lib/view/expenseAutomationView/epics/accountRecon/parseCombinedStatementEpic.d.ts +26 -0
  52. package/lib/view/expenseAutomationView/epics/accountRecon/parseCombinedStatementEpic.js +35 -0
  53. package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.d.ts +21 -1
  54. package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +15 -18
  55. package/lib/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.d.ts +27 -0
  56. package/lib/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.js +72 -0
  57. package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +10 -10
  58. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.d.ts +1 -1
  59. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  60. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +7 -1
  61. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.d.ts +1 -0
  62. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +20 -4
  63. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  64. package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +109 -4
  65. package/lib/view/expenseAutomationView/payload/reconciliationPayload.js +143 -0
  66. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +32 -4
  67. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +121 -18
  68. package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.d.ts +5 -1
  69. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.d.ts +3 -1
  70. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -7
  71. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.d.ts +3 -2
  72. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.js +44 -10
  73. package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +74 -1
  74. package/lib/view/expenseAutomationView/types/reconciliationViewState.js +19 -1
  75. package/lib/view/invoicing/createCreditNote/createCreditNoteEpic.js +2 -0
  76. package/lib/view/invoicing/createInvoice/createInvoiceEpic.js +2 -0
  77. package/lib/view/invoicing/discountAction/discountActionEpic.js +5 -2
  78. package/lib/view/invoicing/dunningAction/dunningActionEpic.js +5 -2
  79. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +5 -4
  80. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +3 -0
  81. package/lib/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +2 -0
  82. package/lib/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +2 -0
  83. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +2 -0
  84. package/lib/view/invoicing/invoiceAction/invoiceActionEpic.js +6 -2
  85. package/lib/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +2 -0
  86. package/lib/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +2 -0
  87. package/lib/view/invoicing/issueCreditNote/issueCreditNoteEpic.js +2 -0
  88. package/lib/view/invoicing/recordPayment/recordPaymentEpic.js +3 -0
  89. package/lib/view/invoicing/settingsView/settingsViewEpics.js +5 -2
  90. package/lib/view/invoicing/settingsView/settingsViewSelector.d.ts +41 -1
  91. package/lib/view/invoicing/settingsView/settingsViewSelector.js +55 -1
  92. package/lib/view/invoicing/subscriptionAction/subscriptionActionEpic.js +5 -2
  93. package/package.json +1 -1
@@ -4,6 +4,7 @@ exports.createCreditNoteEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const creditNoteReducer_1 = require("../../../entity/invoicing/creditNote/creditNoteReducer");
7
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
7
8
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
8
9
  const responsePayload_1 = require("../../../responsePayload");
9
10
  const createCreditNotePayload_1 = require("./createCreditNotePayload");
@@ -32,6 +33,7 @@ const createCreditNoteEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, op
32
33
  messageSection: 'invoicing_credit_note_saved',
33
34
  messageText: 'failed',
34
35
  type: 'error',
36
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
35
37
  }),
36
38
  ]);
37
39
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -6,6 +6,7 @@ const operators_1 = require("rxjs/operators");
6
6
  const addressReducer_1 = require("../../../entity/address/addressReducer");
7
7
  const invoicePayload_1 = require("../../../entity/invoicing/invoice/invoicePayload");
8
8
  const invoiceReducer_1 = require("../../../entity/invoicing/invoice/invoiceReducer");
9
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
9
10
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
10
11
  const responsePayload_1 = require("../../../responsePayload");
11
12
  const invoiceListReducer_1 = require("../invoiceList/invoiceListReducer");
@@ -39,6 +40,7 @@ const createInvoiceEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, oper
39
40
  messageSection: 'invoicing_invoice_saved',
40
41
  messageText: 'failed',
41
42
  type: 'error',
43
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
42
44
  }),
43
45
  ]);
44
46
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -4,6 +4,7 @@ exports.runInvoicingDiscountActionEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const couponReducer_1 = require("../../../entity/invoicing/coupon/couponReducer");
7
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
7
8
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
8
9
  const responsePayload_1 = require("../../../responsePayload");
9
10
  const discountActionReducer_1 = require("./discountActionReducer");
@@ -17,13 +18,15 @@ const runInvoicingDiscountActionEpic = (actions$, _state$, zeniAPI) => actions$.
17
18
  const { action: kind, id } = action.payload;
18
19
  const requestBody = { action: kind };
19
20
  const snackbarSection = SNACKBAR_SECTION_BY_KIND[kind];
20
- const snackbar = (messageText) => snackbarSection == null
21
+ /** `status` surfaces the platform's error text; omit it to keep the generic copy. */
22
+ const snackbar = (messageText, status) => snackbarSection == null
21
23
  ? []
22
24
  : [
23
25
  (0, snackbarReducer_1.openSnackbar)({
24
26
  messageSection: snackbarSection,
25
27
  messageText,
26
28
  type: messageText === 'success' ? 'success' : 'error',
29
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(status),
27
30
  }),
28
31
  ];
29
32
  const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/discounts/${encodeURIComponent(id)}/actions`;
@@ -42,7 +45,7 @@ const runInvoicingDiscountActionEpic = (actions$, _state$, zeniAPI) => actions$.
42
45
  error: response.status,
43
46
  id,
44
47
  }),
45
- ...snackbar('failed'),
48
+ ...snackbar('failed', response.status),
46
49
  ]);
47
50
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
48
51
  (0, discountActionReducer_1.runInvoicingDiscountActionFailure)({
@@ -4,6 +4,7 @@ exports.runInvoicingDunningActionEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const dunningCaseReducer_1 = require("../../../entity/invoicing/dunningCase/dunningCaseReducer");
7
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
7
8
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
8
9
  const responsePayload_1 = require("../../../responsePayload");
9
10
  const dunningActionReducer_1 = require("./dunningActionReducer");
@@ -18,13 +19,15 @@ const SNACKBAR_SECTION_BY_KIND = {
18
19
  const runInvoicingDunningActionEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(dunningActionReducer_1.runInvoicingDunningAction.match), (0, operators_1.mergeMap)((action) => {
19
20
  const { action: kind, body, id } = action.payload;
20
21
  const snackbarSection = SNACKBAR_SECTION_BY_KIND[kind];
21
- const snackbar = (messageText) => snackbarSection == null
22
+ /** `status` surfaces the platform's error text; omit it to keep the generic copy. */
23
+ const snackbar = (messageText, status) => snackbarSection == null
22
24
  ? []
23
25
  : [
24
26
  (0, snackbarReducer_1.openSnackbar)({
25
27
  messageSection: snackbarSection,
26
28
  messageText,
27
29
  type: messageText === 'success' ? 'success' : 'error',
30
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(status),
28
31
  }),
29
32
  ];
30
33
  const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/dunning/${encodeURIComponent(id)}/${kind}`;
@@ -43,7 +46,7 @@ const runInvoicingDunningActionEpic = (actions$, _state$, zeniAPI) => actions$.p
43
46
  error: response.status,
44
47
  id,
45
48
  }),
46
- ...snackbar('failed'),
49
+ ...snackbar('failed', response.status),
47
50
  ]);
48
51
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
49
52
  (0, dunningActionReducer_1.runInvoicingDunningActionFailure)({
@@ -83,6 +83,8 @@ const buildSubFamilyPayload = (localData, subFamily, clearEmptyValues) => {
83
83
  }
84
84
  return payload;
85
85
  };
86
+ /** `unit` is the item's unit of measure, not a currency; `CURRENCY_CODE` above prices sub-families. */
87
+ const DEFAULT_CATALOG_ITEM_UNIT = 'USD';
86
88
  /**
87
89
  * Build the parent catalog-item request body from the form draft. Creates omit
88
90
  * both parent and sub-family IDs; edits retain returned sub-family IDs.
@@ -104,10 +106,9 @@ const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate) => {
104
106
  if (description != null) {
105
107
  itemPayload.description = description;
106
108
  }
107
- const unit = trimOrUndefined(localData.unit);
108
- if (unit != null) {
109
- itemPayload.unit = unit;
110
- }
109
+ // The form no longer collects a unit; an item that already has one keeps it.
110
+ itemPayload.unit =
111
+ trimOrUndefined(localData.unit) ?? DEFAULT_CATALOG_ITEM_UNIT;
111
112
  if (localData.itemApplicability === 'restricted' &&
112
113
  localData.applicableItems.length > 0) {
113
114
  itemPayload.applicable_items = localData.applicableItems;
@@ -5,6 +5,7 @@ const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const planReducer_1 = require("../../../entity/invoicing/plan/planReducer");
7
7
  const productReducer_1 = require("../../../entity/invoicing/product/productReducer");
8
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
8
9
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
9
10
  const responsePayload_1 = require("../../../responsePayload");
10
11
  const invoicingCatalogListViewReducer_1 = require("../invoicingCatalogListView/invoicingCatalogListViewReducer");
@@ -48,6 +49,7 @@ const saveInvoicingCatalogItemEpic = (actions$, state$, zeniAPI) => actions$.pip
48
49
  messageSection: 'invoicing_catalog_item_saved',
49
50
  messageText: 'failed',
50
51
  type: 'error',
52
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(failedProductResponse.status),
51
53
  }),
52
54
  ]);
53
55
  }
@@ -97,6 +99,7 @@ const saveInvoicingCatalogItemEpic = (actions$, state$, zeniAPI) => actions$.pip
97
99
  messageSection: 'invoicing_catalog_item_saved',
98
100
  messageText: 'failed',
99
101
  type: 'error',
102
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
100
103
  }),
101
104
  ]);
102
105
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -4,6 +4,7 @@ exports.saveInvoicingCouponEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const couponReducer_1 = require("../../../entity/invoicing/coupon/couponReducer");
7
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
7
8
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
8
9
  const responsePayload_1 = require("../../../responsePayload");
9
10
  const couponViewReducer_1 = require("../couponView/couponViewReducer");
@@ -60,6 +61,7 @@ const saveInvoicingCouponEpic = (actions$, state$, zeniAPI) => actions$.pipe((0,
60
61
  messageSection: 'invoicing_coupon_saved',
61
62
  messageText: 'failed',
62
63
  type: 'error',
64
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
63
65
  }),
64
66
  ]);
65
67
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -6,6 +6,7 @@ const operators_1 = require("rxjs/operators");
6
6
  const addressReducer_1 = require("../../../entity/address/addressReducer");
7
7
  const invoicingCustomerPayload_1 = require("../../../entity/invoicing/invoicingCustomer/invoicingCustomerPayload");
8
8
  const invoicingCustomerReducer_1 = require("../../../entity/invoicing/invoicingCustomer/invoicingCustomerReducer");
9
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
9
10
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
10
11
  const responsePayload_1 = require("../../../responsePayload");
11
12
  const addressViewReducer_1 = require("../../addressView/addressViewReducer");
@@ -62,6 +63,7 @@ const saveInvoicingCustomerEpic = (actions$, state$, zeniAPI) => actions$.pipe((
62
63
  messageSection: 'invoicing_customer_saved',
63
64
  messageText: 'failed',
64
65
  type: 'error',
66
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
65
67
  }),
66
68
  ]);
67
69
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -6,6 +6,7 @@ const operators_1 = require("rxjs/operators");
6
6
  const addressReducer_1 = require("../../../entity/address/addressReducer");
7
7
  const invoicingSubscriptionPayload_1 = require("../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionPayload");
8
8
  const invoicingSubscriptionReducer_1 = require("../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionReducer");
9
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
9
10
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
10
11
  const responsePayload_1 = require("../../../responsePayload");
11
12
  const addressViewReducer_1 = require("../../addressView/addressViewReducer");
@@ -48,6 +49,7 @@ const saveInvoicingSubscriptionEpic = (actions$, state$, zeniAPI) => actions$.pi
48
49
  messageSection: 'invoicing_subscription_saved',
49
50
  messageText: 'failed',
50
51
  type: 'error',
52
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
51
53
  }),
52
54
  ];
53
55
  }
@@ -6,6 +6,7 @@ const operators_1 = require("rxjs/operators");
6
6
  const addressReducer_1 = require("../../../entity/address/addressReducer");
7
7
  const invoicePayload_1 = require("../../../entity/invoicing/invoice/invoicePayload");
8
8
  const invoiceReducer_1 = require("../../../entity/invoicing/invoice/invoiceReducer");
9
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
9
10
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
10
11
  const responsePayload_1 = require("../../../responsePayload");
11
12
  const invoiceActionReducer_1 = require("./invoiceActionReducer");
@@ -19,13 +20,15 @@ const runInvoicingInvoiceActionEpic = (actions$, _state$, zeniAPI) => actions$.p
19
20
  action.payload.action !== 'issue-credit-note'), (0, operators_1.mergeMap)((action) => {
20
21
  const { action: kind, body, invoiceId } = action.payload;
21
22
  const snackbarSection = SNACKBAR_SECTION_BY_KIND[kind];
22
- const snackbar = (messageText) => snackbarSection == null
23
+ /** `status` surfaces the platform's error text; omit it to keep the generic copy. */
24
+ const snackbar = (messageText, status) => snackbarSection == null
23
25
  ? []
24
26
  : [
25
27
  (0, snackbarReducer_1.openSnackbar)({
26
28
  messageSection: snackbarSection,
27
29
  messageText,
28
30
  type: messageText === 'success' ? 'success' : 'error',
31
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(status),
29
32
  }),
30
33
  ];
31
34
  const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/invoices/${encodeURIComponent(invoiceId)}/${kind}`;
@@ -45,7 +48,7 @@ const runInvoicingInvoiceActionEpic = (actions$, _state$, zeniAPI) => actions$.p
45
48
  error: response.status,
46
49
  invoiceId,
47
50
  }),
48
- ...snackbar('failed'),
51
+ ...snackbar('failed', response.status),
49
52
  ]);
50
53
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
51
54
  (0, invoiceActionReducer_1.runInvoicingInvoiceActionFailure)({
@@ -84,6 +87,7 @@ const updateInvoicingInvoiceEpic = (actions$, _state$, zeniAPI) => actions$.pipe
84
87
  messageSection: 'invoicing_invoice_saved',
85
88
  messageText: 'failed',
86
89
  type: 'error',
90
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
87
91
  }),
88
92
  ]);
89
93
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.retryInvoicingQboSyncTaskEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const snackbarApiError_1 = require("../../../../entity/snackbar/snackbarApiError");
6
7
  const snackbarReducer_1 = require("../../../../entity/snackbar/snackbarReducer");
7
8
  const responsePayload_1 = require("../../../../responsePayload");
8
9
  const invoicingQboViewReducer_1 = require("../invoicingQboViewReducer");
@@ -31,6 +32,7 @@ const retryInvoicingQboSyncTaskEpic = (actions$, _state$, zeniAPI) => actions$.p
31
32
  messageSection: 'invoicing_qbo_sync_health_retry',
32
33
  messageText: 'failed',
33
34
  type: 'error',
35
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
34
36
  }),
35
37
  ]);
36
38
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.startInvoicingQboBackfillEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const snackbarApiError_1 = require("../../../../entity/snackbar/snackbarApiError");
6
7
  const snackbarReducer_1 = require("../../../../entity/snackbar/snackbarReducer");
7
8
  const responsePayload_1 = require("../../../../responsePayload");
8
9
  const invoicingQboViewReducer_1 = require("../invoicingQboViewReducer");
@@ -30,6 +31,7 @@ const startInvoicingQboBackfillEpic = (actions$, _state$, zeniAPI) => actions$.p
30
31
  messageSection: 'invoicing_qbo_backfill',
31
32
  messageText: 'failed',
32
33
  type: 'error',
34
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
33
35
  }),
34
36
  ]);
35
37
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -4,6 +4,7 @@ exports.issueCreditNoteEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const creditNoteReducer_1 = require("../../../entity/invoicing/creditNote/creditNoteReducer");
7
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
7
8
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
8
9
  const responsePayload_1 = require("../../../responsePayload");
9
10
  const invoiceDetailReducer_1 = require("../invoiceDetail/invoiceDetailReducer");
@@ -35,6 +36,7 @@ const issueCreditNoteEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, ope
35
36
  messageSection: 'invoicing_credit_note_saved',
36
37
  messageText: 'failed',
37
38
  type: 'error',
39
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
38
40
  }),
39
41
  ]);
40
42
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -5,6 +5,7 @@ const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const invoiceReducer_1 = require("../../../entity/invoicing/invoice/invoiceReducer");
7
7
  const invoicingTransactionReducer_1 = require("../../../entity/invoicing/invoicingTransaction/invoicingTransactionReducer");
8
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
8
9
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
9
10
  const responsePayload_1 = require("../../../responsePayload");
10
11
  const invoiceDetailReducer_1 = require("../invoiceDetail/invoiceDetailReducer");
@@ -43,6 +44,7 @@ const recordPaymentEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, opera
43
44
  messageSection: 'invoicing_payment_recorded',
44
45
  messageText: 'failed',
45
46
  type: 'error',
47
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
46
48
  }),
47
49
  ]);
48
50
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -85,6 +87,7 @@ const recordPaymentEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, opera
85
87
  messageSection: 'invoicing_payment_recorded',
86
88
  messageText: 'failed',
87
89
  type: 'error',
90
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(response.status),
88
91
  }),
89
92
  ]);
90
93
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
@@ -4,6 +4,7 @@ exports.saveInvoicingSettingsEpic = exports.disconnectInvoicingStripeEpic = expo
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const addressReducer_1 = require("../../../entity/address/addressReducer");
7
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
7
8
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
8
9
  const responsePayload_1 = require("../../../responsePayload");
9
10
  const settingsViewReducer_1 = require("./settingsViewReducer");
@@ -65,13 +66,15 @@ exports.disconnectInvoicingStripeEpic = disconnectInvoicingStripeEpic;
65
66
  const saveInvoicingSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(settingsViewReducer_1.saveInvoicingSettings.match), (0, operators_1.mergeMap)((action) => {
66
67
  const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/settings`;
67
68
  const { settings, snackbarSection } = action.payload;
68
- const snackbar = (messageText) => snackbarSection == null
69
+ /** `status` surfaces the platform's error text; omit it to keep the generic copy. */
70
+ const snackbar = (messageText, status) => snackbarSection == null
69
71
  ? []
70
72
  : [
71
73
  (0, snackbarReducer_1.openSnackbar)({
72
74
  messageSection: snackbarSection,
73
75
  messageText,
74
76
  type: messageText === 'success' ? 'success' : 'error',
77
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(status),
75
78
  }),
76
79
  ];
77
80
  return zeniAPI
@@ -85,7 +88,7 @@ const saveInvoicingSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(
85
88
  }
86
89
  return (0, rxjs_1.from)([
87
90
  (0, settingsViewReducer_1.saveInvoicingSettingsFailure)(response.status),
88
- ...snackbar('failed'),
91
+ ...snackbar('failed', response.status),
89
92
  ]);
90
93
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
91
94
  (0, settingsViewReducer_1.saveInvoicingSettingsFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Save settings REST API call errored out ' +
@@ -1,7 +1,8 @@
1
1
  import { FetchState, FetchStateAndError } from '../../../commonStateTypes/common';
2
- import { InvoicingNamedOption, InvoicingSettingsPayload } from '../../../entity/invoicing/invoicingCommonPayload';
2
+ import { InvoicingNamedOption, InvoicingQboAccountMappingKindOption, InvoicingSettingsPayload } from '../../../entity/invoicing/invoicingCommonPayload';
3
3
  import { RootState } from '../../../reducer';
4
4
  import { ZeniAPIStatus } from '../../../responsePayload';
5
+ import { InvoicingOnboardingStatus } from '../invoicingConfigView/invoicingConfigViewPayload';
5
6
  import { InvoicingBrandingFormLocalData } from './invoicingBrandingFormConfig';
6
7
  /**
7
8
  * Shared primitive: the raw invoicing settings. Consumed internally by other
@@ -27,6 +28,45 @@ export interface InvoicingSettingsView {
27
28
  * Stripe-connect fetch state.
28
29
  */
29
30
  export declare const getInvoicingSettingsView: (state: RootState) => InvoicingSettingsView;
31
+ export interface InvoicingEnablePrerequisites {
32
+ canEnable: boolean;
33
+ isQboConfigured: boolean;
34
+ isStripeConnected: boolean;
35
+ }
36
+ /**
37
+ * Gates the Enable Invoicing action: payments must be able to land (Stripe
38
+ * connected *and* accepting charges) and the QBO accounting step must be
39
+ * finished, so an enabled tenant can always book what it invoices.
40
+ *
41
+ * Deliberately not part of `deriveInvoicingOnboardingStatus`, which routes the
42
+ * module off the config flags alone. Folding these in there would (a) demote a
43
+ * live tenant to the settings tree the moment an integration broke, stranding
44
+ * its existing invoices, and (b) deadlock the route gate, which fetches only the
45
+ * config — never the settings or QBO connection these read.
46
+ */
47
+ export declare function deriveInvoicingEnablePrerequisites(settings: InvoicingSettingsPayload | undefined, isQboConnected: boolean, qboAccountMappingKindOptions: InvoicingQboAccountMappingKindOption[]): InvoicingEnablePrerequisites;
48
+ export interface InvoicingSettingsHubView {
49
+ canEnableInvoicing: boolean;
50
+ isEnablingInvoicing: boolean;
51
+ isQboConfigured: boolean;
52
+ isStripeConnected: boolean;
53
+ status?: InvoicingOnboardingStatus;
54
+ }
55
+ /**
56
+ * The settings hub's composite of everything it derives from the store: whether
57
+ * to offer Enable Invoicing at all, the in-flight flag for that action, and the
58
+ * two integration prerequisites kept separate so the hub can name the step still
59
+ * outstanding instead of showing a dead button.
60
+ *
61
+ * `canEnableInvoicing` folds in the onboarding step, so the screen does not need
62
+ * to re-check it: the footer is only offered mid-onboarding and only once both
63
+ * integrations are ready.
64
+ *
65
+ * Deliberately not folded into `getInvoicingConfigView`: that selector gates
66
+ * every invoicing route and stays a pure read of the config slice. The settings
67
+ * and QBO slices read here are only fetched once a settings screen is mounted.
68
+ */
69
+ export declare const getInvoicingSettingsHubView: (state: RootState) => InvoicingSettingsHubView;
30
70
  export interface InvoicingBrandingFormView {
31
71
  dateFormatOptions: InvoicingNamedOption[];
32
72
  localData: InvoicingBrandingFormLocalData;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getInvoicingBrandingFormView = exports.getInvoicingSettingsView = exports.getInvoicingSettingsFetchState = exports.getInvoicingSettings = void 0;
3
+ exports.getInvoicingBrandingFormView = exports.getInvoicingSettingsHubView = exports.getInvoicingSettingsView = exports.getInvoicingSettingsFetchState = exports.getInvoicingSettings = void 0;
4
+ exports.deriveInvoicingEnablePrerequisites = deriveInvoicingEnablePrerequisites;
5
+ const invoicingCommonPayload_1 = require("../../../entity/invoicing/invoicingCommonPayload");
4
6
  const addressViewSelector_1 = require("../../addressView/addressViewSelector");
5
7
  const invoicingConfigViewSelector_1 = require("../invoicingConfigView/invoicingConfigViewSelector");
6
8
  const invoicingBrandingFormConfig_1 = require("./invoicingBrandingFormConfig");
@@ -36,6 +38,58 @@ const getInvoicingSettingsView = (state) => {
36
38
  };
37
39
  };
38
40
  exports.getInvoicingSettingsView = getInvoicingSettingsView;
41
+ /**
42
+ * Gates the Enable Invoicing action: payments must be able to land (Stripe
43
+ * connected *and* accepting charges) and the QBO accounting step must be
44
+ * finished, so an enabled tenant can always book what it invoices.
45
+ *
46
+ * Deliberately not part of `deriveInvoicingOnboardingStatus`, which routes the
47
+ * module off the config flags alone. Folding these in there would (a) demote a
48
+ * live tenant to the settings tree the moment an integration broke, stranding
49
+ * its existing invoices, and (b) deadlock the route gate, which fetches only the
50
+ * config — never the settings or QBO connection these read.
51
+ */
52
+ function deriveInvoicingEnablePrerequisites(settings, isQboConnected, qboAccountMappingKindOptions) {
53
+ const isStripeConnected = settings?.stripe_connected === true &&
54
+ settings?.stripe_account?.charges_enabled === true;
55
+ const accountMappings = settings?.qbo?.account_mappings ?? undefined;
56
+ // An empty option list means the config has not landed yet — treating that as
57
+ // configured would let `every` pass vacuously and unlock the button early.
58
+ const isQboConfigured = isQboConnected &&
59
+ qboAccountMappingKindOptions.length > 0 &&
60
+ qboAccountMappingKindOptions.every((option) => (0, invoicingCommonPayload_1.getInvoicingQboAccountMappingId)(accountMappings, option.code) != null);
61
+ return {
62
+ canEnable: isStripeConnected && isQboConfigured,
63
+ isQboConfigured,
64
+ isStripeConnected,
65
+ };
66
+ }
67
+ /**
68
+ * The settings hub's composite of everything it derives from the store: whether
69
+ * to offer Enable Invoicing at all, the in-flight flag for that action, and the
70
+ * two integration prerequisites kept separate so the hub can name the step still
71
+ * outstanding instead of showing a dead button.
72
+ *
73
+ * `canEnableInvoicing` folds in the onboarding step, so the screen does not need
74
+ * to re-check it: the footer is only offered mid-onboarding and only once both
75
+ * integrations are ready.
76
+ *
77
+ * Deliberately not folded into `getInvoicingConfigView`: that selector gates
78
+ * every invoicing route and stays a pure read of the config slice. The settings
79
+ * and QBO slices read here are only fetched once a settings screen is mounted.
80
+ */
81
+ const getInvoicingSettingsHubView = (state) => {
82
+ const { enableState, qboAccountMappingKindOptions, status } = (0, invoicingConfigViewSelector_1.getInvoicingConfigView)(state);
83
+ const { canEnable, isQboConfigured, isStripeConnected } = deriveInvoicingEnablePrerequisites(state.invoicingSettingsViewState.settings, state.invoicingQboViewState.connection?.connected === true, qboAccountMappingKindOptions);
84
+ return {
85
+ canEnableInvoicing: status === 'settings' && canEnable,
86
+ isEnablingInvoicing: enableState.fetchState === 'In-Progress',
87
+ isQboConfigured,
88
+ isStripeConnected,
89
+ status,
90
+ };
91
+ };
92
+ exports.getInvoicingSettingsHubView = getInvoicingSettingsHubView;
39
93
  /**
40
94
  * Bundled view for the branding settings form: the draft `localData` (seeded
41
95
  * from the existing settings until the user edits), the business-address label
@@ -6,6 +6,7 @@ const operators_1 = require("rxjs/operators");
6
6
  const addressReducer_1 = require("../../../entity/address/addressReducer");
7
7
  const invoicingSubscriptionPayload_1 = require("../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionPayload");
8
8
  const invoicingSubscriptionReducer_1 = require("../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionReducer");
9
+ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
9
10
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
10
11
  const responsePayload_1 = require("../../../responsePayload");
11
12
  const subscriptionActionReducer_1 = require("./subscriptionActionReducer");
@@ -27,13 +28,15 @@ const runInvoicingSubscriptionActionEpic = (actions$, _state$, zeniAPI) => actio
27
28
  const { action: kind, body, id } = action.payload;
28
29
  const requestBody = { action: kind, ...(body ?? {}) };
29
30
  const snackbarSection = SNACKBAR_SECTION_BY_ACTION[kind];
30
- const snackbar = (messageText) => snackbarSection == null
31
+ /** `status` surfaces the platform's error text; omit it to keep the generic copy. */
32
+ const snackbar = (messageText, status) => snackbarSection == null
31
33
  ? []
32
34
  : [
33
35
  (0, snackbarReducer_1.openSnackbar)({
34
36
  messageSection: snackbarSection,
35
37
  messageText,
36
38
  type: messageText === 'success' ? 'success' : 'error',
39
+ variables: (0, snackbarApiError_1.apiErrorSnackbarVariables)(status),
37
40
  }),
38
41
  ];
39
42
  const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/subscriptions/${encodeURIComponent(id)}/actions`;
@@ -53,7 +56,7 @@ const runInvoicingSubscriptionActionEpic = (actions$, _state$, zeniAPI) => actio
53
56
  error: response.status,
54
57
  id,
55
58
  }),
56
- ...snackbar('failed'),
59
+ ...snackbar('failed', response.status),
57
60
  ]);
58
61
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
59
62
  (0, subscriptionActionReducer_1.runInvoicingSubscriptionActionFailure)({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.1.91",
3
+ "version": "5.1.92-beta0NB",
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",