@zeniai/client-epic-state 5.1.78-betaSI0 → 5.1.78

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 (110) hide show
  1. package/lib/entity/invoicing/invoicingCommonPayload.d.ts +42 -0
  2. package/lib/entity/invoicing/invoicingCommonPayload.js +66 -1
  3. package/lib/entity/tenant/clearAllEpic.d.ts +2 -1
  4. package/lib/entity/tenant/clearAllEpic.js +2 -0
  5. package/lib/epic.d.ts +2 -1
  6. package/lib/epic.js +7 -1
  7. package/lib/esm/entity/invoicing/invoicingCommonPayload.js +61 -0
  8. package/lib/esm/entity/tenant/clearAllEpic.js +2 -0
  9. package/lib/esm/epic.js +7 -1
  10. package/lib/esm/index.js +7 -4
  11. package/lib/esm/reducer.js +3 -0
  12. package/lib/esm/view/expenseAutomationView/epics/transactionCategorization/backgroundRefetchReviewTabEpic.js +0 -1
  13. package/lib/esm/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +0 -1
  14. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +11 -56
  15. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +1 -2
  16. package/lib/esm/view/invoicing/createCreditNote/createCreditNoteFormConfig.js +6 -1
  17. package/lib/esm/view/invoicing/createCreditNote/createCreditNotePayload.js +1 -8
  18. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/catalogDetailEditPayload.js +4 -5
  19. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +10 -11
  20. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/invoicingCatalogItemFormConfig.js +8 -10
  21. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewPayload.js +2 -2
  22. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewReducer.js +1 -1
  23. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.js +1 -1
  24. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewState.js +43 -1
  25. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +2 -5
  26. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.js +1 -2
  27. package/lib/esm/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +7 -1
  28. package/lib/esm/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.js +3 -0
  29. package/lib/esm/view/invoicing/invoicingQboView/epics/fetchInvoicingQboAccountsEpic.js +25 -0
  30. package/lib/esm/view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic.js +15 -0
  31. package/lib/esm/view/invoicing/invoicingQboView/epics/fetchInvoicingQboConnectionEpic.js +15 -0
  32. package/lib/esm/view/invoicing/invoicingQboView/epics/fetchInvoicingQboSyncHealthEpic.js +15 -0
  33. package/lib/esm/view/invoicing/invoicingQboView/epics/invoicingQboViewActionType.js +1 -0
  34. package/lib/esm/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +26 -0
  35. package/lib/esm/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +18 -0
  36. package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewPayload.js +47 -0
  37. package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewReducer.js +128 -0
  38. package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +20 -0
  39. package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewState.js +1 -0
  40. package/lib/esm/view/invoicing/issueCreditNote/issueCreditNotePayload.js +4 -11
  41. package/lib/esm/view/invoicing/recordPayment/recordPaymentFormConfig.js +0 -1
  42. package/lib/esm/view/invoicing/recordPayment/recordPaymentPayload.js +5 -14
  43. package/lib/index.d.ts +9 -4
  44. package/lib/index.js +66 -55
  45. package/lib/reducer.d.ts +3 -0
  46. package/lib/reducer.js +3 -0
  47. package/lib/view/expenseAutomationView/epics/transactionCategorization/backgroundRefetchReviewTabEpic.js +0 -1
  48. package/lib/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +0 -1
  49. package/lib/view/expenseAutomationView/payload/transactionCategorizationPayload.d.ts +0 -11
  50. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +1 -4
  51. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +12 -57
  52. package/lib/view/expenseAutomationView/selectorTypes/transactionsViewSelectorTypes.d.ts +0 -2
  53. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +1 -2
  54. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +0 -11
  55. package/lib/view/invoicing/createCreditNote/createCreditNoteFormConfig.js +6 -1
  56. package/lib/view/invoicing/createCreditNote/createCreditNotePayload.js +1 -8
  57. package/lib/view/invoicing/createCreditNote/createCreditNoteState.d.ts +3 -1
  58. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/catalogDetailEditPayload.d.ts +2 -1
  59. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/catalogDetailEditPayload.js +4 -5
  60. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +10 -11
  61. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewState.d.ts +10 -5
  62. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/invoicingCatalogItemFormConfig.js +8 -10
  63. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewPayload.js +2 -2
  64. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewReducer.js +3 -3
  65. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.js +2 -2
  66. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewState.d.ts +9 -2
  67. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewState.js +45 -0
  68. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +2 -5
  69. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState.d.ts +3 -1
  70. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.js +1 -2
  71. package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewPayload.d.ts +4 -1
  72. package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.d.ts +1 -1
  73. package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +6 -0
  74. package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.d.ts +4 -1
  75. package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.js +3 -0
  76. package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewState.d.ts +4 -1
  77. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboAccountsEpic.d.ts +6 -0
  78. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboAccountsEpic.js +29 -0
  79. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic.d.ts +6 -0
  80. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic.js +19 -0
  81. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboConnectionEpic.d.ts +6 -0
  82. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboConnectionEpic.js +19 -0
  83. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboSyncHealthEpic.d.ts +6 -0
  84. package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboSyncHealthEpic.js +19 -0
  85. package/lib/view/invoicing/invoicingQboView/epics/invoicingQboViewActionType.d.ts +2 -0
  86. package/lib/view/invoicing/invoicingQboView/epics/invoicingQboViewActionType.js +2 -0
  87. package/lib/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.d.ts +6 -0
  88. package/lib/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +30 -0
  89. package/lib/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.d.ts +6 -0
  90. package/lib/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +22 -0
  91. package/lib/view/invoicing/invoicingQboView/invoicingQboViewPayload.d.ts +79 -0
  92. package/lib/view/invoicing/invoicingQboView/invoicingQboViewPayload.js +52 -0
  93. package/lib/view/invoicing/invoicingQboView/invoicingQboViewReducer.d.ts +25 -0
  94. package/lib/view/invoicing/invoicingQboView/invoicingQboViewReducer.js +132 -0
  95. package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.d.ts +21 -0
  96. package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +24 -0
  97. package/lib/view/invoicing/invoicingQboView/invoicingQboViewState.d.ts +14 -0
  98. package/lib/view/invoicing/invoicingQboView/invoicingQboViewState.js +2 -0
  99. package/lib/view/invoicing/issueCreditNote/issueCreditNotePayload.js +4 -11
  100. package/lib/view/invoicing/issueCreditNote/issueCreditNoteState.d.ts +3 -2
  101. package/lib/view/invoicing/recordPayment/recordPaymentFormConfig.js +0 -1
  102. package/lib/view/invoicing/recordPayment/recordPaymentPayload.js +5 -14
  103. package/lib/view/invoicing/recordPayment/recordPaymentState.d.ts +4 -2
  104. package/package.json +1 -1
  105. package/lib/esm/view/expenseAutomationView/types/transactionGroup.js +0 -21
  106. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/invoicingCouponFormConfig.js +0 -44
  107. package/lib/view/expenseAutomationView/types/transactionGroup.d.ts +0 -21
  108. package/lib/view/expenseAutomationView/types/transactionGroup.js +0 -25
  109. package/lib/view/invoicing/editInvoicingCouponDetailView/invoicingCouponFormConfig.d.ts +0 -5
  110. package/lib/view/invoicing/editInvoicingCouponDetailView/invoicingCouponFormConfig.js +0 -48
@@ -44,11 +44,12 @@ export const isTieredCatalogPricingModel = (model) => ['tiered', 'volume', 'stai
44
44
  export const blankInvoicingCatalogTier = (startingUnit = '1') => ({
45
45
  endingUnit: '',
46
46
  packageSize: '',
47
- price: '',
48
47
  pricingType: 'per_unit',
49
48
  startingUnit,
50
49
  });
51
50
  export const blankInvoicingCatalogSubFamily = () => ({
51
+ accountingCategory: '',
52
+ accountingCode: '',
52
53
  billingCycles: '',
53
54
  description: '',
54
55
  freeQuantity: '0',
@@ -58,12 +59,12 @@ export const blankInvoicingCatalogSubFamily = () => ({
58
59
  name: '',
59
60
  period: '1',
60
61
  periodUnit: 'month',
61
- priceDollars: '',
62
62
  priceCode: '',
63
63
  pricingModel: 'flat_fee',
64
64
  prorationType: 'site_default',
65
65
  showDescriptionInInvoices: true,
66
66
  showDescriptionInQuotes: true,
67
+ sku: '',
67
68
  tiers: [blankInvoicingCatalogTier('1')],
68
69
  trialEndAction: 'site_default',
69
70
  trialPeriod: '',
@@ -76,7 +77,10 @@ export const invoicingProductToCatalogItemFormSubFamily = (product) => {
76
77
  }
77
78
  return {
78
79
  ...base,
80
+ accountingCategory: product.accountingDetail?.accountingCategory1 ?? '',
81
+ accountingCode: product.accountingDetail?.accountingCode ?? '',
79
82
  billingCycles: product.billingCycles != null ? String(product.billingCycles) : '',
83
+ sku: product.accountingDetail?.sku ?? '',
80
84
  description: product.description ?? '',
81
85
  freeQuantity: product.freeQuantity != null ? String(product.freeQuantity) : '0',
82
86
  id: product.id,
@@ -85,7 +89,7 @@ export const invoicingProductToCatalogItemFormSubFamily = (product) => {
85
89
  name: product.name ?? '',
86
90
  period: product.period != null ? String(product.period) : '1',
87
91
  periodUnit: product.periodUnit ?? 'month',
88
- priceDollars: product.price != null ? String(product.price.amount) : '',
92
+ priceDollars: product.price,
89
93
  priceCode: product.priceCode ?? '',
90
94
  pricingModel: product.pricingModel ?? 'flat_fee',
91
95
  prorationType: product.prorationType ?? 'site_default',
@@ -95,7 +99,7 @@ export const invoicingProductToCatalogItemFormSubFamily = (product) => {
95
99
  ? product.tiers.map((tier) => ({
96
100
  endingUnit: tier.endingUnit != null ? String(tier.endingUnit) : '',
97
101
  packageSize: tier.packageSize != null ? String(tier.packageSize) : '',
98
- price: String(tier.price.amount),
102
+ price: tier.price,
99
103
  pricingType: tier.pricingType ?? 'per_unit',
100
104
  startingUnit: String(tier.startingUnit ?? 1),
101
105
  }))
@@ -106,8 +110,6 @@ export const invoicingProductToCatalogItemFormSubFamily = (product) => {
106
110
  };
107
111
  };
108
112
  export const initialInvoicingCatalogItemFormLocalData = {
109
- accountingCategory: '',
110
- accountingCode: '',
111
113
  applicableItems: [],
112
114
  catalogType: 'plan',
113
115
  description: '',
@@ -115,7 +117,6 @@ export const initialInvoicingCatalogItemFormLocalData = {
115
117
  itemApplicability: 'all',
116
118
  name: '',
117
119
  productCode: '',
118
- sku: '',
119
120
  subFamilies: [blankInvoicingCatalogSubFamily()],
120
121
  unit: '',
121
122
  };
@@ -136,8 +137,6 @@ export const entityToInvoicingCatalogItemFormLocalData = (item) => {
136
137
  ? 'addon'
137
138
  : 'plan';
138
139
  return {
139
- accountingCategory: plan.subFamilies?.[0]?.accountingDetail?.accountingCategory1 ?? '',
140
- accountingCode: plan.subFamilies?.[0]?.accountingDetail?.accountingCode ?? '',
141
140
  applicableItems: item.applicableItems ?? [],
142
141
  catalogType,
143
142
  description: item.description ?? '',
@@ -145,7 +144,6 @@ export const entityToInvoicingCatalogItemFormLocalData = (item) => {
145
144
  itemApplicability: item.itemApplicability ?? 'all',
146
145
  name: item.name ?? '',
147
146
  productCode: item.productCode ?? '',
148
- sku: plan.subFamilies?.[0]?.accountingDetail?.sku ?? '',
149
147
  subFamilies: plan?.subFamilies != null && plan.subFamilies.length > 0
150
148
  ? plan.subFamilies.map(invoicingProductToCatalogItemFormSubFamily)
151
149
  : [invoicingProductToCatalogItemFormSubFamily()],
@@ -22,8 +22,8 @@ export const localDataToSaveInvoicingCouponPayload = (localData, isCreate) => {
22
22
  data.discount_percentage = Number(localData.discountPercentage);
23
23
  }
24
24
  if (localData.discountType === 'fixed_amount') {
25
- if (localData.discountAmount.trim() !== '') {
26
- data.discount_amount = Number(localData.discountAmount);
25
+ if (localData.discountAmount != null) {
26
+ data.discount_amount = localData.discountAmount.amount;
27
27
  }
28
28
  data.currency_code = 'USD';
29
29
  }
@@ -1,5 +1,5 @@
1
1
  import { createSlice } from '@reduxjs/toolkit';
2
- import { initialInvoicingCouponFormLocalData } from './invoicingCouponFormConfig';
2
+ import { initialInvoicingCouponFormLocalData, } from './editInvoicingCouponDetailViewState';
3
3
  export const initialState = {
4
4
  fetchState: 'Not-Started',
5
5
  error: undefined,
@@ -1,6 +1,6 @@
1
1
  import { INVOICING_COUPON_APPLY_ON_OPTIONS, INVOICING_COUPON_DURATION_TYPE_OPTIONS, INVOICING_COUPON_PERIOD_UNIT_OPTIONS, INVOICING_DISCOUNT_TYPE_OPTIONS, } from '../../../entity/invoicing/coupon/couponConstants';
2
2
  import { getInvoicingCouponById } from '../../../entity/invoicing/coupon/couponSelector';
3
- import { entityToInvoicingCouponFormLocalData } from './invoicingCouponFormConfig';
3
+ import { entityToInvoicingCouponFormLocalData, } from './editInvoicingCouponDetailViewState';
4
4
  /**
5
5
  * Bundled view for the discount create/edit form: the save fetch state/error,
6
6
  * the id of the coupon last saved, and — when a `couponId` is passed (edit
@@ -1 +1,43 @@
1
- export {};
1
+ export const initialInvoicingCouponFormLocalData = {
2
+ applyOn: 'invoice_amount',
3
+ couponCode: '',
4
+ couponId: '',
5
+ discountPercentage: '',
6
+ discountQuantity: '',
7
+ discountType: 'percentage',
8
+ durationType: 'one_time',
9
+ invoiceName: '',
10
+ invoiceNotes: '',
11
+ maxRedemptions: '',
12
+ name: '',
13
+ period: '',
14
+ periodUnit: 'month',
15
+ validFrom: '',
16
+ validTill: '',
17
+ };
18
+ /** Seed the form draft from an existing coupon entity (edit mode). */
19
+ export const entityToInvoicingCouponFormLocalData = (coupon) => {
20
+ if (coupon == null) {
21
+ return { ...initialInvoicingCouponFormLocalData };
22
+ }
23
+ return {
24
+ applyOn: coupon.applyOn ?? 'invoice_amount',
25
+ couponCode: coupon.couponCode ?? '',
26
+ couponId: coupon.id ?? '',
27
+ discountAmount: coupon.discountAmount,
28
+ discountPercentage: coupon.discountPercentage != null
29
+ ? String(coupon.discountPercentage)
30
+ : '',
31
+ discountQuantity: coupon.discountQuantity != null ? String(coupon.discountQuantity) : '',
32
+ discountType: coupon.discountType ?? 'percentage',
33
+ durationType: coupon.durationType ?? 'one_time',
34
+ invoiceName: coupon.invoiceName ?? '',
35
+ invoiceNotes: coupon.invoiceNotes ?? '',
36
+ maxRedemptions: coupon.maxRedemptions != null ? String(coupon.maxRedemptions) : '',
37
+ name: coupon.name ?? '',
38
+ period: coupon.period != null ? String(coupon.period) : '',
39
+ periodUnit: coupon.periodUnit ?? 'month',
40
+ validFrom: coupon.validFrom != null ? coupon.validFrom.format('YYYY-MM-DD') : '',
41
+ validTill: coupon.validTill != null ? coupon.validTill.format('YYYY-MM-DD') : '',
42
+ };
43
+ };
@@ -24,8 +24,7 @@ export const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingA
24
24
  quantity: 1,
25
25
  })),
26
26
  ];
27
- const setupFee = localData.setupFee.trim();
28
- const parsedSetupFee = Number.parseFloat(setupFee);
27
+ const setupFee = localData.setupFee?.amount;
29
28
  const poNumber = localData.poNumber.trim();
30
29
  const trialEnd = localData.trialEnd.trim();
31
30
  return {
@@ -35,9 +34,7 @@ export const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingA
35
34
  currency_code: localData.preferredCurrencyCode,
36
35
  customer_id: localData.customerId,
37
36
  subscription_items: items,
38
- ...(setupFee !== '' && !Number.isNaN(parsedSetupFee)
39
- ? { setup_fee: parsedSetupFee }
40
- : {}),
37
+ ...(setupFee != null ? { setup_fee: setupFee } : {}),
41
38
  ...(poNumber !== '' ? { po_number: poNumber } : {}),
42
39
  ...(trialEnd !== '' ? { trial_end: trialEnd } : {}),
43
40
  ...(localData.couponId !== '' ? { coupon_ids: [localData.couponId] } : {}),
@@ -44,7 +44,6 @@ export const initialInvoicingSubscriptionFormLocalData = {
44
44
  planQuantity: 1,
45
45
  poNumber: '',
46
46
  preferredCurrencyCode: 'USD',
47
- setupFee: '',
48
47
  trialEnd: '',
49
48
  };
50
49
  /** Seed the form draft from an existing subscription entity (edit mode). */
@@ -66,7 +65,7 @@ export const entityToInvoicingSubscriptionFormLocalData = (subscription) => {
66
65
  planQuantity: planItem?.quantity ?? 1,
67
66
  poNumber: subscription.poNumber ?? '',
68
67
  preferredCurrencyCode: subscription.currencyCode ?? 'USD',
69
- setupFee: '',
68
+ setupFee: subscription.setupFee,
70
69
  trialEnd: subscription.trialEnd != null
71
70
  ? subscription.trialEnd.format('YYYY-MM-DD')
72
71
  : '',
@@ -1,5 +1,5 @@
1
1
  import { createSlice } from '@reduxjs/toolkit';
2
- import { toAuditLogEntityRouteOption, toInvoicingCatalogItemLifecycleActionOption, toInvoicingCatalogProductLifecycleActionOption, toInvoicingDiscountLifecycleActionOption, toInvoicingDunningAction, toInvoicingNamedOption, toInvoicingSubscriptionEditFieldOption, toInvoicingSubscriptionLifecycleActionOption, } from '../../../entity/invoicing/invoicingCommonPayload';
2
+ import { toAuditLogEntityRouteOption, toInvoicingCatalogItemLifecycleActionOption, toInvoicingCatalogProductLifecycleActionOption, toInvoicingDiscountLifecycleActionOption, toInvoicingDunningAction, toInvoicingNamedOption, toInvoicingQboAccountMappingKindOption, toInvoicingSubscriptionEditFieldOption, toInvoicingSubscriptionLifecycleActionOption, } from '../../../entity/invoicing/invoicingCommonPayload';
3
3
  export const initialState = {
4
4
  fetchState: 'Not-Started',
5
5
  error: undefined,
@@ -18,6 +18,9 @@ export const initialState = {
18
18
  catalogItemLifecycleActionOptions: [],
19
19
  catalogProductLifecycleActionOptions: [],
20
20
  discountLifecycleActionOptions: [],
21
+ qboAccountMappingKindOptions: [],
22
+ qboCustomerMatchingOptions: [],
23
+ qboSyncStatusOptions: [],
21
24
  isInvoicingEnabled: undefined,
22
25
  isInvoicingTosAccepted: undefined,
23
26
  invoicingTosAcceptanceIp: undefined,
@@ -53,6 +56,9 @@ export function mapInvoicingConfigPayloadToState(payload) {
53
56
  catalogItemLifecycleActionOptions: (payload.catalog_item_lifecycle_action_options ?? []).map((option) => toInvoicingCatalogItemLifecycleActionOption(option)),
54
57
  catalogProductLifecycleActionOptions: (payload.catalog_product_lifecycle_action_options ?? []).map((option) => toInvoicingCatalogProductLifecycleActionOption(option)),
55
58
  discountLifecycleActionOptions: (payload.discount_lifecycle_action_options ?? []).map((option) => toInvoicingDiscountLifecycleActionOption(option)),
59
+ qboAccountMappingKindOptions: (payload.qbo_account_mapping_kind_options ?? []).map(toInvoicingQboAccountMappingKindOption),
60
+ qboCustomerMatchingOptions: (payload.qbo_customer_matching_options ?? []).map(toInvoicingNamedOption),
61
+ qboSyncStatusOptions: (payload.qbo_sync_status_options ?? []).map(toInvoicingNamedOption),
56
62
  isInvoicingEnabled: payload.is_invoicing_enabled,
57
63
  isInvoicingTosAccepted: payload.is_invoicing_tos_accepted,
58
64
  invoicingTosAcceptanceIp: payload.invoicing_tos_acceptance_ip ?? undefined,
@@ -23,6 +23,9 @@ export const getInvoicingConfigView = (state) => {
23
23
  catalogItemLifecycleActionOptions: configState.catalogItemLifecycleActionOptions,
24
24
  catalogProductLifecycleActionOptions: configState.catalogProductLifecycleActionOptions,
25
25
  discountLifecycleActionOptions: configState.discountLifecycleActionOptions,
26
+ qboAccountMappingKindOptions: configState.qboAccountMappingKindOptions,
27
+ qboCustomerMatchingOptions: configState.qboCustomerMatchingOptions,
28
+ qboSyncStatusOptions: configState.qboSyncStatusOptions,
26
29
  error: configState.error,
27
30
  fetchState: configState.fetchState,
28
31
  isInvoicingEnabled: configState.isInvoicingEnabled,
@@ -0,0 +1,25 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, map, mergeMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
+ import { mapInvoicingQboAccountOptions, } from '../invoicingQboViewPayload';
5
+ import { fetchInvoicingQboAccounts, updateInvoicingQboAccounts, updateInvoicingQboAccountsFailure, } from '../invoicingQboViewReducer';
6
+ export const fetchInvoicingQboAccountsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingQboAccounts.match), mergeMap((action) => {
7
+ const { accountTypes } = action.payload;
8
+ const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/accounts?account_types=${encodeURIComponent(accountTypes)}`;
9
+ return zeniAPI.getJSON(apiUrl).pipe(map((response) => {
10
+ if (isSuccessResponse(response)) {
11
+ return updateInvoicingQboAccounts({
12
+ accountTypes,
13
+ accounts: mapInvoicingQboAccountOptions(response.data?.accounts ?? []),
14
+ });
15
+ }
16
+ return updateInvoicingQboAccountsFailure({
17
+ accountTypes,
18
+ status: response.status,
19
+ });
20
+ }), catchError((error) => of(updateInvoicingQboAccountsFailure({
21
+ accountTypes,
22
+ status: createZeniAPIStatus('Unexpected Error', 'Fetch QBO accounts REST API call errored out ' +
23
+ JSON.stringify(error)),
24
+ }))));
25
+ }));
@@ -0,0 +1,15 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, map, switchMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
+ import { mapInvoicingQboAccountOptions, } from '../invoicingQboViewPayload';
5
+ import { fetchInvoicingQboClasses, updateInvoicingQboClasses, updateInvoicingQboClassesFailure, } from '../invoicingQboViewReducer';
6
+ export const fetchInvoicingQboClassesEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingQboClasses.match), switchMap(() => {
7
+ const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/classes`;
8
+ return zeniAPI.getJSON(apiUrl).pipe(map((response) => {
9
+ if (isSuccessResponse(response)) {
10
+ return updateInvoicingQboClasses(mapInvoicingQboAccountOptions(response.data?.accounts ?? []));
11
+ }
12
+ return updateInvoicingQboClassesFailure(response.status);
13
+ }), catchError((error) => of(updateInvoicingQboClassesFailure(createZeniAPIStatus('Unexpected Error', 'Fetch QBO classes REST API call errored out ' +
14
+ JSON.stringify(error))))));
15
+ }));
@@ -0,0 +1,15 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, map, switchMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
+ import { mapInvoicingQboConnection, } from '../invoicingQboViewPayload';
5
+ import { fetchInvoicingQboConnection, updateInvoicingQboConnection, updateInvoicingQboConnectionFailure, } from '../invoicingQboViewReducer';
6
+ export const fetchInvoicingQboConnectionEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingQboConnection.match), switchMap(() => {
7
+ const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/connection`;
8
+ return zeniAPI.getJSON(apiUrl).pipe(map((response) => {
9
+ if (isSuccessResponse(response)) {
10
+ return updateInvoicingQboConnection(mapInvoicingQboConnection(response.data ?? { connected: false }));
11
+ }
12
+ return updateInvoicingQboConnectionFailure(response.status);
13
+ }), catchError((error) => of(updateInvoicingQboConnectionFailure(createZeniAPIStatus('Unexpected Error', 'Fetch QBO connection REST API call errored out ' +
14
+ JSON.stringify(error))))));
15
+ }));
@@ -0,0 +1,15 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, map, switchMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
+ import { mapInvoicingQboSyncHealth, } from '../invoicingQboViewPayload';
5
+ import { fetchInvoicingQboSyncHealth, updateInvoicingQboSyncHealth, updateInvoicingQboSyncHealthFailure, } from '../invoicingQboViewReducer';
6
+ export const fetchInvoicingQboSyncHealthEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingQboSyncHealth.match), switchMap(() => {
7
+ const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/sync-health`;
8
+ return zeniAPI.getJSON(apiUrl).pipe(map((response) => {
9
+ if (isSuccessResponse(response)) {
10
+ return updateInvoicingQboSyncHealth(mapInvoicingQboSyncHealth(response.data ?? {}));
11
+ }
12
+ return updateInvoicingQboSyncHealthFailure(response.status);
13
+ }), catchError((error) => of(updateInvoicingQboSyncHealthFailure(createZeniAPIStatus('Unexpected Error', 'Fetch QBO sync health REST API call errored out ' +
14
+ JSON.stringify(error))))));
15
+ }));
@@ -0,0 +1,26 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
+ import { fetchInvoicingQboSyncHealth, retryInvoicingQboSyncTask, retryInvoicingQboSyncTaskFailure, retryInvoicingQboSyncTaskSuccess, } from '../invoicingQboViewReducer';
5
+ export const retryInvoicingQboSyncTaskEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(retryInvoicingQboSyncTask.match), mergeMap((action) => {
6
+ const { taskId } = action.payload;
7
+ const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/sync-tasks/${encodeURIComponent(taskId)}/retry`;
8
+ return zeniAPI
9
+ .postAndGetJSON(apiUrl, {})
10
+ .pipe(mergeMap((response) => {
11
+ if (isSuccessResponse(response)) {
12
+ return of(retryInvoicingQboSyncTaskSuccess({
13
+ status: response.data?.status ?? '',
14
+ taskId: response.data?.task_id ?? taskId,
15
+ }), fetchInvoicingQboSyncHealth());
16
+ }
17
+ return of(retryInvoicingQboSyncTaskFailure({
18
+ status: response.status,
19
+ taskId,
20
+ }));
21
+ }), catchError((error) => of(retryInvoicingQboSyncTaskFailure({
22
+ status: createZeniAPIStatus('Unexpected Error', 'Retry QBO sync task REST API call errored out ' +
23
+ JSON.stringify(error)),
24
+ taskId,
25
+ }))));
26
+ }));
@@ -0,0 +1,18 @@
1
+ import { of } from 'rxjs';
2
+ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
+ import { fetchInvoicingQboSyncHealth, startInvoicingQboBackfill, startInvoicingQboBackfillFailure, startInvoicingQboBackfillSuccess, } from '../invoicingQboViewReducer';
5
+ export const startInvoicingQboBackfillEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(startInvoicingQboBackfill.match), switchMap((action) => {
6
+ const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/backfill`;
7
+ return zeniAPI
8
+ .postAndGetJSON(apiUrl, {
9
+ start_date: action.payload.startDate,
10
+ })
11
+ .pipe(mergeMap((response) => {
12
+ if (isSuccessResponse(response)) {
13
+ return of(startInvoicingQboBackfillSuccess(), fetchInvoicingQboSyncHealth());
14
+ }
15
+ return of(startInvoicingQboBackfillFailure(response.status));
16
+ }), catchError((error) => of(startInvoicingQboBackfillFailure(createZeniAPIStatus('Unexpected Error', 'Start QBO backfill REST API call errored out ' +
17
+ JSON.stringify(error))))));
18
+ }));
@@ -0,0 +1,47 @@
1
+ export function mapInvoicingQboConnection(payload) {
2
+ return {
3
+ connected: payload.connected,
4
+ companyName: payload.company_name ?? undefined,
5
+ connectionId: payload.connection_id ?? undefined,
6
+ realmId: payload.realm_id ?? undefined,
7
+ };
8
+ }
9
+ export function mapInvoicingQboAccountOptions(rows) {
10
+ return rows.flatMap((row) => {
11
+ // Only qbo_id is a valid QBO AccountRef/ClassRef value — platform-internal
12
+ // ids (account_id / id) are display metadata and must never be submitted.
13
+ const accountId = row.qbo_id ?? row.id ?? row.account_id ?? '';
14
+ if (accountId === '') {
15
+ return [];
16
+ }
17
+ const accountName = row.name ??
18
+ row.account_name ??
19
+ row.accounting_class_name ??
20
+ row.qbo_accounting_class_name ??
21
+ row.fully_qualified_name ??
22
+ accountId;
23
+ return [
24
+ {
25
+ id: accountId,
26
+ name: accountName,
27
+ accountType: row.account_type ?? undefined,
28
+ },
29
+ ];
30
+ });
31
+ }
32
+ export function mapInvoicingQboSyncHealth(payload) {
33
+ return {
34
+ connection: payload.connection != null
35
+ ? mapInvoicingQboConnection(payload.connection)
36
+ : undefined,
37
+ countsByStatus: payload.counts_by_status ?? {},
38
+ failedTasks: (payload.failed_tasks ?? []).map((task) => ({
39
+ attempts: task.attempts,
40
+ entityId: task.entity_id,
41
+ entityType: task.entity_type,
42
+ taskId: task.task_id,
43
+ lastError: task.last_error ?? undefined,
44
+ updatedAt: task.updated_at ?? undefined,
45
+ })),
46
+ };
47
+ }
@@ -0,0 +1,128 @@
1
+ import { createSlice } from '@reduxjs/toolkit';
2
+ export const initialState = {
3
+ accountsByAccountTypes: {},
4
+ accountsFetchStateByAccountTypes: {},
5
+ backfillFetchState: { fetchState: 'Not-Started', error: undefined },
6
+ classes: [],
7
+ classesFetchState: { fetchState: 'Not-Started', error: undefined },
8
+ connection: undefined,
9
+ connectionFetchState: { fetchState: 'Not-Started', error: undefined },
10
+ retryFetchStateByTaskId: {},
11
+ syncHealth: undefined,
12
+ syncHealthFetchState: { fetchState: 'Not-Started', error: undefined },
13
+ };
14
+ const invoicingQboView = createSlice({
15
+ name: 'invoicingQboView',
16
+ initialState,
17
+ reducers: {
18
+ fetchInvoicingQboConnection(draft) {
19
+ draft.connectionFetchState = {
20
+ fetchState: 'In-Progress',
21
+ error: undefined,
22
+ };
23
+ },
24
+ updateInvoicingQboConnection(draft, action) {
25
+ draft.connection = action.payload;
26
+ draft.connectionFetchState = { fetchState: 'Completed', error: undefined };
27
+ },
28
+ updateInvoicingQboConnectionFailure(draft, action) {
29
+ draft.connectionFetchState = { fetchState: 'Error', error: action.payload };
30
+ },
31
+ fetchInvoicingQboAccounts: {
32
+ reducer(draft, action) {
33
+ draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
34
+ fetchState: 'In-Progress',
35
+ error: undefined,
36
+ };
37
+ },
38
+ prepare(accountTypes) {
39
+ return { payload: { accountTypes } };
40
+ },
41
+ },
42
+ updateInvoicingQboAccounts(draft, action) {
43
+ draft.accountsByAccountTypes[action.payload.accountTypes] =
44
+ action.payload.accounts;
45
+ draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
46
+ fetchState: 'Completed',
47
+ error: undefined,
48
+ };
49
+ },
50
+ updateInvoicingQboAccountsFailure(draft, action) {
51
+ draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
52
+ fetchState: 'Error',
53
+ error: action.payload.status,
54
+ };
55
+ },
56
+ fetchInvoicingQboClasses(draft) {
57
+ draft.classesFetchState = { fetchState: 'In-Progress', error: undefined };
58
+ },
59
+ updateInvoicingQboClasses(draft, action) {
60
+ draft.classes = action.payload;
61
+ draft.classesFetchState = { fetchState: 'Completed', error: undefined };
62
+ },
63
+ updateInvoicingQboClassesFailure(draft, action) {
64
+ draft.classesFetchState = { fetchState: 'Error', error: action.payload };
65
+ },
66
+ fetchInvoicingQboSyncHealth(draft) {
67
+ draft.syncHealthFetchState = {
68
+ fetchState: 'In-Progress',
69
+ error: undefined,
70
+ };
71
+ },
72
+ updateInvoicingQboSyncHealth(draft, action) {
73
+ draft.syncHealth = action.payload;
74
+ draft.syncHealthFetchState = { fetchState: 'Completed', error: undefined };
75
+ },
76
+ updateInvoicingQboSyncHealthFailure(draft, action) {
77
+ draft.syncHealthFetchState = {
78
+ fetchState: 'Error',
79
+ error: action.payload,
80
+ };
81
+ },
82
+ retryInvoicingQboSyncTask: {
83
+ reducer(draft, action) {
84
+ draft.retryFetchStateByTaskId[action.payload.taskId] = {
85
+ fetchState: 'In-Progress',
86
+ error: undefined,
87
+ };
88
+ },
89
+ prepare(taskId) {
90
+ return { payload: { taskId } };
91
+ },
92
+ },
93
+ retryInvoicingQboSyncTaskSuccess(draft, action) {
94
+ draft.retryFetchStateByTaskId[action.payload.taskId] = {
95
+ fetchState: 'Completed',
96
+ error: undefined,
97
+ };
98
+ },
99
+ retryInvoicingQboSyncTaskFailure(draft, action) {
100
+ draft.retryFetchStateByTaskId[action.payload.taskId] = {
101
+ fetchState: 'Error',
102
+ error: action.payload.status,
103
+ };
104
+ },
105
+ startInvoicingQboBackfill: {
106
+ reducer(draft) {
107
+ draft.backfillFetchState = {
108
+ fetchState: 'In-Progress',
109
+ error: undefined,
110
+ };
111
+ },
112
+ prepare(startDate) {
113
+ return { payload: { startDate } };
114
+ },
115
+ },
116
+ startInvoicingQboBackfillSuccess(draft) {
117
+ draft.backfillFetchState = { fetchState: 'Completed', error: undefined };
118
+ },
119
+ startInvoicingQboBackfillFailure(draft, action) {
120
+ draft.backfillFetchState = { fetchState: 'Error', error: action.payload };
121
+ },
122
+ clearInvoicingQboView(draft) {
123
+ Object.assign(draft, initialState);
124
+ },
125
+ },
126
+ });
127
+ export const { fetchInvoicingQboConnection, updateInvoicingQboConnection, updateInvoicingQboConnectionFailure, fetchInvoicingQboAccounts, updateInvoicingQboAccounts, updateInvoicingQboAccountsFailure, fetchInvoicingQboClasses, updateInvoicingQboClasses, updateInvoicingQboClassesFailure, fetchInvoicingQboSyncHealth, updateInvoicingQboSyncHealth, updateInvoicingQboSyncHealthFailure, retryInvoicingQboSyncTask, retryInvoicingQboSyncTaskSuccess, retryInvoicingQboSyncTaskFailure, startInvoicingQboBackfill, startInvoicingQboBackfillSuccess, startInvoicingQboBackfillFailure, clearInvoicingQboView, } = invoicingQboView.actions;
128
+ export default invoicingQboView.reducer;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Single bundled view for the QBO integration settings screen — the
3
+ * connection, per-account-types account options, classes, sync health, and the
4
+ * fetch/action states for each of them.
5
+ */
6
+ export const getInvoicingQboView = (state) => {
7
+ const qboState = state.invoicingQboViewState;
8
+ return {
9
+ accountsByAccountTypes: qboState.accountsByAccountTypes,
10
+ accountsFetchStateByAccountTypes: qboState.accountsFetchStateByAccountTypes,
11
+ backfillState: qboState.backfillFetchState,
12
+ classes: qboState.classes,
13
+ classesFetchState: qboState.classesFetchState,
14
+ connection: qboState.connection,
15
+ connectionFetchState: qboState.connectionFetchState,
16
+ retryFetchStateByTaskId: qboState.retryFetchStateByTaskId,
17
+ syncHealth: qboState.syncHealth,
18
+ syncHealthFetchState: qboState.syncHealthFetchState,
19
+ };
20
+ };
@@ -1,15 +1,8 @@
1
- const dollarsFromAmountString = (value) => {
2
- const parsed = Number.parseFloat(value);
3
- if (Number.isNaN(parsed)) {
4
- return 0;
5
- }
6
- return parsed;
7
- };
8
1
  export const computeIssueCreditNoteTotal = (lineItems) => lineItems
9
2
  .filter((lineItem) => lineItem.selected)
10
3
  .reduce((total, lineItem) => {
11
4
  const quantity = Number.parseFloat(lineItem.quantity);
12
- const unitAmount = dollarsFromAmountString(lineItem.unitAmount);
5
+ const unitAmount = lineItem.unitAmount.amount;
13
6
  if (Number.isNaN(quantity) || quantity <= 0 || unitAmount <= 0) {
14
7
  return total;
15
8
  }
@@ -20,7 +13,7 @@ export const localDataToIssueCreditNotePayload = (localData) => {
20
13
  .filter((lineItem) => lineItem.selected)
21
14
  .map((lineItem) => {
22
15
  const quantity = Math.round(Number.parseFloat(lineItem.quantity));
23
- const unitAmount = dollarsFromAmountString(lineItem.unitAmount);
16
+ const unitAmount = lineItem.unitAmount.amount;
24
17
  return {
25
18
  description: lineItem.description,
26
19
  quantity,
@@ -43,9 +36,9 @@ export const initializeIssueCreditNoteDraftFromInvoice = (invoice) => ({
43
36
  description: lineItem.description,
44
37
  id: lineItem.id,
45
38
  maxQuantity: lineItem.quantity,
46
- maxUnitAmount: lineItem.unitAmount.amount,
39
+ maxUnitAmount: lineItem.unitAmount,
47
40
  quantity: String(lineItem.quantity),
48
41
  selected: true,
49
- unitAmount: lineItem.unitAmount.amount.toFixed(2),
42
+ unitAmount: lineItem.unitAmount,
50
43
  })),
51
44
  });
@@ -25,7 +25,6 @@ export const INVOICING_PAYMENT_GATEWAY_VALUES = [
25
25
  'other',
26
26
  ];
27
27
  export const initialRecordPaymentFormLocalData = {
28
- amount: '',
29
28
  comment: '',
30
29
  customerId: '',
31
30
  date: '',