@zeniai/client-epic-state 5.2.41-beta6MM → 5.2.41-beta7MM

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 (195) hide show
  1. package/lib/entity/billPay/billTransaction/billTransactionReducer.d.ts +5 -1
  2. package/lib/entity/billPay/billTransaction/billTransactionReducer.js +17 -2
  3. package/lib/entity/invoicing/coupon/couponPayload.d.ts +8 -0
  4. package/lib/entity/invoicing/coupon/couponPayload.js +8 -0
  5. package/lib/entity/invoicing/coupon/couponState.d.ts +6 -0
  6. package/lib/entity/invoicing/dunningCase/dunningCaseTypes.d.ts +1 -1
  7. package/lib/entity/invoicing/plan/planSelector.d.ts +20 -0
  8. package/lib/entity/invoicing/plan/planSelector.js +42 -0
  9. package/lib/entity/invoicing/product/productPayload.d.ts +8 -1
  10. package/lib/entity/invoicing/product/productPayload.js +4 -1
  11. package/lib/entity/invoicing/product/productState.d.ts +16 -0
  12. package/lib/entity/jeSchedules/jeSchedulesReducer.d.ts +4 -1
  13. package/lib/entity/jeSchedules/jeSchedulesReducer.js +79 -5
  14. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  15. package/lib/entity/snackbar/snackbarTypes.js +1 -0
  16. package/lib/entity/task/taskState.d.ts +1 -1
  17. package/lib/epic.d.ts +4 -1
  18. package/lib/epic.js +10 -4
  19. package/lib/esm/entity/billPay/billTransaction/billTransactionReducer.js +16 -1
  20. package/lib/esm/entity/invoicing/coupon/couponPayload.js +8 -0
  21. package/lib/esm/entity/invoicing/plan/planSelector.js +39 -0
  22. package/lib/esm/entity/invoicing/product/productPayload.js +4 -1
  23. package/lib/esm/entity/jeSchedules/jeSchedulesReducer.js +78 -4
  24. package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
  25. package/lib/esm/epic.js +10 -4
  26. package/lib/esm/index.js +8 -7
  27. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/actualMatching/ignoreActualMatchingSuggestionEpic.js +3 -2
  28. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchFailedJePostingsEpic.js +39 -0
  29. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulePageEpic.js +14 -1
  30. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +10 -13
  31. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/initializeJeScheduleLocalDataEpic.js +38 -17
  32. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/retryJeSchedulesEpic.js +17 -1
  33. package/lib/esm/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +15 -4
  34. package/lib/esm/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +6 -0
  35. package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +74 -1
  36. package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +80 -53
  37. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +10 -0
  38. package/lib/esm/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +6 -2
  39. package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +49 -14
  40. package/lib/esm/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +28 -11
  41. package/lib/esm/view/invoicing/createInvoice/createInvoiceSelector.js +28 -1
  42. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +67 -35
  43. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewReducer.js +22 -11
  44. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.js +23 -4
  45. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/invoicingCatalogItemFormHelper.js +1 -7
  46. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +19 -5
  47. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/seedInvoicingCatalogItemFormDraftEpic.js +30 -7
  48. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewPayload.js +16 -1
  49. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewReducer.js +22 -11
  50. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.js +69 -6
  51. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewState.js +22 -0
  52. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/fetchInvoicingCouponDetailPageEpic.js +22 -4
  53. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +18 -4
  54. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/seedInvoicingCouponFormDraftEpic.js +29 -6
  55. package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer.js +28 -12
  56. package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector.js +37 -2
  57. package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/initializeInvoicingCustomerAddressEpic.js +43 -17
  58. package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +1 -1
  59. package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/seedInvoicingCustomerFormDraftEpic.js +29 -6
  60. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewReducer.js +30 -14
  61. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +143 -8
  62. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionFormPageEpic.js +4 -1
  63. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/initializeInvoicingSubscriptionAddressEpic.js +44 -18
  64. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +1 -1
  65. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/seedInvoicingSubscriptionFormDraftEpic.js +29 -8
  66. package/lib/esm/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewSelector.js +12 -0
  67. package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js +6 -6
  68. package/lib/esm/view/invoicing/invoicingFormDraft.js +78 -0
  69. package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +57 -9
  70. package/lib/esm/view/recommendation/recommendationPayload.js +3 -1
  71. package/lib/esm/view/recommendation/recommendationReducer.js +27 -7
  72. package/lib/esm/view/recommendation/recommendationSelector.js +1 -0
  73. package/lib/esm/view/recommendation/submitRecommendationFeedbackEpic.js +20 -8
  74. package/lib/esm/view/spendManagement/billPay/billDetailView/billDetailViewReducer.js +87 -1
  75. package/lib/esm/view/spendManagement/billPay/billDetailView/billDetailViewSelector.js +1 -0
  76. package/lib/esm/view/spendManagement/billPay/billDetailView/billDetailViewState.js +4 -0
  77. package/lib/esm/view/spendManagement/billPay/billDetailView/epics/fetchBillRecommendationsEpic.js +97 -0
  78. package/lib/esm/view/spendManagement/billPay/billDetailView/epics/fetchRecommendationsForBill.js +85 -0
  79. package/lib/esm/view/spendManagement/billPay/editBillView/editBillViewReducer.js +18 -1
  80. package/lib/esm/view/spendManagement/billPay/editBillView/editBillViewSelector.js +3 -0
  81. package/lib/esm/view/spendManagement/billPay/editBillView/epics/applyBillRecommendationsToLocalStoreEpic.js +95 -0
  82. package/lib/index.d.ts +9 -8
  83. package/lib/index.js +54 -48
  84. package/lib/view/expenseAutomationView/epics/jeSchedule/actualMatching/ignoreActualMatchingSuggestionEpic.js +3 -2
  85. package/lib/view/expenseAutomationView/epics/jeSchedule/fetchFailedJePostingsEpic.d.ts +20 -0
  86. package/lib/view/expenseAutomationView/epics/jeSchedule/fetchFailedJePostingsEpic.js +43 -0
  87. package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulePageEpic.d.ts +2 -2
  88. package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulePageEpic.js +13 -0
  89. package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +8 -11
  90. package/lib/view/expenseAutomationView/epics/jeSchedule/initializeJeScheduleLocalDataEpic.js +38 -17
  91. package/lib/view/expenseAutomationView/epics/jeSchedule/retryJeSchedulesEpic.d.ts +2 -2
  92. package/lib/view/expenseAutomationView/epics/jeSchedule/retryJeSchedulesEpic.js +17 -1
  93. package/lib/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +15 -4
  94. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  95. package/lib/view/expenseAutomationView/payload/jeSchedulesPayload.d.ts +18 -0
  96. package/lib/view/expenseAutomationView/payload/transactionCategorizationPayload.d.ts +18 -7
  97. package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +6 -0
  98. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +10 -3
  99. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +76 -3
  100. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +80 -53
  101. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +10 -0
  102. package/lib/view/expenseAutomationView/selectorTypes/jeSchedulesSelectorTypes.d.ts +3 -0
  103. package/lib/view/expenseAutomationView/selectorTypes/transactionsViewSelectorTypes.d.ts +8 -4
  104. package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.d.ts +1 -0
  105. package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +7 -2
  106. package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +49 -14
  107. package/lib/view/expenseAutomationView/selectors/transactionCategorizationSelector.js +27 -10
  108. package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +16 -0
  109. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +8 -5
  110. package/lib/view/invoicing/createInvoice/createInvoiceSelector.d.ts +7 -2
  111. package/lib/view/invoicing/createInvoice/createInvoiceSelector.js +28 -1
  112. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.d.ts +46 -5
  113. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +69 -36
  114. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewReducer.d.ts +3 -1
  115. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewReducer.js +22 -11
  116. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.d.ts +17 -0
  117. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.js +22 -3
  118. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewState.d.ts +2 -1
  119. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/invoicingCatalogItemFormHelper.d.ts +2 -2
  120. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/invoicingCatalogItemFormHelper.js +1 -7
  121. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +17 -3
  122. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/seedInvoicingCatalogItemFormDraftEpic.d.ts +10 -6
  123. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/seedInvoicingCatalogItemFormDraftEpic.js +29 -6
  124. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewPayload.d.ts +5 -1
  125. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewPayload.js +16 -1
  126. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewReducer.d.ts +3 -1
  127. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewReducer.js +22 -11
  128. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.d.ts +46 -0
  129. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.js +68 -5
  130. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewState.d.ts +21 -1
  131. package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewState.js +24 -1
  132. package/lib/view/invoicing/editInvoicingCouponDetailView/fetchInvoicingCouponDetailPageEpic.d.ts +9 -5
  133. package/lib/view/invoicing/editInvoicingCouponDetailView/fetchInvoicingCouponDetailPageEpic.js +22 -4
  134. package/lib/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +18 -4
  135. package/lib/view/invoicing/editInvoicingCouponDetailView/seedInvoicingCouponFormDraftEpic.d.ts +10 -6
  136. package/lib/view/invoicing/editInvoicingCouponDetailView/seedInvoicingCouponFormDraftEpic.js +28 -5
  137. package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer.d.ts +5 -1
  138. package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer.js +29 -13
  139. package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector.d.ts +16 -7
  140. package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector.js +37 -2
  141. package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewState.d.ts +8 -1
  142. package/lib/view/invoicing/editInvoicingCustomerDetailView/initializeInvoicingCustomerAddressEpic.d.ts +15 -10
  143. package/lib/view/invoicing/editInvoicingCustomerDetailView/initializeInvoicingCustomerAddressEpic.js +42 -16
  144. package/lib/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +1 -1
  145. package/lib/view/invoicing/editInvoicingCustomerDetailView/seedInvoicingCustomerFormDraftEpic.d.ts +10 -6
  146. package/lib/view/invoicing/editInvoicingCustomerDetailView/seedInvoicingCustomerFormDraftEpic.js +28 -5
  147. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewReducer.d.ts +5 -1
  148. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewReducer.js +31 -15
  149. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.d.ts +79 -12
  150. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +145 -9
  151. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState.d.ts +8 -1
  152. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionFormPageEpic.js +4 -1
  153. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/initializeInvoicingSubscriptionAddressEpic.d.ts +15 -11
  154. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/initializeInvoicingSubscriptionAddressEpic.js +42 -16
  155. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +1 -1
  156. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/seedInvoicingSubscriptionFormDraftEpic.d.ts +10 -6
  157. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/seedInvoicingSubscriptionFormDraftEpic.js +28 -7
  158. package/lib/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewSelector.d.ts +10 -0
  159. package/lib/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewSelector.js +12 -0
  160. package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.d.ts +1 -1
  161. package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.d.ts +2 -2
  162. package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js +6 -6
  163. package/lib/view/invoicing/invoicingFormDraft.d.ts +63 -0
  164. package/lib/view/invoicing/invoicingFormDraft.js +86 -0
  165. package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.d.ts +49 -0
  166. package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +59 -10
  167. package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.d.ts +1 -1
  168. package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewState.d.ts +1 -1
  169. package/lib/view/recommendation/recommendationPayload.d.ts +1 -0
  170. package/lib/view/recommendation/recommendationPayload.js +5 -0
  171. package/lib/view/recommendation/recommendationReducer.d.ts +7 -1
  172. package/lib/view/recommendation/recommendationReducer.js +28 -8
  173. package/lib/view/recommendation/recommendationSelector.d.ts +2 -0
  174. package/lib/view/recommendation/recommendationSelector.js +3 -1
  175. package/lib/view/recommendation/recommendationState.d.ts +2 -1
  176. package/lib/view/recommendation/submitRecommendationFeedbackEpic.d.ts +2 -2
  177. package/lib/view/recommendation/submitRecommendationFeedbackEpic.js +18 -6
  178. package/lib/view/spendManagement/billPay/billDetailView/billDetailViewPayload.d.ts +19 -0
  179. package/lib/view/spendManagement/billPay/billDetailView/billDetailViewReducer.d.ts +10 -1
  180. package/lib/view/spendManagement/billPay/billDetailView/billDetailViewReducer.js +88 -2
  181. package/lib/view/spendManagement/billPay/billDetailView/billDetailViewSelector.d.ts +1 -0
  182. package/lib/view/spendManagement/billPay/billDetailView/billDetailViewSelector.js +1 -0
  183. package/lib/view/spendManagement/billPay/billDetailView/billDetailViewState.d.ts +7 -0
  184. package/lib/view/spendManagement/billPay/billDetailView/billDetailViewState.js +4 -0
  185. package/lib/view/spendManagement/billPay/billDetailView/epics/fetchBillRecommendationsEpic.d.ts +37 -0
  186. package/lib/view/spendManagement/billPay/billDetailView/epics/fetchBillRecommendationsEpic.js +104 -0
  187. package/lib/view/spendManagement/billPay/billDetailView/epics/fetchRecommendationsForBill.d.ts +24 -0
  188. package/lib/view/spendManagement/billPay/billDetailView/epics/fetchRecommendationsForBill.js +92 -0
  189. package/lib/view/spendManagement/billPay/editBillView/editBillViewReducer.d.ts +4 -1
  190. package/lib/view/spendManagement/billPay/editBillView/editBillViewReducer.js +19 -2
  191. package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.d.ts +1 -0
  192. package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.js +3 -0
  193. package/lib/view/spendManagement/billPay/editBillView/epics/applyBillRecommendationsToLocalStoreEpic.d.ts +18 -0
  194. package/lib/view/spendManagement/billPay/editBillView/epics/applyBillRecommendationsToLocalStoreEpic.js +102 -0
  195. package/package.json +2 -2
@@ -8,8 +8,11 @@ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
8
8
  const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
9
9
  const responsePayload_1 = require("../../../responsePayload");
10
10
  const couponViewReducer_1 = require("../couponView/couponViewReducer");
11
+ const invoicingQboViewSelector_1 = require("../invoicingQboView/invoicingQboViewSelector");
12
+ const settingsViewSelector_1 = require("../settingsView/settingsViewSelector");
11
13
  const editInvoicingCouponDetailViewPayload_1 = require("./editInvoicingCouponDetailViewPayload");
12
14
  const editInvoicingCouponDetailViewReducer_1 = require("./editInvoicingCouponDetailViewReducer");
15
+ const editInvoicingCouponDetailViewState_1 = require("./editInvoicingCouponDetailViewState");
13
16
  const saveInvoicingCouponEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)((action) => editInvoicingCouponDetailViewReducer_1.submitInvoicingCouponForm.match(action) ||
14
17
  editInvoicingCouponDetailViewReducer_1.saveInvoicingCoupon.match(action)), (0, operators_1.mergeMap)((action) => {
15
18
  const { id } = action.payload;
@@ -17,11 +20,22 @@ const saveInvoicingCouponEpic = (actions$, state$, zeniAPI) => actions$.pipe((0,
17
20
  const data = editInvoicingCouponDetailViewReducer_1.saveInvoicingCoupon.match(action)
18
21
  ? action.payload.data
19
22
  : (() => {
20
- const viewState = state$.value.editInvoicingCouponDetailViewState;
21
- const localData = (id != null
22
- ? viewState.editDraftById[id]
23
+ const state = state$.value;
24
+ const viewState = state.editInvoicingCouponDetailViewState;
25
+ const draft = (id != null
26
+ ? viewState.editDraftById[id]?.localData
23
27
  : viewState.newCouponDraft) ?? viewState.newCouponDraft;
24
- return (0, editInvoicingCouponDetailViewPayload_1.localDataToSaveInvoicingCouponPayload)(localData, id == null);
28
+ // The create default is resolved here as well as in the form view,
29
+ // so a create that never touched the picker still persists the
30
+ // settings account on the coupon instead of leaving it to whatever
31
+ // the setting says the day an invoice is raised.
32
+ const localData = id == null
33
+ ? {
34
+ ...draft,
35
+ discountsAccountId: (0, editInvoicingCouponDetailViewState_1.invoicingCouponDiscountsAccountIdForCreate)(draft.discountsAccountId, (0, settingsViewSelector_1.getInvoicingSettings)(state)?.qbo?.account_mappings),
36
+ }
37
+ : draft;
38
+ return (0, editInvoicingCouponDetailViewPayload_1.localDataToSaveInvoicingCouponPayload)(localData, id == null, (qboId) => (0, invoicingQboViewSelector_1.invoicingQboAccountByQboId)(state, qboId));
25
39
  })();
26
40
  const baseUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0`;
27
41
  const path = id != null
@@ -1,12 +1,16 @@
1
1
  import { ActionsObservable, StateObservable } from 'redux-observable';
2
2
  import { Observable } from 'rxjs';
3
3
  import { RootState } from '../../../rootStateTypes';
4
- import { seedInvoicingCouponFormDraft, updateInvoicingCouponDetail } from './editInvoicingCouponDetailViewReducer';
5
- export type ActionType = ReturnType<typeof updateInvoicingCouponDetail> | ReturnType<typeof seedInvoicingCouponFormDraft>;
4
+ import { fetchInvoicingCouponDetailPage, seedInvoicingCouponFormDraft, updateInvoicingCouponDetail } from './editInvoicingCouponDetailViewReducer';
5
+ export type ActionType = ReturnType<typeof fetchInvoicingCouponDetailPage> | ReturnType<typeof updateInvoicingCouponDetail> | ReturnType<typeof seedInvoicingCouponFormDraft>;
6
6
  /**
7
- * Seeds the edit draft from the record the moment the detail fetch lands, so
8
- * the form has its values before it mounts. The reducer ignores the seed when a
9
- * draft already exists, which is what stops a background refetch from
10
- * overwriting edits in progress.
7
+ * Seeds the edit draft from the record, so the form has its values before it
8
+ * mounts. The reducer ignores a seed once the draft holds the record, which is
9
+ * what stops a background refetch from overwriting edits in progress.
10
+ *
11
+ * Opening the page counts as a trigger, not just the detail response: the page
12
+ * fetch is cache-guarded, so re-opening a form for a record already loaded this
13
+ * session issues no request at all — and a draft cleared in between (by a save
14
+ * or a cancel) would have nothing left to seed it.
11
15
  */
12
16
  export declare const seedInvoicingCouponFormDraftEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => Observable<ActionType>;
@@ -7,13 +7,36 @@ const couponSelector_1 = require("../../../entity/invoicing/coupon/couponSelecto
7
7
  const editInvoicingCouponDetailViewReducer_1 = require("./editInvoicingCouponDetailViewReducer");
8
8
  const editInvoicingCouponDetailViewState_1 = require("./editInvoicingCouponDetailViewState");
9
9
  /**
10
- * Seeds the edit draft from the record the moment the detail fetch lands, so
11
- * the form has its values before it mounts. The reducer ignores the seed when a
12
- * draft already exists, which is what stops a background refetch from
13
- * overwriting edits in progress.
10
+ * Seeds the edit draft from the record, so the form has its values before it
11
+ * mounts. The reducer ignores a seed once the draft holds the record, which is
12
+ * what stops a background refetch from overwriting edits in progress.
13
+ *
14
+ * Opening the page counts as a trigger, not just the detail response: the page
15
+ * fetch is cache-guarded, so re-opening a form for a record already loaded this
16
+ * session issues no request at all — and a draft cleared in between (by a save
17
+ * or a cancel) would have nothing left to seed it.
14
18
  */
15
- const seedInvoicingCouponFormDraftEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(editInvoicingCouponDetailViewReducer_1.updateInvoicingCouponDetail.match), (0, operators_1.withLatestFrom)(state$), (0, operators_1.mergeMap)(([action, state]) => {
19
+ const seedInvoicingCouponFormDraftEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)((action) => editInvoicingCouponDetailViewReducer_1.updateInvoicingCouponDetail.match(action) ||
20
+ editInvoicingCouponDetailViewReducer_1.fetchInvoicingCouponDetailPage.match(action)), (0, operators_1.withLatestFrom)(state$), (0, operators_1.mergeMap)(([action, state]) => {
16
21
  const { id } = action.payload;
22
+ if (id == null) {
23
+ return rxjs_1.EMPTY;
24
+ }
25
+ // The entity alone does not say the whole record is loaded — the list
26
+ // endpoints merge their own list-shaped rows into the same store. Only a
27
+ // completed detail load does, which is also exactly when the page's
28
+ // cache-guarded fetch issues no request and this is the sole seed.
29
+ // A forced refetch is the caller asking for fresh data: the response will
30
+ // seed, and seeding first from the entity as it stands would mark the
31
+ // draft loaded and lock that response out.
32
+ if (editInvoicingCouponDetailViewReducer_1.fetchInvoicingCouponDetailPage.match(action) &&
33
+ (action.payload.cacheOverride === true ||
34
+ state.editInvoicingCouponDetailViewState.recordStateById[id]
35
+ ?.fetchState !== 'Completed')) {
36
+ return rxjs_1.EMPTY;
37
+ }
38
+ // Nothing to seed from on a cold open; the detail response triggers this
39
+ // again once it lands.
17
40
  const coupon = (0, couponSelector_1.getInvoicingCouponById)(state.invoicingCouponState, id);
18
41
  if (coupon == null) {
19
42
  return rxjs_1.EMPTY;
@@ -54,6 +54,10 @@ export declare const fetchInvoicingPaymentLinkEmailPreview: import("@reduxjs/too
54
54
  status: ZeniAPIStatus;
55
55
  }, "editInvoicingCustomerDetailView/updateInvoicingCustomerDetailFailure">, updateInvoicingCustomerFormDraft: import("@reduxjs/toolkit").ActionCreatorWithPayload<UpdateInvoicingCustomerFormDraftPayload, "editInvoicingCustomerDetailView/updateInvoicingCustomerFormDraft">, submitInvoicingCustomerForm: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: SubmitInvoicingCustomerFormPayload], SubmitInvoicingCustomerFormPayload, "editInvoicingCustomerDetailView/submitInvoicingCustomerForm", never, never>, submitInvoicingCustomerFormSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
56
56
  customerId: ID;
57
- }, "editInvoicingCustomerDetailView/submitInvoicingCustomerFormSuccess">, submitInvoicingCustomerFormFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "editInvoicingCustomerDetailView/submitInvoicingCustomerFormFailure">, resetEditInvoicingCustomerDetailView: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"editInvoicingCustomerDetailView/resetEditInvoicingCustomerDetailView">, initializeInvoicingCustomerAddress: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: InitializeInvoicingCustomerAddressPayload], InitializeInvoicingCustomerAddressPayload, "editInvoicingCustomerDetailView/initializeInvoicingCustomerAddress", never, never>;
57
+ }, "editInvoicingCustomerDetailView/submitInvoicingCustomerFormSuccess">, submitInvoicingCustomerFormFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "editInvoicingCustomerDetailView/submitInvoicingCustomerFormFailure">, resetEditInvoicingCustomerDetailView: import("@reduxjs/toolkit").ActionCreatorWithOptionalPayload<{
58
+ id?: ID;
59
+ } | undefined, "editInvoicingCustomerDetailView/resetEditInvoicingCustomerDetailView">, initializeInvoicingCustomerAddress: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: InitializeInvoicingCustomerAddressPayload], InitializeInvoicingCustomerAddressPayload, "editInvoicingCustomerDetailView/initializeInvoicingCustomerAddress", never, never>, claimInvoicingCustomerBillingAddress: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
60
+ id: ID;
61
+ }, "editInvoicingCustomerDetailView/claimInvoicingCustomerBillingAddress">;
58
62
  declare const _default: import("redux").Reducer<EditInvoicingCustomerDetailViewState>;
59
63
  export default _default;
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.initializeInvoicingCustomerAddress = exports.resetEditInvoicingCustomerDetailView = exports.submitInvoicingCustomerFormFailure = exports.submitInvoicingCustomerFormSuccess = exports.submitInvoicingCustomerForm = exports.updateInvoicingCustomerFormDraft = exports.updateInvoicingCustomerDetailFailure = exports.submitAddPromotionalCredits = exports.resetPromotionalCreditAction = exports.updateInvoicingCustomerDetail = exports.seedInvoicingCustomerFormDraft = exports.fetchInvoicingCustomerDetailPage = exports.fetchInvoicingCustomerDetail = exports.addPromotionalCreditsSuccess = exports.addPromotionalCreditsFailure = exports.updateInvoicingPaymentLinkEmailPreviewFailure = exports.updateInvoicingPaymentLinkEmailPreview = exports.fetchInvoicingPaymentLinkEmailPreviewPage = exports.fetchInvoicingPaymentLinkEmailPreview = exports.initialState = void 0;
4
+ exports.claimInvoicingCustomerBillingAddress = exports.initializeInvoicingCustomerAddress = exports.resetEditInvoicingCustomerDetailView = exports.submitInvoicingCustomerFormFailure = exports.submitInvoicingCustomerFormSuccess = exports.submitInvoicingCustomerForm = exports.updateInvoicingCustomerFormDraft = exports.updateInvoicingCustomerDetailFailure = exports.submitAddPromotionalCredits = exports.resetPromotionalCreditAction = exports.updateInvoicingCustomerDetail = exports.seedInvoicingCustomerFormDraft = exports.fetchInvoicingCustomerDetailPage = exports.fetchInvoicingCustomerDetail = exports.addPromotionalCreditsSuccess = exports.addPromotionalCreditsFailure = exports.updateInvoicingPaymentLinkEmailPreviewFailure = exports.updateInvoicingPaymentLinkEmailPreview = exports.fetchInvoicingPaymentLinkEmailPreviewPage = exports.fetchInvoicingPaymentLinkEmailPreview = exports.initialState = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const rootActions_1 = require("../../../rootActions");
7
+ const invoicingFormDraft_1 = require("../invoicingFormDraft");
7
8
  const invoicingCustomerFormConfig_1 = require("./invoicingCustomerFormConfig");
8
9
  exports.initialState = {
9
10
  emailPreviewFetchState: { fetchState: 'Not-Started', error: undefined },
@@ -11,6 +12,7 @@ exports.initialState = {
11
12
  emailPreviewCustomerId: undefined,
12
13
  promotionalCreditSubmitState: { fetchState: 'Not-Started', error: undefined },
13
14
  recordStateById: {},
15
+ billingAddressOwnerId: undefined,
14
16
  fetchState: 'Not-Started',
15
17
  error: undefined,
16
18
  editDraftById: {},
@@ -127,20 +129,17 @@ const editInvoicingCustomerDetailView = (0, toolkit_1.createSlice)({
127
129
  fetchState: 'Error',
128
130
  error: action.payload.status,
129
131
  };
132
+ (0, invoicingFormDraft_1.applyInvoicingFormDraftFailure)(draft.editDraftById, action.payload.id, invoicingCustomerFormConfig_1.initialInvoicingCustomerFormLocalData);
130
133
  },
131
- /**
132
- * Seed the draft from the loaded record, once. Skipped when a draft already
133
- * exists so a late refetch cannot overwrite in-progress edits.
134
- */
134
+ /** Fill the draft from the loaded record — see `applyInvoicingFormDraftSeed`. */
135
135
  seedInvoicingCustomerFormDraft(draft, action) {
136
- if (draft.editDraftById[action.payload.id] == null) {
137
- draft.editDraftById[action.payload.id] = action.payload.localData;
138
- }
136
+ const { id, localData } = action.payload;
137
+ (0, invoicingFormDraft_1.applyInvoicingFormDraftSeed)(draft.editDraftById, id, localData);
139
138
  },
140
139
  updateInvoicingCustomerFormDraft(draft, action) {
141
140
  const { id, localData } = action.payload;
142
141
  if (id != null) {
143
- draft.editDraftById[id] = localData;
142
+ (0, invoicingFormDraft_1.applyInvoicingFormDraftEdit)(draft.editDraftById, id, localData);
144
143
  }
145
144
  else {
146
145
  draft.newCustomerDraft = localData;
@@ -160,17 +159,30 @@ const editInvoicingCustomerDetailView = (0, toolkit_1.createSlice)({
160
159
  draft.fetchState = 'Completed';
161
160
  draft.error = undefined;
162
161
  draft.savedCustomerId = action.payload.customerId;
162
+ // An edit is refetched on success; keep the saved values on screen until
163
+ // that lands, and let it replace them.
164
+ (0, invoicingFormDraft_1.applyInvoicingFormDraftSaved)(draft.editDraftById, action.payload.customerId);
163
165
  },
164
166
  submitInvoicingCustomerFormFailure(draft, action) {
165
167
  draft.fetchState = 'Error';
166
168
  draft.error = action.payload;
167
169
  },
168
- resetEditInvoicingCustomerDetailView(draft) {
170
+ /**
171
+ * Discard a form's draft — the customer's own when `id` is given,
172
+ * the create draft otherwise. Scoped to the one form on purpose: another
173
+ * customer's half-finished edit is not this form's to throw away.
174
+ * Clearing every draft at once is what `clearAll` is for.
175
+ */
176
+ resetEditInvoicingCustomerDetailView(draft, action) {
169
177
  draft.fetchState = 'Not-Started';
170
178
  draft.error = undefined;
171
179
  draft.savedCustomerId = undefined;
172
- draft.editDraftById = {};
173
- draft.newCustomerDraft = { ...invoicingCustomerFormConfig_1.initialInvoicingCustomerFormLocalData };
180
+ const id = action.payload?.id;
181
+ if (id == null) {
182
+ draft.newCustomerDraft = { ...invoicingCustomerFormConfig_1.initialInvoicingCustomerFormLocalData };
183
+ return;
184
+ }
185
+ delete draft.editDraftById[id];
174
186
  },
175
187
  // Trigger only — handled by initializeInvoicingCustomerAddressEpic.
176
188
  initializeInvoicingCustomerAddress: {
@@ -179,6 +191,10 @@ const editInvoicingCustomerDetailView = (0, toolkit_1.createSlice)({
179
191
  return { payload };
180
192
  },
181
193
  },
194
+ /** Record which customer the shared billing-address slot now belongs to. */
195
+ claimInvoicingCustomerBillingAddress(draft, action) {
196
+ draft.billingAddressOwnerId = action.payload.id;
197
+ },
182
198
  },
183
199
  extraReducers: (builder) => {
184
200
  builder.addCase(rootActions_1.clearAll, (draft) => {
@@ -186,5 +202,5 @@ const editInvoicingCustomerDetailView = (0, toolkit_1.createSlice)({
186
202
  });
187
203
  },
188
204
  });
189
- _a = editInvoicingCustomerDetailView.actions, exports.fetchInvoicingPaymentLinkEmailPreview = _a.fetchInvoicingPaymentLinkEmailPreview, exports.fetchInvoicingPaymentLinkEmailPreviewPage = _a.fetchInvoicingPaymentLinkEmailPreviewPage, exports.updateInvoicingPaymentLinkEmailPreview = _a.updateInvoicingPaymentLinkEmailPreview, exports.updateInvoicingPaymentLinkEmailPreviewFailure = _a.updateInvoicingPaymentLinkEmailPreviewFailure, exports.addPromotionalCreditsFailure = _a.addPromotionalCreditsFailure, exports.addPromotionalCreditsSuccess = _a.addPromotionalCreditsSuccess, exports.fetchInvoicingCustomerDetail = _a.fetchInvoicingCustomerDetail, exports.fetchInvoicingCustomerDetailPage = _a.fetchInvoicingCustomerDetailPage, exports.seedInvoicingCustomerFormDraft = _a.seedInvoicingCustomerFormDraft, exports.updateInvoicingCustomerDetail = _a.updateInvoicingCustomerDetail, exports.resetPromotionalCreditAction = _a.resetPromotionalCreditAction, exports.submitAddPromotionalCredits = _a.submitAddPromotionalCredits, exports.updateInvoicingCustomerDetailFailure = _a.updateInvoicingCustomerDetailFailure, exports.updateInvoicingCustomerFormDraft = _a.updateInvoicingCustomerFormDraft, exports.submitInvoicingCustomerForm = _a.submitInvoicingCustomerForm, exports.submitInvoicingCustomerFormSuccess = _a.submitInvoicingCustomerFormSuccess, exports.submitInvoicingCustomerFormFailure = _a.submitInvoicingCustomerFormFailure, exports.resetEditInvoicingCustomerDetailView = _a.resetEditInvoicingCustomerDetailView, exports.initializeInvoicingCustomerAddress = _a.initializeInvoicingCustomerAddress;
205
+ _a = editInvoicingCustomerDetailView.actions, exports.fetchInvoicingPaymentLinkEmailPreview = _a.fetchInvoicingPaymentLinkEmailPreview, exports.fetchInvoicingPaymentLinkEmailPreviewPage = _a.fetchInvoicingPaymentLinkEmailPreviewPage, exports.updateInvoicingPaymentLinkEmailPreview = _a.updateInvoicingPaymentLinkEmailPreview, exports.updateInvoicingPaymentLinkEmailPreviewFailure = _a.updateInvoicingPaymentLinkEmailPreviewFailure, exports.addPromotionalCreditsFailure = _a.addPromotionalCreditsFailure, exports.addPromotionalCreditsSuccess = _a.addPromotionalCreditsSuccess, exports.fetchInvoicingCustomerDetail = _a.fetchInvoicingCustomerDetail, exports.fetchInvoicingCustomerDetailPage = _a.fetchInvoicingCustomerDetailPage, exports.seedInvoicingCustomerFormDraft = _a.seedInvoicingCustomerFormDraft, exports.updateInvoicingCustomerDetail = _a.updateInvoicingCustomerDetail, exports.resetPromotionalCreditAction = _a.resetPromotionalCreditAction, exports.submitAddPromotionalCredits = _a.submitAddPromotionalCredits, exports.updateInvoicingCustomerDetailFailure = _a.updateInvoicingCustomerDetailFailure, exports.updateInvoicingCustomerFormDraft = _a.updateInvoicingCustomerFormDraft, exports.submitInvoicingCustomerForm = _a.submitInvoicingCustomerForm, exports.submitInvoicingCustomerFormSuccess = _a.submitInvoicingCustomerFormSuccess, exports.submitInvoicingCustomerFormFailure = _a.submitInvoicingCustomerFormFailure, exports.resetEditInvoicingCustomerDetailView = _a.resetEditInvoicingCustomerDetailView, exports.initializeInvoicingCustomerAddress = _a.initializeInvoicingCustomerAddress, exports.claimInvoicingCustomerBillingAddress = _a.claimInvoicingCustomerBillingAddress;
190
206
  exports.default = editInvoicingCustomerDetailView.reducer;
@@ -53,6 +53,15 @@ export interface InvoicingCustomerFormView extends SelectorView {
53
53
  * Folded in here so the screen never reaches for the config view itself.
54
54
  */
55
55
  fieldHelp: InvoicingFieldHelpByCode;
56
+ /**
57
+ * True while the customer being edited is still on its way to the form. The
58
+ * form holds a skeleton on this rather than mount: it seeds react-hook-form
59
+ * once, at first render, so fields mounted against the blank draft stay blank
60
+ * and the first change writes that blankness back over the customer. A later
61
+ * refetch does not raise this again, so a refresh leaves the form on screen
62
+ * instead of blanking it mid-edit.
63
+ */
64
+ isFormLoading: boolean;
56
65
  localData: InvoicingCustomerFormLocalData;
57
66
  mode: 'create' | 'edit';
58
67
  netTermDayOptions: InvoicingNamedOption[];
@@ -77,13 +86,13 @@ export interface InvoicingCustomerFormView extends SelectorView {
77
86
  billingAddressId?: ID;
78
87
  billingAddressLabel?: string;
79
88
  emailPreview?: InvoicingPaymentLinkEmailPreviewData;
89
+ /**
90
+ * A billing address entered on the Address screen that the customer has not
91
+ * saved yet. The inline-edit form cannot see it — the address lives in the
92
+ * shared address store, not in a field — so the detail page reads this to
93
+ * offer Save, or the address could never be linked.
94
+ */
95
+ hasUnsavedBillingAddress?: boolean;
80
96
  savedCustomerId?: ID;
81
97
  }
82
- /**
83
- * Bundled view for the customer create/edit form. Exposes the draft `localData`
84
- * (seeded from the existing customer entity in edit mode until the user edits),
85
- * the canonical option value sets (labels resolved in web-components), the save
86
- * fetch state/error, and the id of the customer last saved — so the form screen
87
- * depends on this single selector.
88
- */
89
98
  export declare const getInvoicingCustomerFormView: (state: RootState, invoicingCustomerID?: ID) => InvoicingCustomerFormView;
@@ -2,12 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInvoicingCustomerFormView = exports.getInvoicingCustomerRecord = void 0;
4
4
  const reduceFetchState_1 = require("../../../commonStateTypes/reduceFetchState");
5
+ const addressSelector_1 = require("../../../entity/address/addressSelector");
5
6
  const invoiceSelector_1 = require("../../../entity/invoicing/invoice/invoiceSelector");
6
7
  const invoicingCustomerSelector_1 = require("../../../entity/invoicing/invoicingCustomer/invoicingCustomerSelector");
7
8
  const invoicingCustomerSelector_2 = require("../../../entity/invoicing/invoicingCustomer/invoicingCustomerSelector");
8
9
  const addressViewSelector_1 = require("../../addressView/addressViewSelector");
9
10
  const customerPaymentMethodSelector_1 = require("../customerPaymentMethod/customerPaymentMethodSelector");
10
11
  const invoicingConfigViewSelector_1 = require("../invoicingConfigView/invoicingConfigViewSelector");
12
+ const invoicingFormDraft_1 = require("../invoicingFormDraft");
11
13
  const invoicingSettingsHelpers_1 = require("../settingsView/invoicingSettingsHelpers");
12
14
  const settingsViewSelector_1 = require("../settingsView/settingsViewSelector");
13
15
  const invoicingCustomerFormConfig_1 = require("./invoicingCustomerFormConfig");
@@ -53,6 +55,37 @@ exports.getInvoicingCustomerRecord = getInvoicingCustomerRecord;
53
55
  * fetch state/error, and the id of the customer last saved — so the form screen
54
56
  * depends on this single selector.
55
57
  */
58
+ /**
59
+ * Whether the billing address entered on the Address screen is a change the
60
+ * customer has not saved. Presence alone cannot say so: the detail page seeds
61
+ * the address store with the saved address on load so the Address screen opens
62
+ * prefilled. Only a pending address that differs from the saved one — or one
63
+ * where nothing is saved yet — is an unsaved change. Compared on what the user
64
+ * enters; a saved address's coordinates and timestamps are left out.
65
+ */
66
+ const isBillingAddressUnsaved = (state, id, savedBillingAddressId) => {
67
+ // The slot is keyed by address type alone; only a draft this customer owns counts.
68
+ if (id == null ||
69
+ state.editInvoicingCustomerDetailViewState.billingAddressOwnerId !== id) {
70
+ return false;
71
+ }
72
+ const pending = state.addressViewState.newAddressState?.[invoicingCustomerFormConfig_1.INVOICING_CUSTOMER_BILLING_ADDRESS_TYPE]?.addressToCreate;
73
+ if (pending == null) {
74
+ return false;
75
+ }
76
+ const saved = savedBillingAddressId != null
77
+ ? (0, addressSelector_1.getAddressByAddressId)(state.addressState, savedBillingAddressId)
78
+ : undefined;
79
+ if (saved == null) {
80
+ return true;
81
+ }
82
+ return !(pending.street.join('\u0000') === saved.street.join('\u0000') &&
83
+ pending.city === saved.city &&
84
+ pending.state === saved.state &&
85
+ pending.postalCode === saved.postalCode &&
86
+ pending.country === saved.country &&
87
+ (pending.countryCode ?? '') === (saved.countryCode ?? ''));
88
+ };
56
89
  const getInvoicingCustomerFormView = (state, invoicingCustomerID) => {
57
90
  const { editDraftById, error, fetchState, newCustomerDraft, savedCustomerId } = state.editInvoicingCustomerDetailViewState;
58
91
  const mode = invoicingCustomerID != null ? 'edit' : 'create';
@@ -63,8 +96,7 @@ const getInvoicingCustomerFormView = (state, invoicingCustomerID) => {
63
96
  // `seedInvoicingCustomerFormDraftEpic` when the detail load lands. Until then
64
97
  // the page is showing its skeleton.
65
98
  const localData = invoicingCustomerID != null
66
- ? (editDraftById[invoicingCustomerID] ??
67
- invoicingCustomerFormConfig_1.initialInvoicingCustomerFormLocalData)
99
+ ? (0, invoicingFormDraft_1.getInvoicingFormDraftLocalData)(editDraftById, invoicingCustomerID, invoicingCustomerFormConfig_1.initialInvoicingCustomerFormLocalData)
68
100
  : newCustomerDraft;
69
101
  // Billing address is captured via the shared Address screen and seeded there
70
102
  // (from the address entity) on detail load, so the formatted label comes from
@@ -82,6 +114,7 @@ const getInvoicingCustomerFormView = (state, invoicingCustomerID) => {
82
114
  ? { error: undefined, fetchState: 'Completed' }
83
115
  : (state.editInvoicingCustomerDetailViewState.recordStateById[invoicingCustomerID] ?? { error: undefined, fetchState: 'Not-Started' });
84
116
  const { emailPreview, emailPreviewCustomerId, emailPreviewFetchState } = state.editInvoicingCustomerDetailViewState;
117
+ const isFormLoading = (0, invoicingFormDraft_1.isInvoicingFormDraftPending)(editDraftById, invoicingCustomerID);
85
118
  return {
86
119
  // A preview cached for another customer is not this screen's.
87
120
  emailPreview: emailPreviewCustomerId === invoicingCustomerID ? emailPreview : undefined,
@@ -96,6 +129,7 @@ const getInvoicingCustomerFormView = (state, invoicingCustomerID) => {
96
129
  promotionalCreditSubmitState: state.editInvoicingCustomerDetailViewState.promotionalCreditSubmitState,
97
130
  record: (0, exports.getInvoicingCustomerRecord)(state, invoicingCustomerID),
98
131
  fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'customer'),
132
+ isFormLoading,
99
133
  customerTypeOptions,
100
134
  localData,
101
135
  mode,
@@ -103,6 +137,7 @@ const getInvoicingCustomerFormView = (state, invoicingCustomerID) => {
103
137
  taxabilityOptions,
104
138
  billingAddressId,
105
139
  billingAddressLabel,
140
+ hasUnsavedBillingAddress: isBillingAddressUnsaved(state, invoicingCustomerID, customer?.billingAddressId),
106
141
  savedCustomerId,
107
142
  fetchState,
108
143
  error,
@@ -1,4 +1,5 @@
1
1
  import { FetchStateAndError, FetchedState, ID } from '../../../commonStateTypes/common';
2
+ import { InvoicingFormDraftById } from '../invoicingFormDraft';
2
3
  /**
3
4
  * The payment-link email the composer opens with: the backend's prefill plus
4
5
  * the tokens the frontend splices the user's edits into. State, not wire shape
@@ -37,7 +38,7 @@ export interface InvoicingCustomerFormLocalData {
37
38
  vatNumber: string;
38
39
  }
39
40
  export interface EditInvoicingCustomerDetailViewState extends FetchedState {
40
- editDraftById: Record<ID, InvoicingCustomerFormLocalData>;
41
+ editDraftById: InvoicingFormDraftById<InvoicingCustomerFormLocalData>;
41
42
  /**
42
43
  * The payment-link email rendered by the backend, cached per customer so
43
44
  * reopening the composer costs nothing. `emailPreviewCustomerId` is the cache
@@ -52,6 +53,12 @@ export interface EditInvoicingCustomerDetailViewState extends FetchedState {
52
53
  promotionalCreditSubmitState: FetchStateAndError;
53
54
  /** Detail-load state per customer id. */
54
55
  recordStateById: Record<ID, FetchStateAndError>;
56
+ /**
57
+ * The customer whose billing address currently occupies the shared address
58
+ * store slot. That slot is keyed by address type alone, so without this a
59
+ * draft seeded or edited for one customer would pass for the next one's.
60
+ */
61
+ billingAddressOwnerId?: ID;
55
62
  emailPreview?: InvoicingPaymentLinkEmailPreviewData;
56
63
  emailPreviewCustomerId?: ID;
57
64
  savedCustomerId?: ID;
@@ -1,16 +1,21 @@
1
1
  import { ActionsObservable, StateObservable } from 'redux-observable';
2
2
  import { Observable } from 'rxjs';
3
3
  import { RootState } from '../../../rootStateTypes';
4
- import { newAddressInLocalStore } from '../../addressView/addressViewReducer';
5
- import { updateInvoicingCustomerDetail } from '../editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer';
6
- import { initializeInvoicingCustomerAddress } from './editInvoicingCustomerDetailViewReducer';
7
- export type ActionType = ReturnType<typeof initializeInvoicingCustomerAddress> | ReturnType<typeof updateInvoicingCustomerDetail> | ReturnType<typeof newAddressInLocalStore>;
4
+ import { newAddressInLocalStore, removeNewAddressDataInLocalStore } from '../../addressView/addressViewReducer';
5
+ import { claimInvoicingCustomerBillingAddress, fetchInvoicingCustomerDetail, fetchInvoicingCustomerDetailPage, initializeInvoicingCustomerAddress, updateInvoicingCustomerDetail } from './editInvoicingCustomerDetailViewReducer';
6
+ export type ActionType = ReturnType<typeof initializeInvoicingCustomerAddress> | ReturnType<typeof updateInvoicingCustomerDetail> | ReturnType<typeof fetchInvoicingCustomerDetailPage> | ReturnType<typeof fetchInvoicingCustomerDetail> | ReturnType<typeof claimInvoicingCustomerBillingAddress> | ReturnType<typeof newAddressInLocalStore> | ReturnType<typeof removeNewAddressDataInLocalStore>;
8
7
  /**
9
- * Seed the shared Address screen with an existing customer's saved billing
10
- * address (looked up in the address entity store by `billingAddressId`). Runs
11
- * both when the customer detail loads and on an explicit initialize trigger.
12
- * Skips when an in-progress draft already exists, so an address the user just
13
- * entered survives navigating between the form and the Address screen. Mirrors
14
- * `initializeVendorAddressEpic`.
8
+ * Seed the shared Address screen with the customer's saved billing address, and
9
+ * record that the slot is this customer's. Runs when a detail request is issued
10
+ * (every path that loads a record issues one — the detail page when not cached,
11
+ * the create/edit form always), when the page opens, when the detail load
12
+ * lands, and on an explicit initialize trigger.
13
+ *
14
+ * The address store slot is keyed by address type alone, so it can still hold
15
+ * another customer's draft. Only a draft this customer owns is left alone —
16
+ * that is what lets an address the user just entered survive a trip to the
17
+ * Address screen. Anything else is replaced by this customer's saved address,
18
+ * or cleared when it has none. Opening the page counts as a trigger because a
19
+ * record already loaded this session issues no detail request at all.
15
20
  */
16
21
  export declare const initializeInvoicingCustomerAddressEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => Observable<ActionType>;
@@ -6,34 +6,60 @@ const operators_1 = require("rxjs/operators");
6
6
  const addressSelector_1 = require("../../../entity/address/addressSelector");
7
7
  const invoicingCustomerSelector_1 = require("../../../entity/invoicing/invoicingCustomer/invoicingCustomerSelector");
8
8
  const addressViewReducer_1 = require("../../addressView/addressViewReducer");
9
- const editInvoicingCustomerDetailViewReducer_1 = require("../editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer");
10
- const editInvoicingCustomerDetailViewReducer_2 = require("./editInvoicingCustomerDetailViewReducer");
9
+ const editInvoicingCustomerDetailViewReducer_1 = require("./editInvoicingCustomerDetailViewReducer");
11
10
  const invoicingCustomerFormConfig_1 = require("./invoicingCustomerFormConfig");
12
11
  /**
13
- * Seed the shared Address screen with an existing customer's saved billing
14
- * address (looked up in the address entity store by `billingAddressId`). Runs
15
- * both when the customer detail loads and on an explicit initialize trigger.
16
- * Skips when an in-progress draft already exists, so an address the user just
17
- * entered survives navigating between the form and the Address screen. Mirrors
18
- * `initializeVendorAddressEpic`.
12
+ * Seed the shared Address screen with the customer's saved billing address, and
13
+ * record that the slot is this customer's. Runs when a detail request is issued
14
+ * (every path that loads a record issues one — the detail page when not cached,
15
+ * the create/edit form always), when the page opens, when the detail load
16
+ * lands, and on an explicit initialize trigger.
17
+ *
18
+ * The address store slot is keyed by address type alone, so it can still hold
19
+ * another customer's draft. Only a draft this customer owns is left alone —
20
+ * that is what lets an address the user just entered survive a trip to the
21
+ * Address screen. Anything else is replaced by this customer's saved address,
22
+ * or cleared when it has none. Opening the page counts as a trigger because a
23
+ * record already loaded this session issues no detail request at all.
19
24
  */
20
- const initializeInvoicingCustomerAddressEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)((action) => editInvoicingCustomerDetailViewReducer_2.initializeInvoicingCustomerAddress.match(action) ||
21
- editInvoicingCustomerDetailViewReducer_1.updateInvoicingCustomerDetail.match(action)), (0, operators_1.mergeMap)((action) => {
25
+ const initializeInvoicingCustomerAddressEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)((action) => editInvoicingCustomerDetailViewReducer_1.initializeInvoicingCustomerAddress.match(action) ||
26
+ editInvoicingCustomerDetailViewReducer_1.updateInvoicingCustomerDetail.match(action) ||
27
+ editInvoicingCustomerDetailViewReducer_1.fetchInvoicingCustomerDetailPage.match(action) ||
28
+ editInvoicingCustomerDetailViewReducer_1.fetchInvoicingCustomerDetail.match(action)), (0, operators_1.mergeMap)((action) => {
22
29
  const { id } = action.payload;
30
+ if (id == null) {
31
+ return rxjs_1.EMPTY;
32
+ }
23
33
  const rootState = state$.value;
24
- const existingDraft = rootState.addressViewState.newAddressState?.[invoicingCustomerFormConfig_1.INVOICING_CUSTOMER_BILLING_ADDRESS_TYPE]?.addressToCreate;
25
- if (existingDraft != null || id == null) {
34
+ const pending = rootState.addressViewState.newAddressState?.[invoicingCustomerFormConfig_1.INVOICING_CUSTOMER_BILLING_ADDRESS_TYPE]?.addressToCreate;
35
+ const ownerId = rootState.editInvoicingCustomerDetailViewState.billingAddressOwnerId;
36
+ // A detail response speaks for the record it loaded, which may no longer
37
+ // be the one on screen: its request keeps running when the user moves on
38
+ // to a cached record, which issues no request of its own to cancel it.
39
+ // Only the page-open and explicit triggers define the current record.
40
+ if (editInvoicingCustomerDetailViewReducer_1.updateInvoicingCustomerDetail.match(action) &&
41
+ ownerId != null &&
42
+ ownerId !== id) {
43
+ return rxjs_1.EMPTY;
44
+ }
45
+ if (pending != null && ownerId === id) {
26
46
  return rxjs_1.EMPTY;
27
47
  }
28
48
  const customer = (0, invoicingCustomerSelector_1.getInvoicingCustomerById)(rootState.invoicingCustomerState, id);
29
49
  const address = customer?.billingAddressId != null
30
50
  ? (0, addressSelector_1.getAddressByAddressId)(rootState.addressState, customer.billingAddressId)
31
51
  : undefined;
32
- return address != null
33
- ? (0, rxjs_1.of)((0, addressViewReducer_1.newAddressInLocalStore)({
52
+ const actions = [];
53
+ if (address != null) {
54
+ actions.push((0, addressViewReducer_1.newAddressInLocalStore)({
34
55
  addressType: invoicingCustomerFormConfig_1.INVOICING_CUSTOMER_BILLING_ADDRESS_TYPE,
35
56
  addressToCreate: address,
36
- }))
37
- : rxjs_1.EMPTY;
57
+ }));
58
+ }
59
+ else if (pending != null) {
60
+ actions.push((0, addressViewReducer_1.removeNewAddressDataInLocalStore)(invoicingCustomerFormConfig_1.INVOICING_CUSTOMER_BILLING_ADDRESS_TYPE));
61
+ }
62
+ actions.push((0, editInvoicingCustomerDetailViewReducer_1.claimInvoicingCustomerBillingAddress)({ id }));
63
+ return (0, rxjs_1.from)(actions);
38
64
  }));
39
65
  exports.initializeInvoicingCustomerAddressEpic = initializeInvoicingCustomerAddressEpic;
@@ -19,7 +19,7 @@ const saveInvoicingCustomerEpic = (actions$, state$, zeniAPI) => actions$.pipe((
19
19
  const rootState = state$.value;
20
20
  const viewState = rootState.editInvoicingCustomerDetailViewState;
21
21
  const localData = (id != null
22
- ? viewState.editDraftById[id]
22
+ ? viewState.editDraftById[id]?.localData
23
23
  : viewState.newCustomerDraft) ?? viewState.newCustomerDraft;
24
24
  // Billing address captured via the shared Address screen is sent as an
25
25
  // object in the payload; the backend creates it and returns its id
@@ -1,12 +1,16 @@
1
1
  import { ActionsObservable, StateObservable } from 'redux-observable';
2
2
  import { Observable } from 'rxjs';
3
3
  import { RootState } from '../../../rootStateTypes';
4
- import { seedInvoicingCustomerFormDraft, updateInvoicingCustomerDetail } from './editInvoicingCustomerDetailViewReducer';
5
- export type ActionType = ReturnType<typeof updateInvoicingCustomerDetail> | ReturnType<typeof seedInvoicingCustomerFormDraft>;
4
+ import { fetchInvoicingCustomerDetailPage, seedInvoicingCustomerFormDraft, updateInvoicingCustomerDetail } from './editInvoicingCustomerDetailViewReducer';
5
+ export type ActionType = ReturnType<typeof fetchInvoicingCustomerDetailPage> | ReturnType<typeof updateInvoicingCustomerDetail> | ReturnType<typeof seedInvoicingCustomerFormDraft>;
6
6
  /**
7
- * Seeds the edit draft from the record the moment the detail fetch lands, so
8
- * the form has its values before it mounts. The reducer ignores the seed when a
9
- * draft already exists, which is what stops a background refetch from
10
- * overwriting edits in progress.
7
+ * Seeds the edit draft from the record, so the form has its values before it
8
+ * mounts. The reducer ignores a seed once the draft holds the record, which is
9
+ * what stops a background refetch from overwriting edits in progress.
10
+ *
11
+ * Opening the page counts as a trigger, not just the detail response: the page
12
+ * fetch is cache-guarded, so re-opening for a record already loaded this
13
+ * session issues no request at all — and a draft cleared in between (by a save
14
+ * or a cancel) would have nothing left to seed it.
11
15
  */
12
16
  export declare const seedInvoicingCustomerFormDraftEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => Observable<ActionType>;
@@ -7,13 +7,36 @@ const invoicingCustomerSelector_1 = require("../../../entity/invoicing/invoicing
7
7
  const editInvoicingCustomerDetailViewReducer_1 = require("./editInvoicingCustomerDetailViewReducer");
8
8
  const invoicingCustomerFormConfig_1 = require("./invoicingCustomerFormConfig");
9
9
  /**
10
- * Seeds the edit draft from the record the moment the detail fetch lands, so
11
- * the form has its values before it mounts. The reducer ignores the seed when a
12
- * draft already exists, which is what stops a background refetch from
13
- * overwriting edits in progress.
10
+ * Seeds the edit draft from the record, so the form has its values before it
11
+ * mounts. The reducer ignores a seed once the draft holds the record, which is
12
+ * what stops a background refetch from overwriting edits in progress.
13
+ *
14
+ * Opening the page counts as a trigger, not just the detail response: the page
15
+ * fetch is cache-guarded, so re-opening for a record already loaded this
16
+ * session issues no request at all — and a draft cleared in between (by a save
17
+ * or a cancel) would have nothing left to seed it.
14
18
  */
15
- const seedInvoicingCustomerFormDraftEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(editInvoicingCustomerDetailViewReducer_1.updateInvoicingCustomerDetail.match), (0, operators_1.withLatestFrom)(state$), (0, operators_1.mergeMap)(([action, state]) => {
19
+ const seedInvoicingCustomerFormDraftEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)((action) => editInvoicingCustomerDetailViewReducer_1.updateInvoicingCustomerDetail.match(action) ||
20
+ editInvoicingCustomerDetailViewReducer_1.fetchInvoicingCustomerDetailPage.match(action)), (0, operators_1.withLatestFrom)(state$), (0, operators_1.mergeMap)(([action, state]) => {
16
21
  const { id } = action.payload;
22
+ if (id == null) {
23
+ return rxjs_1.EMPTY;
24
+ }
25
+ // The entity alone does not say the whole record is loaded — the list
26
+ // endpoints merge their own list-shaped rows into the same store. Only a
27
+ // completed detail load does, which is also exactly when the page's
28
+ // cache-guarded fetch issues no request and this is the sole seed.
29
+ // A forced refetch is the caller asking for fresh data: the response will
30
+ // seed, and seeding first from the entity as it stands would mark the
31
+ // draft loaded and lock that response out.
32
+ if (editInvoicingCustomerDetailViewReducer_1.fetchInvoicingCustomerDetailPage.match(action) &&
33
+ (action.payload.cacheOverride === true ||
34
+ state.editInvoicingCustomerDetailViewState.recordStateById[id]
35
+ ?.fetchState !== 'Completed')) {
36
+ return rxjs_1.EMPTY;
37
+ }
38
+ // Nothing to seed from on a cold open; the detail response triggers this
39
+ // again once it lands.
17
40
  const customer = (0, invoicingCustomerSelector_1.getInvoicingCustomerById)(state.invoicingCustomerState, id);
18
41
  if (customer == null) {
19
42
  return rxjs_1.EMPTY;
@@ -55,6 +55,10 @@ export declare const runInvoicingSubscriptionAction: import("@reduxjs/toolkit").
55
55
  id: ID;
56
56
  }, "editInvoicingSubscriptionDetailView/updateInvoicingSubscriptionDetailFailure">, updateInvoicingSubscriptionFormDraft: import("@reduxjs/toolkit").ActionCreatorWithPayload<UpdateInvoicingSubscriptionFormDraftPayload, "editInvoicingSubscriptionDetailView/updateInvoicingSubscriptionFormDraft">, submitInvoicingSubscriptionForm: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: SubmitInvoicingSubscriptionFormPayload], SubmitInvoicingSubscriptionFormPayload, "editInvoicingSubscriptionDetailView/submitInvoicingSubscriptionForm", never, never>, submitInvoicingSubscriptionFormSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
57
57
  subscriptionId: ID;
58
- }, "editInvoicingSubscriptionDetailView/submitInvoicingSubscriptionFormSuccess">, submitInvoicingSubscriptionFormFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "editInvoicingSubscriptionDetailView/submitInvoicingSubscriptionFormFailure">, resetEditInvoicingSubscriptionDetailView: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"editInvoicingSubscriptionDetailView/resetEditInvoicingSubscriptionDetailView">, initializeInvoicingSubscriptionAddress: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: InitializeInvoicingSubscriptionAddressPayload], InitializeInvoicingSubscriptionAddressPayload, "editInvoicingSubscriptionDetailView/initializeInvoicingSubscriptionAddress", never, never>, syncInvoicingSubscriptionCoupons: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: SyncInvoicingSubscriptionCouponsPayload], SyncInvoicingSubscriptionCouponsPayload, "editInvoicingSubscriptionDetailView/syncInvoicingSubscriptionCoupons", never, never>;
58
+ }, "editInvoicingSubscriptionDetailView/submitInvoicingSubscriptionFormSuccess">, submitInvoicingSubscriptionFormFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "editInvoicingSubscriptionDetailView/submitInvoicingSubscriptionFormFailure">, resetEditInvoicingSubscriptionDetailView: import("@reduxjs/toolkit").ActionCreatorWithOptionalPayload<{
59
+ id?: ID;
60
+ } | undefined, "editInvoicingSubscriptionDetailView/resetEditInvoicingSubscriptionDetailView">, initializeInvoicingSubscriptionAddress: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: InitializeInvoicingSubscriptionAddressPayload], InitializeInvoicingSubscriptionAddressPayload, "editInvoicingSubscriptionDetailView/initializeInvoicingSubscriptionAddress", never, never>, claimInvoicingSubscriptionShippingAddress: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
61
+ id: ID;
62
+ }, "editInvoicingSubscriptionDetailView/claimInvoicingSubscriptionShippingAddress">, syncInvoicingSubscriptionCoupons: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: SyncInvoicingSubscriptionCouponsPayload], SyncInvoicingSubscriptionCouponsPayload, "editInvoicingSubscriptionDetailView/syncInvoicingSubscriptionCoupons", never, never>;
59
63
  declare const _default: import("redux").Reducer<EditInvoicingSubscriptionDetailViewState>;
60
64
  export default _default;