@veloceapps/sdk 11.0.0-10 → 11.0.0-100

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 (183) hide show
  1. package/cms/cms.actions.d.ts +94 -29
  2. package/cms/components/element-renderer/element-renderer.component.d.ts +3 -10
  3. package/cms/components/preview/preview.component.d.ts +5 -6
  4. package/cms/components/preview/preview.types.d.ts +0 -4
  5. package/cms/services/element-context.service.d.ts +0 -1
  6. package/cms/types/common.types.d.ts +2 -0
  7. package/cms/types/index.d.ts +0 -1
  8. package/cms/utils/path.utils.d.ts +1 -2
  9. package/cms/vendor-map.d.ts +18 -40
  10. package/core/index.d.ts +1 -1
  11. package/core/modules/configuration/index.d.ts +4 -4
  12. package/core/modules/configuration/services/configuration-runtime.service.d.ts +8 -19
  13. package/core/modules/configuration/services/configuration-state.service.d.ts +8 -8
  14. package/core/modules/configuration/services/configuration.service.d.ts +24 -52
  15. package/core/modules/configuration/services/guided-selling.service.d.ts +15 -0
  16. package/core/modules/configuration/services/test-mode-configuration.service.d.ts +23 -0
  17. package/core/modules/configuration/types/configuration-runtime.types.d.ts +0 -5
  18. package/core/modules/configuration/types/configuration.types.d.ts +4 -2
  19. package/core/modules/configuration/types/index.d.ts +2 -0
  20. package/core/modules/flow-configuration/index.d.ts +0 -3
  21. package/core/modules/flow-configuration/services/flow-configuration.service.d.ts +11 -38
  22. package/core/operators/filter-successful-execute.operator.d.ts +3 -0
  23. package/core/operators/index.d.ts +1 -0
  24. package/core/services/catalog-products.service.d.ts +11 -0
  25. package/core/services/flow-info.service.d.ts +27 -12
  26. package/core/services/flow-state-configuration.service.d.ts +9 -8
  27. package/core/services/flow-state.service.d.ts +12 -24
  28. package/core/services/index.d.ts +3 -3
  29. package/core/services/integration.state.d.ts +1 -1
  30. package/core/services/product-images.service.d.ts +3 -3
  31. package/core/services/runtime-settings.service.d.ts +1 -1
  32. package/core/services/sales-transaction.service.d.ts +27 -0
  33. package/core/types/flow-customization.types.d.ts +2 -2
  34. package/core/types/flow-state.types.d.ts +2 -2
  35. package/core/types/index.d.ts +0 -1
  36. package/core/utils/index.d.ts +2 -2
  37. package/core/utils/transaction-item.utils.d.ts +7 -0
  38. package/core/utils/transaction-item.worker.d.ts +8 -0
  39. package/esm2020/cms/cms.actions.mjs +93 -71
  40. package/esm2020/cms/cms.default.mjs +2 -3
  41. package/esm2020/cms/components/element-renderer/element-renderer.component.mjs +7 -64
  42. package/esm2020/cms/components/element-tools-panel/element-tools-panel.component.mjs +3 -3
  43. package/esm2020/cms/components/preview/preview.component.mjs +19 -28
  44. package/esm2020/cms/components/preview/preview.types.mjs +1 -1
  45. package/esm2020/cms/services/element-context.service.mjs +1 -1
  46. package/esm2020/cms/types/common.types.mjs +1 -1
  47. package/esm2020/cms/types/index.mjs +1 -2
  48. package/esm2020/cms/utils/element.utils.mjs +3 -3
  49. package/esm2020/cms/utils/elements-resolver.mjs +16 -5
  50. package/esm2020/cms/utils/path.utils.mjs +1 -10
  51. package/esm2020/cms/vendor-map.mjs +18 -18
  52. package/esm2020/core/core.module.mjs +7 -7
  53. package/esm2020/core/index.mjs +2 -2
  54. package/esm2020/core/modules/configuration/configuration.module.mjs +17 -4
  55. package/esm2020/core/modules/configuration/index.mjs +5 -5
  56. package/esm2020/core/modules/configuration/services/configuration-runtime.service.mjs +16 -101
  57. package/esm2020/core/modules/configuration/services/configuration-state.service.mjs +69 -77
  58. package/esm2020/core/modules/configuration/services/configuration.service.mjs +125 -247
  59. package/esm2020/core/modules/configuration/services/guided-selling.service.mjs +62 -0
  60. package/esm2020/core/modules/configuration/services/test-mode-configuration.service.mjs +74 -0
  61. package/esm2020/core/modules/configuration/types/configuration-runtime.types.mjs +1 -1
  62. package/esm2020/core/modules/configuration/types/configuration.types.mjs +1 -1
  63. package/esm2020/core/modules/configuration/types/index.mjs +3 -0
  64. package/esm2020/core/modules/flow-configuration/flow-configuration.module.mjs +3 -4
  65. package/esm2020/core/modules/flow-configuration/index.mjs +1 -4
  66. package/esm2020/core/modules/flow-configuration/services/flow-configuration.service.mjs +44 -128
  67. package/esm2020/core/operators/filter-successful-execute.operator.mjs +5 -0
  68. package/esm2020/core/operators/index.mjs +2 -0
  69. package/esm2020/core/services/catalog-products.service.mjs +25 -0
  70. package/esm2020/core/services/flow-info.service.mjs +82 -31
  71. package/esm2020/core/services/flow-state-configuration.service.mjs +55 -25
  72. package/esm2020/core/services/flow-state.service.mjs +58 -180
  73. package/esm2020/core/services/index.mjs +4 -4
  74. package/esm2020/core/services/integration.state.mjs +2 -2
  75. package/esm2020/core/services/product-images.service.mjs +8 -8
  76. package/esm2020/core/services/runtime-settings.service.mjs +3 -3
  77. package/esm2020/core/services/sales-transaction.service.mjs +67 -0
  78. package/esm2020/core/types/flow-customization.types.mjs +1 -1
  79. package/esm2020/core/types/flow-state.types.mjs +1 -1
  80. package/esm2020/core/types/index.mjs +1 -2
  81. package/esm2020/core/utils/index.mjs +3 -3
  82. package/esm2020/core/utils/transaction-item.utils.mjs +60 -0
  83. package/esm2020/core/utils/transaction-item.worker.mjs +16 -0
  84. package/esm2020/src/components/flow-header/flow-header.component.mjs +8 -12
  85. package/esm2020/src/components/guided-selling/guided-selling.component.mjs +8 -12
  86. package/esm2020/src/flow-routing.module.mjs +12 -41
  87. package/esm2020/src/flow.component.mjs +5 -5
  88. package/esm2020/src/guards/flow.guard.mjs +13 -14
  89. package/esm2020/src/guards/product-unload.guard.mjs +7 -9
  90. package/esm2020/src/index.mjs +1 -3
  91. package/esm2020/src/pages/assets/assets.component.mjs +8 -9
  92. package/esm2020/src/pages/catalog/catalog.component.mjs +8 -9
  93. package/esm2020/src/pages/debug/debug.component.mjs +14 -23
  94. package/esm2020/src/pages/product/product.component.mjs +12 -89
  95. package/esm2020/src/pages/product/product.module.mjs +5 -5
  96. package/esm2020/src/pages/record-not-found/record-not-found.component.mjs +5 -6
  97. package/esm2020/src/pages/shopping-cart/shopping-cart.component.mjs +8 -9
  98. package/esm2020/src/resolvers/flow.resolver.mjs +10 -18
  99. package/esm2020/src/resolvers/pcm-model.resolver.mjs +12 -0
  100. package/esm2020/src/resolvers/sales-transaction.resolver.mjs +64 -0
  101. package/esm2020/src/resolvers/ui-definition.resolver.mjs +42 -0
  102. package/esm2020/src/services/flow-dialog.service.mjs +10 -31
  103. package/esm2020/src/services/flow-router.service.mjs +16 -33
  104. package/esm2020/src/services/flow.service.mjs +15 -54
  105. package/esm2020/src/types/index.mjs +2 -3
  106. package/esm2020/src/types/route.types.mjs +1 -1
  107. package/fesm2015/veloceapps-sdk-cms.mjs +163 -309
  108. package/fesm2015/veloceapps-sdk-cms.mjs.map +1 -1
  109. package/fesm2015/veloceapps-sdk-core.mjs +900 -1670
  110. package/fesm2015/veloceapps-sdk-core.mjs.map +1 -1
  111. package/fesm2015/veloceapps-sdk.mjs +192 -824
  112. package/fesm2015/veloceapps-sdk.mjs.map +1 -1
  113. package/fesm2020/veloceapps-sdk-cms.mjs +159 -300
  114. package/fesm2020/veloceapps-sdk-cms.mjs.map +1 -1
  115. package/fesm2020/veloceapps-sdk-core.mjs +976 -1755
  116. package/fesm2020/veloceapps-sdk-core.mjs.map +1 -1
  117. package/fesm2020/veloceapps-sdk.mjs +192 -818
  118. package/fesm2020/veloceapps-sdk.mjs.map +1 -1
  119. package/package.json +1 -1
  120. package/src/components/flow-header/flow-header.component.d.ts +3 -3
  121. package/src/components/guided-selling/guided-selling.component.d.ts +3 -3
  122. package/src/flow-routing.module.d.ts +1 -2
  123. package/src/flow.component.d.ts +2 -2
  124. package/src/guards/product-unload.guard.d.ts +5 -6
  125. package/src/index.d.ts +0 -2
  126. package/src/pages/assets/assets.component.d.ts +3 -3
  127. package/src/pages/catalog/catalog.component.d.ts +3 -3
  128. package/src/pages/debug/debug.component.d.ts +2 -5
  129. package/src/pages/product/product.component.d.ts +5 -14
  130. package/src/pages/product/product.module.d.ts +1 -1
  131. package/src/pages/record-not-found/record-not-found.component.d.ts +2 -3
  132. package/src/pages/shopping-cart/shopping-cart.component.d.ts +3 -3
  133. package/src/resolvers/flow.resolver.d.ts +5 -6
  134. package/src/resolvers/pcm-model.resolver.d.ts +3 -0
  135. package/src/resolvers/sales-transaction.resolver.d.ts +18 -0
  136. package/src/resolvers/ui-definition.resolver.d.ts +3 -0
  137. package/src/services/flow-dialog.service.d.ts +6 -8
  138. package/src/services/flow-router.service.d.ts +4 -6
  139. package/src/services/flow.service.d.ts +3 -7
  140. package/src/types/index.d.ts +1 -2
  141. package/src/types/route.types.d.ts +0 -5
  142. package/cms/plugins/configuration.plugin.d.ts +0 -23
  143. package/cms/types/configuration.types.d.ts +0 -21
  144. package/core/modules/configuration/helpers.d.ts +0 -6
  145. package/core/modules/configuration/services/runtime-context.service.d.ts +0 -12
  146. package/core/modules/flow-configuration/services/flow-update.service.d.ts +0 -13
  147. package/core/modules/flow-configuration/types/update.types.d.ts +0 -12
  148. package/core/services/context.service.d.ts +0 -23
  149. package/core/services/quote-draft.service.d.ts +0 -50
  150. package/core/types/runtime.types.d.ts +0 -30
  151. package/core/utils/line-item.utils.d.ts +0 -25
  152. package/core/utils/line-item.worker.d.ts +0 -9
  153. package/esm2020/cms/plugins/configuration.plugin.mjs +0 -109
  154. package/esm2020/cms/types/configuration.types.mjs +0 -2
  155. package/esm2020/core/modules/configuration/helpers.mjs +0 -73
  156. package/esm2020/core/modules/configuration/services/runtime-context.service.mjs +0 -45
  157. package/esm2020/core/modules/flow-configuration/services/flow-update.service.mjs +0 -138
  158. package/esm2020/core/modules/flow-configuration/types/update.types.mjs +0 -2
  159. package/esm2020/core/services/context.service.mjs +0 -91
  160. package/esm2020/core/services/quote-draft.service.mjs +0 -192
  161. package/esm2020/core/types/runtime.types.mjs +0 -16
  162. package/esm2020/core/utils/line-item.utils.mjs +0 -187
  163. package/esm2020/core/utils/line-item.worker.mjs +0 -19
  164. package/esm2020/src/guards/context.guard.mjs +0 -91
  165. package/esm2020/src/guards/index.mjs +0 -2
  166. package/esm2020/src/pages/remote/remote.component.mjs +0 -342
  167. package/esm2020/src/pages/remote/remote.module.mjs +0 -20
  168. package/esm2020/src/pages/remote/remote.types.mjs +0 -2
  169. package/esm2020/src/resolvers/quote.resolver.mjs +0 -82
  170. package/esm2020/src/types/context-route.types.mjs +0 -2
  171. package/esm2020/src/types/metrics.types.mjs +0 -2
  172. package/esm2020/src/utils/flow.utils.mjs +0 -25
  173. package/esm2020/src/utils/index.mjs +0 -2
  174. package/src/guards/context.guard.d.ts +0 -19
  175. package/src/guards/index.d.ts +0 -1
  176. package/src/pages/remote/remote.component.d.ts +0 -46
  177. package/src/pages/remote/remote.module.d.ts +0 -10
  178. package/src/pages/remote/remote.types.d.ts +0 -4
  179. package/src/resolvers/quote.resolver.d.ts +0 -19
  180. package/src/types/context-route.types.d.ts +0 -5
  181. package/src/types/metrics.types.d.ts +0 -5
  182. package/src/utils/flow.utils.d.ts +0 -8
  183. package/src/utils/index.d.ts +0 -1
@@ -1,249 +1,243 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, InjectionToken, Optional, Inject, NgModule, inject, Directive, Input, LOCALE_ID, Pipe } from '@angular/core';
3
- import { UUID, ConfigurationContextMode, ConfigurationContext, UITemplateType, QuoteDraft, isDefined, ConfigurationProcessorTypes, EntityUtil, DEFAULT_CURRENCY_ISO_CODE, DEFAULT_CURRENCY_SYMBOL, validateDateFormat, DEFAULT_DATE_FORMAT, DEFAULT_DECIMALS_COUNT, getSupportedDateFormats, DEFAULT_DECIMAL_SEPARATOR, DEFAULT_THOUSANDS_SEPARATOR, DEFAULT_ACTION_CODE_LABELS, parseJsonSafely, ConfigurationMode, extractErrorDetails, ConfigurationTranslatorUtils, ChargeGroupUtils, RuntimeModel, isNotLegacyUIDefinition, SalesforceIdUtils, DEFAULT_TIME_FORMAT, formatNumber } from '@veloceapps/core';
4
- import * as i1 from '@veloceapps/api';
3
+ import { DEFAULT_CURRENCY_ISO_CODE, DEFAULT_CURRENCY_SYMBOL, validateDateFormat, DEFAULT_DATE_FORMAT, DEFAULT_DECIMALS_COUNT, getSupportedDateFormats, DEFAULT_DECIMAL_SEPARATOR, DEFAULT_THOUSANDS_SEPARATOR, DEFAULT_ACTION_CODE_LABELS, parseJsonSafely, isDefined, UITemplateType, SalesforceIdUtils, UUID, extractErrorDetails, ConfigurationProcessorTypes, EntityUtil, DEFAULT_TIME_FORMAT, formatNumber } from '@veloceapps/core';
4
+ import * as i3 from '@veloceapps/api';
5
5
  import { ApiModule } from '@veloceapps/api';
6
- import { BehaviorSubject, switchMap, map as map$1, tap as tap$1, noop, catchError, throwError, forkJoin, of, zip, combineLatest, Subject, filter as filter$1, shareReplay as shareReplay$1, finalize, takeUntil, buffer, debounceTime, share, take as take$1, distinctUntilChanged } from 'rxjs';
7
- import { map, filter, tap, switchMap as switchMap$1, skip, take, shareReplay, catchError as catchError$1, finalize as finalize$1, first } from 'rxjs/operators';
8
- import { merge, isEqual, cloneDeep, assign, flatten, entries, sortBy, map as map$2, uniqBy, omit, transform } from 'lodash';
9
6
  import * as i6 from '@veloceapps/components';
10
- import { ToastType, ConfirmationComponent, ConfirmationDialogModule } from '@veloceapps/components';
11
- import { HttpErrorResponse } from '@angular/common/http';
12
- import * as i5 from 'primeng/api';
13
- import * as i6$1 from 'primeng/dynamicdialog';
14
- import moment from 'moment';
7
+ import { ToastType, ConfirmationDialogModule } from '@veloceapps/components';
8
+ import * as i1 from '@veloceapps/api/v2';
9
+ import { tap, BehaviorSubject, map, filter, switchMap, of, forkJoin, noop, throwError, Subject, catchError as catchError$1, combineLatest, finalize as finalize$1, buffer, debounceTime, share, take, distinctUntilChanged, shareReplay, takeUntil, first } from 'rxjs';
10
+ import { uniqBy, flatten, omit, cloneDeep, assign, isEqual } from 'lodash';
11
+ import * as i2 from 'primeng/api';
12
+ import { filter as filter$1, map as map$1, tap as tap$1, catchError, finalize } from 'rxjs/operators';
15
13
  import { NgControl } from '@angular/forms';
16
14
  import 'primeng/calendar';
17
15
  import { DATE_PIPE_DEFAULT_OPTIONS, formatDate } from '@angular/common';
18
16
 
19
- const getDefaultLineItem = (context, uiDefinitionProperties, qty = 1) => {
20
- const id = UUID.UUID();
21
- const attributes = [];
22
- const lineItems = [];
23
- return {
24
- id,
25
- type: uiDefinitionProperties.rootType ?? '',
26
- cfgStatus: 'Default',
27
- actionCode: 'ADD',
28
- qty,
29
- attributes,
30
- lineItems,
31
- productName: context.properties?.['displayName'] || context.productName,
32
- productId: context.productId ?? '',
33
- ...(uiDefinitionProperties.offeringId ? { offeringId: uiDefinitionProperties.offeringId } : {}),
34
- };
35
- };
36
- const getGuidedSellingConfigurationRequest = (data, context) => {
37
- const _context = { ...context };
38
- delete _context.configurationToken;
39
- const properties = { ...context.properties };
40
- delete properties['ConfigurationToken'];
41
- return {
42
- mode: 'SEARCH',
43
- step: 'START',
44
- attributeDomainMode: 'ALL',
45
- context: {
46
- ..._context,
47
- mode: ConfigurationContextMode.TEST,
48
- properties: {
49
- ...properties,
50
- ModelId: data.modelId,
51
- Name: 'Veloce Guided Selling',
52
- PricingEnabled: 'false',
53
- RuntimeMode: 'TEST',
54
- },
55
- },
56
- lineItem: {
57
- actionCode: 'ADD',
58
- cfgStatus: 'Default',
59
- id: UUID.UUID(),
60
- qty: 1,
61
- type: data.modelType,
62
- attributes: Object.entries(data.attributesMap).map(([name, value]) => ({
63
- name,
64
- value,
65
- cfgStatus: 'User',
66
- })),
67
- },
68
- };
69
- };
70
- const generateConfigurationLineItem = (props, qty = 1) => {
71
- const id = UUID.UUID();
72
- const attributes = Object.entries(props.attributesMap ?? {}).map(([name, value]) => ({
73
- name,
74
- value,
75
- cfgStatus: 'User',
76
- }));
77
- const lineItems = [];
78
- return {
79
- id,
80
- type: props.product.typeName ?? '',
81
- cfgStatus: 'Default',
82
- actionCode: 'ADD',
83
- qty,
84
- attributes,
85
- lineItems,
86
- productName: props.product.name,
87
- productId: props.product.id ?? '',
88
- };
89
- };
90
-
91
- class ContextService {
92
- constructor(contextApiService) {
93
- this.contextApiService = contextApiService;
94
- this.context = new BehaviorSubject(null);
17
+ class ConfigurationRuntimeService {
18
+ constructor(pcmApiService) {
19
+ this.pcmApiService = pcmApiService;
20
+ this.uiDefinitionContainer = null;
95
21
  }
96
- get isInitialized() {
97
- return Boolean(this.context.value);
22
+ get uiDefinitionProps() {
23
+ return this.uiDefinitionContainer?.source.properties ?? {};
98
24
  }
99
- get isInitialized$() {
100
- return this.context.pipe(map(Boolean));
25
+ reset() {
26
+ this.uiDefinitionContainer = null;
27
+ this.initializationProps = undefined;
28
+ this.pcmModel = undefined;
29
+ }
30
+ init$(props) {
31
+ this.initializationProps = props;
32
+ return this.pcmApiService.fetchPCMByProductId(props.productId).pipe(tap(pcmModel => (this.pcmModel = pcmModel)));
101
33
  }
102
- get mode() {
103
- return this.resolve().properties['#mode'];
34
+ }
35
+ ConfigurationRuntimeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationRuntimeService, deps: [{ token: i1.PCMApiService }], target: i0.ɵɵFactoryTarget.Injectable });
36
+ ConfigurationRuntimeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationRuntimeService });
37
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationRuntimeService, decorators: [{
38
+ type: Injectable
39
+ }], ctorParameters: function () { return [{ type: i1.PCMApiService }]; } });
40
+
41
+ const FLOW_CUSTOMIZATION = new InjectionToken('FLOW_CUSTOMIZATION');
42
+
43
+ class RuntimeSettingsService {
44
+ constructor(configurationSettingsApiService) {
45
+ this.configurationSettingsApiService = configurationSettingsApiService;
46
+ this.configurationSettings$ = new BehaviorSubject({});
47
+ this.currencySettings$ = new BehaviorSubject({
48
+ iso: DEFAULT_CURRENCY_ISO_CODE,
49
+ symbol: DEFAULT_CURRENCY_SYMBOL,
50
+ });
51
+ this.shoppingCartSettings$ = new BehaviorSubject([]);
52
+ this.getCurrencySymbol = (locale, currency) => {
53
+ return (0)
54
+ .toLocaleString(locale, { style: 'currency', currency, minimumFractionDigits: 0, maximumFractionDigits: 0 })
55
+ .replace(/\d/g, '')
56
+ .trim();
57
+ };
104
58
  }
105
- get isEditMode$() {
106
- return this.resolve$().pipe(map(() => this.isEditMode));
59
+ create() {
60
+ return this.configurationSettingsApiService.fetchSettings().pipe(map(settings => this.parseConfigurationSettings(settings)), tap(configurationSettings => {
61
+ this.configurationSettings$.next(configurationSettings);
62
+ this.addShoppingCartSettings(configurationSettings['shopping-cart'] ?? []);
63
+ this.formattingSettings = this.getFormattingSettings();
64
+ }), map(() => undefined));
107
65
  }
108
- get isEditMode() {
109
- const context = this.resolve();
110
- if (context.properties['#mode'] === ConfigurationContextMode.ACCOUNT) {
111
- return true;
112
- }
113
- if (context.properties['#mode'] === ConfigurationContextMode.QUOTE) {
114
- return context.properties.Status === 'Draft';
66
+ initCurrency(iso) {
67
+ if (iso) {
68
+ const symbol = this.getCurrencySymbol('en-US', iso);
69
+ this.currencySettings$.next({ iso, symbol });
70
+ if (this.formattingSettings) {
71
+ this.formattingSettings.currencySymbol = symbol;
72
+ }
115
73
  }
116
- return false;
117
74
  }
118
- resolve() {
119
- if (!this.context.value) {
120
- throw new Error('Context is not initialized yet!');
75
+ getFormattingSettings() {
76
+ if (this.formattingSettings) {
77
+ return this.formattingSettings;
121
78
  }
122
- return { ...this.context.value };
79
+ const shoppingCartSettings = this.getConfigurationSettings()['shopping-cart']?.reduce((acc, setting) => {
80
+ return { ...acc, [setting.id]: setting.properties };
81
+ }, {});
82
+ const currencySettings = this.getCurrencySettings();
83
+ const dateFormat = (validateDateFormat(shoppingCartSettings?.DATE_FORMAT ?? '') && shoppingCartSettings?.DATE_FORMAT) ||
84
+ DEFAULT_DATE_FORMAT;
85
+ const decimalSeparator = shoppingCartSettings?.DECIMAL_SEPARATOR;
86
+ const thousandsSeparator = shoppingCartSettings?.THOUSANDS_SEPARATOR;
87
+ // the number of decimal places can be 0
88
+ const priceScale = shoppingCartSettings?.PRICE_SCALE;
89
+ const decimalsCount = priceScale !== null && priceScale !== '' && !isNaN(Number(priceScale)) && Number(priceScale) >= 0
90
+ ? Number(priceScale)
91
+ : DEFAULT_DECIMALS_COUNT;
92
+ const actionCodeSettings = shoppingCartSettings?.STATUS_LABEL;
93
+ return {
94
+ currencySymbol: currencySettings.symbol,
95
+ dateFormats: getSupportedDateFormats(dateFormat),
96
+ decimalsCount,
97
+ decimalSeparator: decimalSeparator !== undefined && ['.', ','].includes(decimalSeparator)
98
+ ? decimalSeparator
99
+ : DEFAULT_DECIMAL_SEPARATOR,
100
+ // thousands separator can be a blank value, so it can also be null
101
+ thousandsSeparator: thousandsSeparator !== undefined && ['.', ',', '', null].includes(thousandsSeparator)
102
+ ? thousandsSeparator || ''
103
+ : DEFAULT_THOUSANDS_SEPARATOR,
104
+ actionCodeLabels: actionCodeSettings?.length
105
+ ? actionCodeSettings.reduce((result, setting) => ({ ...result, [setting.status_label]: setting.custom_label }), {})
106
+ : DEFAULT_ACTION_CODE_LABELS,
107
+ };
123
108
  }
124
- resolve$() {
125
- return this.context.pipe(filter((ctx) => Boolean(ctx)));
109
+ getConfigurationSettings() {
110
+ return this.configurationSettings$.value;
126
111
  }
127
- create(headerId, mode) {
128
- return this.contextApiService.getContext(headerId, mode).pipe(tap(context => this.context.next(merge(new ConfigurationContext(headerId, mode), context))), map(() => this.resolve()));
112
+ getShoppingCartSettings() {
113
+ return this.shoppingCartSettings$.value;
129
114
  }
130
- initTestMode() {
131
- return this.create('TestId', ConfigurationContextMode.TEST).pipe(map(context => {
132
- return this.update({
133
- properties: {
134
- ...context.properties,
135
- RuntimeMode: ConfigurationContextMode.TEST,
136
- StartDate: new Date().toISOString().substring(0, 10),
137
- standalone: 'true',
138
- },
139
- });
140
- }));
115
+ getCurrencySettings() {
116
+ return this.currencySettings$.value;
141
117
  }
142
- update(partialContext) {
143
- const originalContext = this.resolve();
144
- const updatedContext = {
145
- ...originalContext,
146
- ...partialContext,
147
- properties: {
148
- ...originalContext.properties,
149
- ...partialContext.properties,
150
- },
151
- };
152
- this.context.next(updatedContext);
153
- return updatedContext;
154
- }
155
- set(context) {
156
- const originalContext = this.resolve();
157
- const updatedContext = {
158
- ...originalContext,
159
- ...context,
160
- };
161
- this.context.next(updatedContext);
162
- return updatedContext;
118
+ parseConfigurationSettings(settings) {
119
+ return settings.reduce((acc, setting) => {
120
+ switch (setting.key) {
121
+ case 'shopping-cart':
122
+ acc['shopping-cart'] = parseJsonSafely(setting.value, []);
123
+ break;
124
+ case 'navigation':
125
+ acc.navigation = parseJsonSafely(setting.value, {});
126
+ break;
127
+ case 'flows':
128
+ acc.flows = parseJsonSafely(setting.value, []);
129
+ break;
130
+ default:
131
+ acc[setting.key] = setting.value;
132
+ }
133
+ return acc;
134
+ }, {});
163
135
  }
164
- delete() {
165
- this.context.next(null);
136
+ addShoppingCartSettings(settings) {
137
+ // uniqBy removes items with the biggest index
138
+ const newSettings = uniqBy([...settings, ...this.shoppingCartSettings$.value], 'id');
139
+ this.shoppingCartSettings$.next(newSettings);
166
140
  }
167
141
  }
168
- ContextService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ContextService, deps: [{ token: i1.ContextApiService }], target: i0.ɵɵFactoryTarget.Injectable });
169
- ContextService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ContextService });
170
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ContextService, decorators: [{
142
+ RuntimeSettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeSettingsService, deps: [{ token: i1.ConfigurationSettingsApiService }], target: i0.ɵɵFactoryTarget.Injectable });
143
+ RuntimeSettingsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeSettingsService });
144
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeSettingsService, decorators: [{
171
145
  type: Injectable
172
- }], ctorParameters: function () { return [{ type: i1.ContextApiService }]; } });
173
-
174
- const FLOW_CUSTOMIZATION = new InjectionToken('FLOW_CUSTOMIZATION');
175
-
176
- const FORMATTING_SETTINGS_TOKEN = new InjectionToken('Summary of formatting settings for variant types of data, e.g. numbers, text, dates, etc');
177
-
178
- var RuntimeMode;
179
- (function (RuntimeMode) {
180
- RuntimeMode[RuntimeMode["TEST"] = 0] = "TEST";
181
- RuntimeMode[RuntimeMode["PROD"] = 1] = "PROD";
182
- })(RuntimeMode || (RuntimeMode = {}));
183
- var RuntimeOperation;
184
- (function (RuntimeOperation) {
185
- RuntimeOperation["INIT"] = "INIT";
186
- RuntimeOperation["UPDATE"] = "UPDATE";
187
- })(RuntimeOperation || (RuntimeOperation = {}));
188
- var RuntimeStep;
189
- (function (RuntimeStep) {
190
- RuntimeStep["START"] = "START";
191
- RuntimeStep["UPDATE"] = "UPDATE";
192
- })(RuntimeStep || (RuntimeStep = {}));
193
-
194
- const UI_DEFINITION_VERSION = 3;
146
+ }], ctorParameters: function () { return [{ type: i1.ConfigurationSettingsApiService }]; } });
195
147
 
196
148
  class FlowInfoService {
197
149
  get flow() {
150
+ if (!this.flowSubj$.value) {
151
+ throw new Error(`Flow not initialized yet`);
152
+ }
198
153
  return this.flowSubj$.value;
199
154
  }
200
- set flow(value) {
201
- this.flowSubj$.next(value);
155
+ get isFlowInitialized() {
156
+ return Boolean(this.flowSubj$.value);
157
+ }
158
+ get context() {
159
+ if (!this.contextSubj$.value) {
160
+ throw new Error('Context is not initialized yet!');
161
+ }
162
+ return { ...this.contextSubj$.value };
163
+ }
164
+ get context$() {
165
+ return this.contextSubj$.asObservable().pipe(filter(isDefined));
202
166
  }
203
- get isLegacy() {
204
- return !!this.flow && this.flow?.properties.stateful == null;
167
+ get templates() {
168
+ return this.templatesSubj$.value;
169
+ }
170
+ get isFlowEngineInitialized$() {
171
+ return this.templates$.pipe(map(v => Boolean(v.FLOW_ENGINE)));
205
172
  }
206
173
  get isStateful() {
207
174
  return !!this.flow?.properties.stateful;
208
175
  }
209
- constructor(flowsApiService, templatesApiService, customizationService) {
210
- this.flowsApiService = flowsApiService;
211
- this.templatesApiService = templatesApiService;
176
+ constructor(runtimeSettingsService, templatesAdminApiService, customizationService) {
177
+ this.runtimeSettingsService = runtimeSettingsService;
178
+ this.templatesAdminApiService = templatesAdminApiService;
212
179
  this.customizationService = customizationService;
213
- this.templates = {};
214
180
  this.defaultTemplates = {
215
181
  flowEngine: 'Flow Engine',
216
182
  };
217
183
  this.flowSubj$ = new BehaviorSubject(null);
184
+ this.templatesSubj$ = new BehaviorSubject({});
185
+ this.contextSubj$ = new BehaviorSubject(null);
218
186
  this.flow$ = this.flowSubj$.asObservable();
187
+ this.templates$ = this.templatesSubj$.asObservable();
188
+ }
189
+ reset() {
190
+ this.flowSubj$.next(null);
191
+ this.templatesSubj$.next({});
192
+ this.contextSubj$.next(null);
219
193
  }
220
194
  init$(flowId, routeQueryParams) {
221
- return this.flowsApiService.getFlow(flowId).pipe(switchMap(flow => this.initFlowTemplates$(flow).pipe(map$1(() => flow))), tap$1(flow => {
222
- this.params = { ...routeQueryParams, ...flow.properties.queryParams };
223
- this.flowSubj$.next(flow);
224
- }), map$1(noop), catchError(e => {
225
- this.flowSubj$.next(null);
226
- return throwError(() => e);
227
- }));
195
+ return this.initFlow$(flowId, routeQueryParams).pipe(switchMap(() => this.initFlowTemplates$()));
228
196
  }
229
- cleanup() {
230
- this.flowSubj$.next(null);
231
- this.params = undefined;
232
- this.templates = {};
197
+ updateContext(update) {
198
+ this.contextSubj$.next({
199
+ ...this.context,
200
+ ...update,
201
+ });
202
+ }
203
+ initFlow$(flowId, routeQueryParams) {
204
+ const flow = this.runtimeSettingsService.getConfigurationSettings()['flows']?.find(({ id }) => flowId === id);
205
+ if (!flow) {
206
+ this.flowSubj$.next(null);
207
+ throw new Error(`Flow with flowId=${flowId} is not defined`);
208
+ }
209
+ const headerId = routeQueryParams['headerId'];
210
+ if (typeof headerId !== 'string') {
211
+ throw new Error(`Please provide 'headerId'`);
212
+ }
213
+ const mode = this.getFlowContextMode(headerId);
214
+ // Restrict if mode is not defined
215
+ if (mode == null) {
216
+ throw new Error('Mode is undefined');
217
+ }
218
+ this.contextSubj$.next({
219
+ ...flow.properties.queryParams,
220
+ ...routeQueryParams,
221
+ mode,
222
+ });
223
+ this.flowSubj$.next(flow);
224
+ return of(undefined);
233
225
  }
234
- initFlowTemplates$(flow) {
226
+ initFlowTemplates$() {
235
227
  return forkJoin([
236
- this.templatesApiService.fetchTemplates$(),
228
+ this.templatesAdminApiService.fetchTemplates$(),
237
229
  this.customizationService?.getTemplates?.() ?? of([]),
238
- ]).pipe(map$1(([templates, localTemplates]) => {
239
- Object.entries({ ...this.defaultTemplates, ...flow.properties.templates }).forEach(([key, name]) => {
230
+ ]).pipe(map(([templates, localTemplates]) => {
231
+ const newValue = {};
232
+ Object.entries({ ...this.defaultTemplates, ...(this.flow?.properties.templates ?? {}) }).forEach(([key, name]) => {
240
233
  const type = this.remapTemplateName(key);
241
234
  if (type) {
242
- this.templates[type] =
235
+ newValue[type] =
243
236
  localTemplates.find(template => template.name === name && template.type === type) ??
244
237
  templates.find(template => template.name === name && template.type === type);
245
238
  }
246
239
  });
240
+ this.templatesSubj$.next(newValue);
247
241
  }));
248
242
  }
249
243
  remapTemplateName(templateType) {
@@ -269,207 +263,509 @@ class FlowInfoService {
269
263
  }
270
264
  return undefined;
271
265
  }
266
+ getFlowContextMode(headerId) {
267
+ const objectName = SalesforceIdUtils.getSfObjectNameById(headerId);
268
+ if (!objectName) {
269
+ return;
270
+ }
271
+ return objectName.toUpperCase();
272
+ }
272
273
  }
273
- FlowInfoService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowInfoService, deps: [{ token: i1.FlowsApiService }, { token: i1.UITemplatesApiService }, { token: FLOW_CUSTOMIZATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
274
+ FlowInfoService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowInfoService, deps: [{ token: RuntimeSettingsService }, { token: i1.UITemplatesAdminApiService }, { token: FLOW_CUSTOMIZATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
274
275
  FlowInfoService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowInfoService });
275
276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowInfoService, decorators: [{
276
277
  type: Injectable
277
- }], ctorParameters: function () { return [{ type: i1.FlowsApiService }, { type: i1.UITemplatesApiService }, { type: undefined, decorators: [{
278
+ }], ctorParameters: function () { return [{ type: RuntimeSettingsService }, { type: i1.UITemplatesAdminApiService }, { type: undefined, decorators: [{
278
279
  type: Optional
279
280
  }, {
280
281
  type: Inject,
281
282
  args: [FLOW_CUSTOMIZATION]
282
283
  }] }]; } });
283
284
 
284
- class QuoteDraftService {
285
- get isInitialized$() {
286
- return this.isInitializedSubj$.asObservable();
287
- }
288
- get isInitialized() {
289
- return this.isInitializedSubj$.getValue();
290
- }
291
- set isInitialized(value) {
292
- if (this.isInitialized !== value) {
293
- this.isInitializedSubj$.next(value);
285
+ const findTransactionItem = (id, items) => {
286
+ return findTransactionItemWithComparator(items, (ti) => ti.id === id);
287
+ };
288
+ const findTransactionItemWithComparator = (items, comparator) => {
289
+ let currentLevel = items;
290
+ while (currentLevel.length) {
291
+ const found = currentLevel.find(comparator);
292
+ if (found) {
293
+ return found;
294
294
  }
295
+ currentLevel = flatten(currentLevel.map(parent => parent.children));
295
296
  }
296
- get hasUnsavedChanges() {
297
- return this._hasUnsavedChanges;
297
+ return;
298
+ };
299
+ const insertTransactionItem = (item, parentId, toInsert) => {
300
+ const insertData = item.id === parentId ? [toInsert] : [];
301
+ return {
302
+ ...item,
303
+ children: [
304
+ ...insertData,
305
+ ...item.children.map(ti => {
306
+ return insertTransactionItem(ti, parentId, toInsert);
307
+ }),
308
+ ],
309
+ };
310
+ };
311
+ const removeTransactionItem = (item, idToRemove) => {
312
+ return {
313
+ ...item,
314
+ children: item.children
315
+ .map(ti => {
316
+ if (ti.id === idToRemove) {
317
+ return;
318
+ }
319
+ else if (ti.children.length) {
320
+ return removeTransactionItem(ti, idToRemove);
321
+ }
322
+ return ti;
323
+ })
324
+ .filter(isDefined),
325
+ };
326
+ };
327
+ const replaceTransactionItem = (item, replaceTo) => {
328
+ if (item.id === replaceTo.id) {
329
+ return { ...replaceTo };
298
330
  }
299
- set hasUnsavedChanges(value) {
300
- this._hasUnsavedChanges = value;
301
- if (!this._hasUnsavedChanges) {
302
- this.initialCurrentState = this.quoteDraft?.currentState ?? [];
303
- }
331
+ return {
332
+ ...item,
333
+ children: item.children.map(ti => replaceTransactionItem(ti, replaceTo)),
334
+ };
335
+ };
336
+ const generateTransactionItem = (productId) => {
337
+ return {
338
+ id: UUID.UUID(),
339
+ productId,
340
+ };
341
+ };
342
+
343
+ class TransactionItemWorker {
344
+ constructor(src) {
345
+ this.ti = { ...src };
304
346
  }
305
- get hasProducts$() {
306
- return this.quoteSubj$.pipe(map(() => this.hasProducts));
347
+ insert(parentId, toInsert) {
348
+ return new TransactionItemWorker(insertTransactionItem(this.ti, parentId, toInsert));
307
349
  }
308
- get hasProducts() {
309
- return Boolean(this.quoteSubj$.value?.currentState.length);
350
+ remove(id) {
351
+ return new TransactionItemWorker(removeTransactionItem(this.ti, id));
310
352
  }
311
- get hasAssets$() {
312
- return this.assetsSubj$.pipe(map(() => this.hasAssets));
353
+ replace(toReplace) {
354
+ return new TransactionItemWorker(replaceTransactionItem(this.ti, toReplace));
313
355
  }
314
- get hasAssets() {
315
- return Boolean(this.assetsSubj$.value?.currentState.length);
356
+ }
357
+
358
+ function extractMetadata(uiDefinition) {
359
+ return omit(uiDefinition, [
360
+ 'children',
361
+ 'pages',
362
+ 'components',
363
+ ]);
364
+ }
365
+
366
+ class GuidedSellingService {
367
+ constructor(orchestrationsApiService) {
368
+ this.orchestrationsApiService = orchestrationsApiService;
369
+ this.guidedSellingResult$ = new BehaviorSubject({});
316
370
  }
317
- get assetsState() {
318
- return this.assetsSubj$.value;
371
+ get guidedSellingResult() {
372
+ return this.guidedSellingResult$.value;
319
373
  }
320
- constructor(context, flowInfoService, accountApiService, quoteApiService) {
321
- this.context = context;
322
- this.flowInfoService = flowInfoService;
323
- this.accountApiService = accountApiService;
324
- this.quoteApiService = quoteApiService;
325
- this.quoteSubj$ = new BehaviorSubject(null);
326
- this.assetsSubj$ = new BehaviorSubject(null);
327
- this.resetSubj$ = new BehaviorSubject(true);
328
- this.isInitializedSubj$ = new BehaviorSubject(false);
329
- this.initialCurrentState = [];
330
- this._hasUnsavedChanges = false;
331
- this.reset$ = this.resetSubj$.asObservable();
332
- this.isInitializedSubj$
333
- .pipe(filter(isInitialized => isInitialized), switchMap$1(() => this.quoteSubj$.asObservable()), skip(1), tap(quote => this.markAsUpdated(quote)))
334
- .subscribe();
374
+ configureGuidedSelling$(data) {
375
+ return this.orchestrationsApiService
376
+ .apply$({
377
+ transactionContext: this.getTransactionContext(data.attributesMap),
378
+ orchestrationName: data.orchestrationName,
379
+ })
380
+ .pipe(map(transactionContext => {
381
+ const guidedSellingNode = transactionContext.nodes['GuidedSelling']?.[0];
382
+ const guidedSellingResult = guidedSellingNode?.attributes?.['result'] || {};
383
+ this.guidedSellingResult$.next(guidedSellingResult);
384
+ return guidedSellingResult;
385
+ }));
335
386
  }
336
- reset() {
337
- this.resetSubj$.next(true);
338
- this.quoteSubj$.next(null);
339
- this.assetsSubj$.next(null);
340
- this.isInitialized = false;
341
- this.hasUnsavedChanges = false;
387
+ clearGuidedSelling$() {
388
+ this.guidedSellingResult$.next({});
342
389
  }
343
- init(headerId, params) {
344
- const ctx = this.context.resolve();
345
- const isAccountMode = this.context.mode === ConfigurationContextMode.ACCOUNT;
346
- const accountId = isAccountMode ? headerId : ctx.properties.AccountId;
347
- return zip(accountId ? this.accountApiService.getAssetsState(accountId, params) : of(null), isAccountMode
348
- ? of(QuoteDraft.emptyQuote(ConfigurationContextMode.ACCOUNT))
349
- : this.quoteApiService.getQuoteState(headerId, params)).pipe(tap(([assets, quote]) => {
350
- if (assets) {
351
- this.assetsSubj$.next(assets);
352
- }
353
- this.quoteSubj$.next(quote);
354
- if (assets && isAccountMode) {
355
- this.context.update(assets.context);
356
- }
357
- else {
358
- this.context.update(quote.context);
359
- }
360
- }), map(() => noop()), take(1));
390
+ getTransactionContext(guidedSellingAttributes) {
391
+ const testTransaction = {
392
+ id: UUID.UUID(),
393
+ businessObjectType: 'Quote',
394
+ salesTransactionItems: [],
395
+ attributes: {},
396
+ };
397
+ return {
398
+ salesTransaction: testTransaction,
399
+ transactionId: UUID.UUID(),
400
+ businessObjectType: 'Quote',
401
+ nodes: {
402
+ GuidedSelling: [
403
+ {
404
+ id: UUID.UUID(),
405
+ attributes: {},
406
+ nodes: {},
407
+ properties: { guidedSellingAttributes },
408
+ },
409
+ ],
410
+ },
411
+ id: UUID.UUID(),
412
+ attributes: {},
413
+ };
361
414
  }
362
- finalizeInit() {
363
- this.isInitialized = true;
415
+ }
416
+ GuidedSellingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GuidedSellingService, deps: [{ token: i1.OrchestrationsApiService }], target: i0.ɵɵFactoryTarget.Injectable });
417
+ GuidedSellingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GuidedSellingService });
418
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GuidedSellingService, decorators: [{
419
+ type: Injectable
420
+ }], ctorParameters: function () { return [{ type: i1.OrchestrationsApiService }]; } });
421
+
422
+ class ConfigurationService {
423
+ constructor(flowInfoService, messageService, configurationRuntimeService, salesTransactionService, orchestrationsApiService, guidedSellingService) {
424
+ this.flowInfoService = flowInfoService;
425
+ this.messageService = messageService;
426
+ this.configurationRuntimeService = configurationRuntimeService;
427
+ this.salesTransactionService = salesTransactionService;
428
+ this.orchestrationsApiService = orchestrationsApiService;
429
+ this.guidedSellingService = guidedSellingService;
364
430
  this.hasUnsavedChanges = false;
431
+ this.configurationStateSubj$ = new BehaviorSubject(null);
432
+ this.previousConfigurationStateSubj$ = new BehaviorSubject(null);
433
+ this.isLoadingSubj$ = new BehaviorSubject(false);
434
+ this.isLoading$ = this.isLoadingSubj$.asObservable();
365
435
  }
366
- setCurrentLineItemState(lineItems) {
367
- const quoteDraft = this.quoteSubj$.value;
368
- if (!quoteDraft) {
369
- return;
370
- }
371
- this.quoteSubj$.next({
372
- ...quoteDraft,
373
- currentState: lineItems,
374
- });
436
+ get state$() {
437
+ return this.configurationStateSubj$.asObservable().pipe(filter$1(isDefined));
375
438
  }
376
- updateQuoteDraft(update) {
377
- const quoteDraft = this.quoteSubj$.value;
378
- if (!quoteDraft) {
379
- return;
380
- }
381
- if (update.context) {
382
- this.context.set(update.context);
383
- }
384
- this.quoteSubj$.next({
385
- ...quoteDraft,
386
- ...update,
387
- });
439
+ get state() {
440
+ return this.configurationStateSubj$.getValue();
388
441
  }
389
- updateByPriceSummary(priceSummary) {
390
- const quoteDraft = this.quoteSubj$.value;
391
- if (!quoteDraft) {
392
- return;
393
- }
394
- const updatedCurrentState = this.currentState.map(lineItem => {
395
- const updated = priceSummary.lineItems.find(li => li.id === lineItem.id);
396
- return updated ?? lineItem;
397
- });
398
- this.quoteSubj$.next({
399
- ...quoteDraft,
400
- currentState: updatedCurrentState,
401
- totalPrices: priceSummary.totalPrices,
402
- approvalItems: priceSummary.approvalItems,
403
- });
442
+ get previousState() {
443
+ return this.previousConfigurationStateSubj$.getValue();
404
444
  }
405
- setAssetsState(assetsState) {
406
- this.assetsSubj$.next(assetsState);
445
+ get root$() {
446
+ return this.state$.pipe(map$1(state => state.salesTransaction.salesTransactionItems[0]), filter$1(isDefined));
407
447
  }
408
- get quoteDraft$() {
409
- return combineLatest([this.quoteSubj$, this.context.resolve$()]).pipe(map(() => this.quoteDraft), filter((quote) => Boolean(quote)), shareReplay());
448
+ get root() {
449
+ return this.configurationStateSubj$.getValue()?.salesTransaction.salesTransactionItems[0] ?? null;
410
450
  }
411
- get quoteDraft() {
412
- const quote = this.quoteSubj$.value;
413
- if (!quote) {
414
- return null;
451
+ reset() {
452
+ this.hasUnsavedChanges = false;
453
+ this.configurationStateSubj$.next(null);
454
+ this.previousConfigurationStateSubj$.next(null);
455
+ }
456
+ init$() {
457
+ const { state } = this.salesTransactionService;
458
+ const { standalone } = this.flowInfoService.flow.properties;
459
+ const { productId, transactionItemId, newProductQty } = this.flowInfoService.context;
460
+ if (!state || !productId) {
461
+ return of(undefined);
415
462
  }
416
- return {
417
- ...quote,
418
- context: this.context.resolve(),
463
+ const salesTransactionItems = state?.salesTransaction.salesTransactionItems ?? [];
464
+ let isRootGenerated = false;
465
+ let transactionItem = salesTransactionItems.find(item => item.id === transactionItemId);
466
+ if (!transactionItem && standalone) {
467
+ transactionItem = salesTransactionItems.find(item => item.productId === productId);
468
+ }
469
+ if (!transactionItem) {
470
+ transactionItem = generateTransactionItem(productId);
471
+ if (typeof newProductQty === 'number' && newProductQty > 0) {
472
+ transactionItem.qty = newProductQty;
473
+ }
474
+ isRootGenerated = true;
475
+ }
476
+ const guidedSellingResult = this.guidedSellingService.guidedSellingResult;
477
+ if (transactionItem && Object.keys(guidedSellingResult).length && isRootGenerated) {
478
+ transactionItem.stiAttributes = Object.entries(guidedSellingResult).map(([attributeName, value]) => ({
479
+ attributeName,
480
+ value,
481
+ }));
482
+ }
483
+ const configurationState = {
484
+ ...state,
485
+ salesTransaction: {
486
+ ...state.salesTransaction,
487
+ salesTransactionItems: transactionItem ? [transactionItem] : [],
488
+ },
489
+ };
490
+ return (isRootGenerated ? this.configure$(configurationState) : of(configurationState)).pipe(tap$1(configurationState => {
491
+ this.configurationStateSubj$.next(configurationState);
492
+ this.previousConfigurationStateSubj$.next(configurationState);
493
+ }), map$1(noop));
494
+ }
495
+ patch$(transactionItem) {
496
+ const { state, root } = this;
497
+ if (!state) {
498
+ return throwError(() => new Error(`Configuration State is not initialized`));
499
+ }
500
+ if (!root) {
501
+ return throwError(() => new Error(`Root SalesTransactionItem not found`));
502
+ }
503
+ const newRoot = new TransactionItemWorker(root).replace(transactionItem).ti;
504
+ const newTransactionContext = {
505
+ ...state,
506
+ salesTransaction: {
507
+ ...state.salesTransaction,
508
+ salesTransactionItems: [newRoot],
509
+ },
510
+ };
511
+ return this.configure$(newTransactionContext).pipe(catchError(error => {
512
+ console.error(error);
513
+ if (!this.configurationRuntimeService.uiDefinitionProps.suppressToastMessages) {
514
+ this.messageService.add({ severity: 'error', summary: error });
515
+ }
516
+ return throwError(() => error);
517
+ }), tap$1(() => {
518
+ if (!this.hasUnsavedChanges) {
519
+ this.hasUnsavedChanges = true;
520
+ }
521
+ }), map$1(noop));
522
+ }
523
+ patch(transactionItem) {
524
+ this.patch$(transactionItem).subscribe();
525
+ }
526
+ configure$(transactionContext) {
527
+ this.isLoadingSubj$.next(true);
528
+ return this.justConfigureRequest$(transactionContext).pipe(tap$1(result => {
529
+ this.configurationStateSubj$.next(result);
530
+ this.previousConfigurationStateSubj$.next(cloneDeep(result));
531
+ }), catchError(e => {
532
+ const resetState = this.previousConfigurationStateSubj$.getValue();
533
+ if (resetState) {
534
+ this.previousConfigurationStateSubj$.next(cloneDeep(resetState));
535
+ this.configurationStateSubj$.next(resetState);
536
+ }
537
+ return throwError(() => e);
538
+ }), finalize(() => this.isLoadingSubj$.next(false)));
539
+ }
540
+ justConfigureRequest$(transactionContext) {
541
+ const request = {
542
+ transactionContext,
543
+ flowId: this.flowInfoService.flow.id,
419
544
  };
545
+ return this.orchestrationsApiService.apply$(request).pipe(catchError(error => throwError(() => {
546
+ if (error.error) {
547
+ return extractErrorDetails(error.error).join('. ');
548
+ }
549
+ return error.message || JSON.stringify(error);
550
+ })));
551
+ }
552
+ getPCMModel() {
553
+ const pcmModel = this.configurationRuntimeService.pcmModel;
554
+ if (!pcmModel) {
555
+ throw new Error('PCM model not initialized');
556
+ }
557
+ return pcmModel;
558
+ }
559
+ }
560
+ ConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationService, deps: [{ token: FlowInfoService }, { token: i2.MessageService }, { token: ConfigurationRuntimeService }, { token: SalesTransactionService }, { token: i1.OrchestrationsApiService }, { token: GuidedSellingService }], target: i0.ɵɵFactoryTarget.Injectable });
561
+ ConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationService });
562
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationService, decorators: [{
563
+ type: Injectable
564
+ }], ctorParameters: function () { return [{ type: FlowInfoService }, { type: i2.MessageService }, { type: ConfigurationRuntimeService }, { type: SalesTransactionService }, { type: i1.OrchestrationsApiService }, { type: GuidedSellingService }]; } });
565
+
566
+ class SalesTransactionService {
567
+ get isInitialized$() {
568
+ return this.isInitializedSubj$.asObservable();
569
+ }
570
+ get isInitialized() {
571
+ return this.isInitializedSubj$.getValue();
572
+ }
573
+ set hasUnsavedChanges(value) {
574
+ this.hasUnsavedChangesSubj$.next(value);
575
+ if (!this.hasUnsavedChanges) {
576
+ this.initialState = this.state?.salesTransaction.salesTransactionItems ?? [];
577
+ }
578
+ }
579
+ get hasUnsavedChanges() {
580
+ return this.hasUnsavedChangesSubj$.getValue();
581
+ }
582
+ get state() {
583
+ return this.stateSubj$.getValue();
584
+ }
585
+ get hasProducts() {
586
+ return Boolean(this.state?.salesTransaction.salesTransactionItems.length);
587
+ }
588
+ constructor(salesTransactionApiService) {
589
+ this.salesTransactionApiService = salesTransactionApiService;
590
+ this.stateSubj$ = new BehaviorSubject(null);
591
+ this.isInitializedSubj$ = new BehaviorSubject(false);
592
+ this.hasUnsavedChangesSubj$ = new BehaviorSubject(false);
593
+ this.initialState = [];
594
+ this.hasUnsavedChanges$ = this.hasUnsavedChangesSubj$.asObservable();
595
+ this.state$ = this.stateSubj$.asObservable().pipe(filter(isDefined));
420
596
  }
421
- get currentState$() {
422
- return this.quoteDraft$.pipe(map(quote => quote.currentState));
597
+ init(headerId, params) {
598
+ return this.salesTransactionApiService.query(headerId, params).pipe(tap(res => {
599
+ if (!res.salesTransaction) {
600
+ throw new Error('SalesTransaction is not defined. Please check Query Orchestration.');
601
+ }
602
+ this.stateSubj$.next(res);
603
+ }));
423
604
  }
424
- get currentState() {
425
- return this.quoteDraft?.currentState ?? [];
605
+ finalizeInit() {
606
+ this.isInitializedSubj$.next(true);
607
+ this.hasUnsavedChanges = false;
426
608
  }
427
- get isStandalone() {
428
- return this.flowInfoService.flow?.properties.standalone ?? false;
609
+ reset() {
610
+ this.stateSubj$.next(null);
611
+ this.isInitializedSubj$.next(false);
612
+ this.hasUnsavedChangesSubj$.next(false);
429
613
  }
430
- get isStandalone$() {
431
- return this.flowInfoService.flow$.pipe(map(() => this.isStandalone));
614
+ getInitialState() {
615
+ return this.initialState;
432
616
  }
433
- getInitialCurrentState() {
434
- return this.initialCurrentState;
617
+ setState(state) {
618
+ this.stateSubj$.next(state);
435
619
  }
436
- isEditMode$() {
437
- return this.context.resolve$().pipe(map(() => this.isEditMode()));
620
+ }
621
+ SalesTransactionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SalesTransactionService, deps: [{ token: i1.SalesTransactionApiService }], target: i0.ɵɵFactoryTarget.Injectable });
622
+ SalesTransactionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SalesTransactionService });
623
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SalesTransactionService, decorators: [{
624
+ type: Injectable
625
+ }], ctorParameters: function () { return [{ type: i1.SalesTransactionApiService }]; } });
626
+
627
+ class FlowConfigurationService {
628
+ constructor(orchestrationsApiService, salesTransactionService, flowInfoService) {
629
+ this.orchestrationsApiService = orchestrationsApiService;
630
+ this.salesTransactionService = salesTransactionService;
631
+ this.flowInfoService = flowInfoService;
632
+ this.updatedSubj$ = new Subject();
633
+ this.updated$ = this.updatedSubj$.asObservable();
438
634
  }
439
- isEditMode() {
440
- const context = this.context.resolve();
441
- if (context.mode === ConfigurationContextMode.ACCOUNT) {
442
- return true;
635
+ calculate$(state) {
636
+ return this.orchestrationsApiService
637
+ .apply$({ transactionContext: state, flowId: this.flowInfoService.flow.id })
638
+ .pipe(tap(result => this.salesTransactionService.setState(result)), map(noop));
639
+ }
640
+ calculate(state) {
641
+ this.calculate$(state).subscribe();
642
+ }
643
+ revert$(transactionItemId) {
644
+ const state = this.salesTransactionService.state;
645
+ const initialState = this.salesTransactionService.getInitialState();
646
+ const currentState = state?.salesTransaction.salesTransactionItems ?? [];
647
+ const currentItemIndex = currentState.findIndex(({ id }) => id === transactionItemId);
648
+ const currentItem = currentState[currentItemIndex];
649
+ const initialItem = initialState.find(({ integrationId }) => integrationId === currentItem?.integrationId);
650
+ if (!state || !currentItem || !initialItem) {
651
+ return of(null);
443
652
  }
444
- if (context.mode === ConfigurationContextMode.QUOTE) {
445
- return context.properties.Status === 'Draft';
653
+ const updatedState = cloneDeep(currentState);
654
+ updatedState.splice(currentItemIndex, 1, initialItem);
655
+ return of([]).pipe(map(() => ({
656
+ ...state,
657
+ salesTransaction: { ...state.salesTransaction, salesTransactionItems: updatedState },
658
+ })), tap(newState => this.salesTransactionService.setState(newState)), switchMap(newState => this.calculate$(newState)), map(() => this.salesTransactionService.state), tap(() => this.updatedSubj$.next()), this.handleErrorAndBounceBack());
659
+ }
660
+ revert(transactionItemId) {
661
+ this.revert$(transactionItemId).subscribe();
662
+ }
663
+ delete$(ids) {
664
+ const state = this.salesTransactionService.state;
665
+ if (!state) {
666
+ return of(null);
446
667
  }
447
- return false;
668
+ return of([]).pipe(map(() => state.salesTransaction.salesTransactionItems.filter(({ id }) => !ids.includes(id))), switchMap(updatedState => this.calculate$({
669
+ ...state,
670
+ salesTransaction: { ...state.salesTransaction, salesTransactionItems: updatedState },
671
+ })), map(() => this.salesTransactionService.state), tap(() => this.updatedSubj$.next()), this.handleErrorAndBounceBack());
672
+ }
673
+ delete(ids) {
674
+ this.delete$(ids).subscribe();
675
+ }
676
+ handleErrorAndBounceBack() {
677
+ return (source$) => {
678
+ return source$.pipe(catchError$1(error => {
679
+ console.error(error);
680
+ // bounce back if configuration call has failed
681
+ const state = this.salesTransactionService.state;
682
+ if (state) {
683
+ this.salesTransactionService.setState(state);
684
+ this.updatedSubj$.next();
685
+ }
686
+ return throwError(() => error);
687
+ }));
688
+ };
689
+ }
690
+ }
691
+ FlowConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationService, deps: [{ token: i1.OrchestrationsApiService }, { token: SalesTransactionService }, { token: FlowInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
692
+ FlowConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationService });
693
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationService, decorators: [{
694
+ type: Injectable
695
+ }], ctorParameters: function () { return [{ type: i1.OrchestrationsApiService }, { type: SalesTransactionService }, { type: FlowInfoService }]; } });
696
+
697
+ class TestModeConfigurationService {
698
+ constructor(flowInfoService, configurationService, configurationRuntimeService, salesTransactionService, runtimeSettingsService) {
699
+ this.flowInfoService = flowInfoService;
700
+ this.configurationService = configurationService;
701
+ this.configurationRuntimeService = configurationRuntimeService;
702
+ this.salesTransactionService = salesTransactionService;
703
+ this.runtimeSettingsService = runtimeSettingsService;
704
+ this.isInitialized = false;
448
705
  }
449
- markAsUpdated(quote) {
450
- if (quote?.context.properties['#mode'] === ConfigurationContextMode.ACCOUNT) {
451
- this.hasUnsavedChanges = !!quote && !quote.currentState.every(li => li.actionCode === 'EXIST');
706
+ initTestMode$(uiDefinitionContainer, options) {
707
+ this.configurationRuntimeService.uiDefinitionContainer = uiDefinitionContainer;
708
+ if (this.checkInitialized(uiDefinitionContainer)) {
709
+ this.configurationRuntimeService.pcmModel = this.pcmModel;
710
+ return of(undefined);
452
711
  }
453
- else {
454
- this.hasUnsavedChanges = !isEqual(this.initialCurrentState, quote?.currentState);
712
+ this.configurationService.reset();
713
+ const { productId, quoteId, flowId } = uiDefinitionContainer.source.properties ?? {};
714
+ if (!productId) {
715
+ return throwError(() => 'Unable to start the Configuration Preview: Product is missing.');
716
+ }
717
+ if (!quoteId) {
718
+ return throwError(() => `Unable to start the Configuration Preview: Quote is missing.`);
719
+ }
720
+ if (!flowId) {
721
+ return throwError(() => `Unable to start the Configuration Preview: Flow is missing.`);
455
722
  }
723
+ return this.runtimeSettingsService.create().pipe(switchMap(() => this.flowInfoService.init$(flowId, { productId, headerId: quoteId })), switchMap(() => this.configurationRuntimeService.init$({ productId })), tap(pcmModel => (this.pcmModel = pcmModel)), switchMap(() => {
724
+ if (options?.customizationMode) {
725
+ return of(undefined);
726
+ }
727
+ return this.initConfiguration$(quoteId);
728
+ }), tap(() => (this.isInitialized = true)), map(noop));
729
+ }
730
+ initConfiguration$(quoteId) {
731
+ this.salesTransactionService.setState(this.getTestTransactionContext(quoteId));
732
+ return this.configurationService.init$().pipe(switchMap(() => this.configurationService.state
733
+ ? this.configurationService.configure$(this.configurationService.state)
734
+ : of(undefined)), map(noop));
735
+ }
736
+ getTestTransactionContext(quoteId) {
737
+ const testTransaction = {
738
+ id: quoteId,
739
+ businessObjectType: 'Quote',
740
+ salesTransactionItems: [],
741
+ };
742
+ return {
743
+ salesTransaction: testTransaction,
744
+ transactionId: quoteId,
745
+ businessObjectType: 'Quote',
746
+ nodes: {},
747
+ id: UUID.UUID(),
748
+ attributes: {},
749
+ };
750
+ }
751
+ checkInitialized(uiDefinitionContainer) {
752
+ return this.isInitialized && !!uiDefinitionContainer.source.properties?.persistTestState;
456
753
  }
457
754
  }
458
- QuoteDraftService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: QuoteDraftService, deps: [{ token: ContextService }, { token: FlowInfoService }, { token: i1.AccountApiService }, { token: i1.QuoteApiService }], target: i0.ɵɵFactoryTarget.Injectable });
459
- QuoteDraftService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: QuoteDraftService });
460
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: QuoteDraftService, decorators: [{
755
+ TestModeConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TestModeConfigurationService, deps: [{ token: FlowInfoService }, { token: ConfigurationService }, { token: ConfigurationRuntimeService }, { token: SalesTransactionService }, { token: RuntimeSettingsService }], target: i0.ɵɵFactoryTarget.Injectable });
756
+ TestModeConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TestModeConfigurationService });
757
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TestModeConfigurationService, decorators: [{
461
758
  type: Injectable
462
- }], ctorParameters: function () { return [{ type: ContextService }, { type: FlowInfoService }, { type: i1.AccountApiService }, { type: i1.QuoteApiService }]; } });
759
+ }], ctorParameters: function () { return [{ type: FlowInfoService }, { type: ConfigurationService }, { type: ConfigurationRuntimeService }, { type: SalesTransactionService }, { type: RuntimeSettingsService }]; } });
463
760
 
464
761
  class FlowStateService {
465
- constructor(contextService, quoteDraftService, flowInfoService, flowConfiguration, processorsApiService, flowStateApiService, quoteApiService, toastService, customizationService) {
466
- this.contextService = contextService;
467
- this.quoteDraftService = quoteDraftService;
468
- this.flowInfoService = flowInfoService;
762
+ constructor(flowConfiguration, flowInfoService, flowStateApiService, processorsApiService, salesTransactionApiService, salesTransactionService, toastService, customizationService) {
469
763
  this.flowConfiguration = flowConfiguration;
470
- this.processorsApiService = processorsApiService;
764
+ this.flowInfoService = flowInfoService;
471
765
  this.flowStateApiService = flowStateApiService;
472
- this.quoteApiService = quoteApiService;
766
+ this.processorsApiService = processorsApiService;
767
+ this.salesTransactionApiService = salesTransactionApiService;
768
+ this.salesTransactionService = salesTransactionService;
473
769
  this.toastService = toastService;
474
770
  this.customizationService = customizationService;
475
771
  this.NOT_INITIALIZED = Symbol();
@@ -486,68 +782,22 @@ class FlowStateService {
486
782
  this.cleanup$ = new Subject();
487
783
  this.statefulExecutionRequest$ = this.initBufferedRequest$();
488
784
  /*
489
- In stateless mode watch QuoteDraft changes and call executeRequest so that
490
- all subscriptions get their updates according to updated QuoteDraft
785
+ In stateless mode watch State changes and call executeRequest so that
786
+ all subscriptions get their updates according to updated State
491
787
  */
492
788
  this.isInitialized$()
493
- .pipe(filter$1(Boolean), filter$1(() => !this.getFlowSafe().properties.stateful), switchMap(() => this.flowConfiguration.updated$), switchMap(() => this.executeRequest$({}, true)))
789
+ .pipe(filter(Boolean), filter(() => !this.flowInfoService.flow.properties.stateful), switchMap(() => this.flowConfiguration.updated$), switchMap(() => this.executeRequest$({}, true)))
494
790
  .subscribe();
495
- this.charges$ = this.flowInfoService.flow$.pipe(filter$1(isDefined), switchMap(() => {
496
- if (this.flowInfoService.isLegacy) {
497
- return this.quoteDraftService.quoteDraft$.pipe(map$1(quoteDraft => quoteDraft.charges));
498
- }
499
- else {
500
- return this.subscribe$(UITemplateType.FLOW_ENGINE, 'CHARGES', null, {
501
- cold: true,
502
- }).pipe(map$1(response => (response.success ? response.result : {})));
503
- }
504
- }), shareReplay$1(1));
505
- this.charges$.subscribe();
506
- this.pricePlans$ = this.flowInfoService.flow$.pipe(filter$1(isDefined), switchMap(() => {
507
- if (this.flowInfoService.isLegacy) {
508
- return this.quoteDraftService.quoteDraft$.pipe(map$1(quoteDraft => quoteDraft.pricePlans));
509
- }
510
- else {
511
- return this.subscribe$(UITemplateType.FLOW_ENGINE, 'PRICE_PLANS', null, {
512
- cold: true,
513
- }).pipe(map$1(response => (response.success ? response.result : {})));
514
- }
515
- }), shareReplay$1(1));
516
- this.pricePlans$.subscribe();
517
- this.activeMetrics$ = this.flowInfoService.flow$.pipe(filter$1(isDefined), switchMap(() => {
518
- if (this.flowInfoService.isLegacy) {
519
- return this.quoteDraftService.quoteDraft$.pipe(map$1(quoteDraft => quoteDraft.activeMetrics));
520
- }
521
- else {
522
- return this.subscribe$(UITemplateType.FLOW_ENGINE, 'ACTIVE_METRICS', null, {
523
- cold: true,
524
- }).pipe(map$1(response => (response.success ? response.result : [])));
525
- }
526
- }), shareReplay$1(1));
527
- this.activeMetrics$.subscribe();
528
- this.isPriceListLocked$ = this.flowInfoService.flow$.pipe(filter$1(isDefined), switchMap(() => {
529
- if (this.flowInfoService.isLegacy) {
530
- return of(false);
531
- }
532
- else {
533
- return this.subscribe$(UITemplateType.FLOW_ENGINE, 'IS_PRICE_LIST_LOCKED', null, {
534
- cold: true,
535
- }).pipe(map$1(response => (response.success ? response.result : false)));
536
- }
537
- }), shareReplay$1(1));
538
- this.isPriceListLocked$.subscribe();
539
791
  }
540
792
  init$() {
541
- return this.initProcessors$().pipe(switchMap(() => {
542
- if (this.getFlowSafe().properties.stateful) {
543
- return this.initStateful$();
544
- }
545
- else {
546
- return this.initStateless$();
547
- }
548
- }));
793
+ if (this.flowInfoService.flow.properties.stateful) {
794
+ return this.initProcessors$().pipe(switchMap(() => this.initStateful$()));
795
+ }
796
+ else {
797
+ return forkJoin([this.initStateless$(), this.initProcessors$()]).pipe(map(noop));
798
+ }
549
799
  }
550
- cleanup() {
800
+ reset() {
551
801
  Object.values(this.subscriptions).forEach(({ data$ }) => data$.complete());
552
802
  this.subscriptions = {};
553
803
  if (this.stateId$.value) {
@@ -559,9 +809,9 @@ class FlowStateService {
559
809
  this.cleanup$.next();
560
810
  }
561
811
  get hasUnsavedChanges() {
562
- return this.getFlowSafe().properties.stateful
812
+ return this.flowInfoService.flow.properties.stateful
563
813
  ? Array.from(this.trackedStatefulChangesMap.values()).some(Boolean)
564
- : this.quoteDraftService.hasUnsavedChanges;
814
+ : this.salesTransactionService.hasUnsavedChanges;
565
815
  }
566
816
  get stateId() {
567
817
  return this.stateId$.value;
@@ -570,14 +820,14 @@ class FlowStateService {
570
820
  return this.executionInProgress$.asObservable();
571
821
  }
572
822
  isInitialized$() {
573
- return combineLatest([this.stateId$, this.quoteDraftService.isInitialized$]).pipe(map$1(values => values.some(Boolean)));
823
+ return combineLatest([this.stateId$, this.salesTransactionService.isInitialized$]).pipe(map(values => values.some(Boolean)));
574
824
  }
575
825
  isInitialized() {
576
- return Boolean(this.stateId$.value) || this.quoteDraftService.isInitialized;
826
+ return Boolean(this.stateId$.value) || this.salesTransactionService.isInitialized;
577
827
  }
578
828
  execute$(scope, exec) {
579
829
  const request = this.execToRequest(scope, exec);
580
- return this.executeRequest$(request).pipe(map$1(result => {
830
+ return this.executeRequest$(request).pipe(map(result => {
581
831
  // Keep only requested results
582
832
  const actualSelectors = Object.entries(result.selectors).reduce((trunk, [requestId, result]) => {
583
833
  if (exec.selectors?.[requestId]) {
@@ -593,7 +843,7 @@ class FlowStateService {
593
843
  actions: [{ name: action, inputData }],
594
844
  };
595
845
  const request = this.execToRequest(scope, exec);
596
- return this.executeRequest$(request).pipe(map$1(noop));
846
+ return this.executeRequest$(request).pipe(map(noop));
597
847
  }
598
848
  select$(scope, selectorName, inputData) {
599
849
  const requestId = this.generateRequestId(scope, selectorName, inputData);
@@ -605,7 +855,7 @@ class FlowStateService {
605
855
  },
606
856
  },
607
857
  });
608
- return this.executeRequest$(request).pipe(map$1(response => response.selectors[requestId]));
858
+ return this.executeRequest$(request).pipe(map(response => response.selectors[requestId]));
609
859
  }
610
860
  subscribe$(scope, selectorName, inputData, options) {
611
861
  const requestId = this.generateRequestId(scope, selectorName, inputData);
@@ -631,16 +881,16 @@ class FlowStateService {
631
881
  this.executeRequest$(request).subscribe();
632
882
  }
633
883
  }
634
- return subscription.data$.pipe(filter$1(data => data != this.NOT_INITIALIZED), map$1(data => data), finalize(() => {
884
+ return subscription.data$.pipe(filter(data => data != this.NOT_INITIALIZED), map(data => data), finalize$1(() => {
635
885
  if (!this.subscriptions[requestId]?.data$.observed) {
636
886
  delete this.subscriptions[requestId];
637
887
  }
638
888
  }));
639
889
  }
640
890
  save$() {
641
- if (this.getFlowSafe().properties.stateful) {
891
+ if (this.flowInfoService.flow.properties.stateful) {
642
892
  if (this.stateId$.value) {
643
- return this.flowStateApiService.save(this.stateId$.value).pipe(tap$1(() => {
893
+ return this.flowStateApiService.save(this.stateId$.value).pipe(map(({ quoteId }) => ({ id: quoteId })), tap(() => {
644
894
  Array.from(this.trackedStatefulChangesMap.keys()).forEach(key => {
645
895
  this.trackedStatefulChangesMap.set(key, false);
646
896
  });
@@ -648,30 +898,16 @@ class FlowStateService {
648
898
  }
649
899
  }
650
900
  else {
651
- const quoteDraft = this.quoteDraftService.quoteDraft;
652
- if (quoteDraft) {
653
- return this.quoteApiService.upsertQuote(quoteDraft).pipe(tap$1(({ versionId }) => {
654
- this.contextService.update({ properties: { VELOCE_PRISM__VersionId__c: versionId } });
655
- }));
656
- }
657
- }
658
- return of({ quoteId: '' });
659
- }
660
- submit$() {
661
- if (this.getFlowSafe().properties.stateful) {
662
- if (this.stateId$.value) {
663
- return this.flowStateApiService.submit(this.stateId$.value);
664
- }
665
- }
666
- else {
667
- const quoteDraft = this.quoteDraftService.quoteDraft;
668
- if (quoteDraft) {
669
- return this.quoteApiService.submitQuote(quoteDraft).pipe(tap$1(({ versionId }) => {
670
- this.contextService.update({ properties: { VELOCE_PRISM__VersionId__c: versionId } });
671
- }));
901
+ const state = this.salesTransactionService.state;
902
+ if (state) {
903
+ const request = {
904
+ transactionContext: state,
905
+ flowId: this.flowInfoService.flow.id,
906
+ };
907
+ return this.salesTransactionApiService.save(request).pipe(map(id => ({ id })));
672
908
  }
673
909
  }
674
- return of({ quoteId: '' });
910
+ return of({ id: '' });
675
911
  }
676
912
  getFlowStore() {
677
913
  return this.flowStore;
@@ -709,10 +945,10 @@ class FlowStateService {
709
945
  fullRequest.selectors = assign(fullRequest.selectors, subscription.request.selectors);
710
946
  }
711
947
  }
712
- const execution$ = this.getFlowSafe().properties.stateful
948
+ const execution$ = this.flowInfoService.flow.properties.stateful
713
949
  ? this.executeStateful$(fullRequest)
714
950
  : this.executeStateless$(fullRequest);
715
- return execution$.pipe(tap$1(result => this.handleSelectorsResponse(result.selectors)));
951
+ return execution$.pipe(tap(result => this.handleSelectorsResponse(result.selectors)));
716
952
  }
717
953
  handleSelectorsResponse(selectors) {
718
954
  Object.entries(selectors).forEach(([requestId, selectorResult]) => {
@@ -727,31 +963,21 @@ class FlowStateService {
727
963
  });
728
964
  }
729
965
  initStateful$() {
730
- // Subscriptions
731
- this.subscribe$(UITemplateType.FLOW_ENGINE, 'CONTEXT', null, { cold: true })
732
- .pipe(tap$1(response => {
733
- if (response.success) {
734
- this.contextService.update(response.result);
735
- }
736
- }), takeUntil(this.cleanup$))
737
- .subscribe();
738
966
  const processorsList = flatten(Object.values(this.processors).map(ownerMap => Object.values(ownerMap ?? {})));
739
967
  const processors = processorsList.length ? processorsList : undefined;
740
968
  const selectors = Object.values(this.subscriptions)
741
969
  .map(({ request }) => request.selectors)
742
970
  .filter(isDefined)
743
971
  .reduce((trunk, selectors) => ({ ...trunk, ...selectors }), {});
744
- const request = this.getDefaultExecutionRequestDTO();
745
972
  return this.flowStateApiService
746
973
  .init({
747
- quoteId: this.contextService.resolve().headerId,
748
- params: this.flowInfoService.params ?? {},
974
+ quoteId: this.flowInfoService.context.headerId,
975
+ params: this.flowInfoService.context,
749
976
  actionsOverride: processors?.filter(processor => processor.type === ConfigurationProcessorTypes.ACTION),
750
977
  selectorsOverride: processors?.filter(processor => processor.type === ConfigurationProcessorTypes.SELECTOR),
751
- selectors: { ...selectors, ...request.selectors },
752
- actions: request.actions,
978
+ selectors: selectors,
753
979
  })
754
- .pipe(map$1(({ stateId, selectors }) => {
980
+ .pipe(map(({ stateId, selectors }) => {
755
981
  this.handleSelectorsResponse(selectors);
756
982
  this.stateId$.next(stateId);
757
983
  }));
@@ -771,1112 +997,173 @@ class FlowStateService {
771
997
  };
772
998
  this.executionInProgress$.next(true);
773
999
  return this.flowStateApiService.execute(this.stateId$.value, request);
774
- }), tap$1(({ stateId }) => this.stateId$.next(stateId)), share(), tap$1(() => this.executionInProgress$.next(false)), catchError(e => {
1000
+ }), tap(({ stateId }) => this.stateId$.next(stateId)), share(), tap(() => this.executionInProgress$.next(false)), catchError$1(e => {
775
1001
  this.executionInProgress$.next(false);
776
1002
  return throwError(() => e);
777
1003
  }));
778
1004
  }
779
1005
  executeStateful$(request) {
780
- return this.executionInProgress$.pipe(filter$1(inProgress => !inProgress), take$1(1), switchMap(() =>
1006
+ return this.executionInProgress$.pipe(filter(inProgress => !inProgress), take(1), switchMap(() =>
781
1007
  // make sure stream switches to statefulExecutionRequest$ before pushing an execution request
782
1008
  combineLatest([
783
1009
  this.statefulExecutionRequest$,
784
- of(undefined).pipe(tap$1(() => this.statefulRequestStream$.next(request))),
785
- ])), map$1(([response]) => response), take$1(1));
1010
+ of(undefined).pipe(tap(() => this.statefulRequestStream$.next(request))),
1011
+ ])), map(([response]) => response), take(1));
786
1012
  }
787
1013
  initStateless$() {
788
- const { headerId } = this.contextService.resolve();
789
- return this.quoteDraftService.init(headerId, this.flowInfoService.params ?? {}).pipe(tap$1(() => {
790
- const assets = this.quoteDraftService.assetsState;
791
- if (assets) {
792
- this.flowStore = { ...this.flowStore, assets };
793
- }
794
- }), switchMap(() => {
795
- if (this.flowInfoService.isLegacy) {
796
- return of(null);
797
- }
798
- return this.executeRequest$(this.getDefaultExecutionRequestDTO());
799
- }), switchMap(() => this.calculate$()), tap$1(() => this.quoteDraftService.finalizeInit()), map$1(noop));
800
- }
801
- calculate$() {
802
- const flowState = this.quoteDraftService.quoteDraft;
803
- if (!flowState) {
804
- return of(undefined);
805
- }
806
- /*
807
- Don't execute procedures when:
808
- * Initializing a standalone product configuration UI, as procedure is execute in /price call
809
- * Initializing an empty account (account with no assets)
810
- */
811
- const isEmptyAccountMode = this.contextService.mode === ConfigurationContextMode.ACCOUNT &&
812
- !this.quoteDraftService.hasProducts &&
813
- !this.quoteDraftService.hasAssets &&
814
- !this.quoteDraftService.quoteDraft?.initialState.length;
815
- if (this.quoteDraftService.isStandalone || isEmptyAccountMode) {
816
- return of(undefined);
817
- }
818
- return this.flowConfiguration.calculate$(flowState);
1014
+ return this.salesTransactionService.init(this.flowInfoService.context.headerId, this.flowInfoService.context).pipe(switchMap(state => this.flowConfiguration.calculate$(state)), tap(() => this.salesTransactionService.finalizeInit()), map(noop));
819
1015
  }
820
1016
  executeStateless$(request) {
821
1017
  this.executionInProgress$.next(true);
822
- return of(undefined).pipe(tap$1(() => this.executeStatelessActions(request)), switchMap(() => {
1018
+ return of(undefined).pipe(tap(() => this.executeStatelessActions(request)), switchMap(() => {
823
1019
  /*
824
1020
  Skip price calculation in case
825
1021
  1. No actions in the request
826
1022
  2. Initialization process execution (state not initialized yet)
827
- */
828
- if (!request.actions?.length || !this.isInitialized()) {
829
- return of(undefined);
830
- }
831
- else {
832
- return this.calculate$();
833
- }
834
- }), map$1(() => this.executeStatelessSelectors(request)), tap$1(() => this.executionInProgress$.next(false)), catchError(e => {
835
- this.executionInProgress$.next(false);
836
- return throwError(() => e);
837
- }));
838
- }
839
- executeStatelessActions(request) {
840
- if (!this.quoteDraftService.quoteDraft || !request.actions?.length) {
841
- return;
842
- }
843
- let flowState = this.quoteDraftService.quoteDraft;
844
- request.actions.forEach(action => {
845
- try {
846
- flowState = this.executeActionScript(flowState, action) ?? flowState;
847
- }
848
- catch (e) {
849
- console.error(e);
850
- this.toastService.add({ severity: ToastType.error, summary: String(e) });
851
- throw e;
852
- }
853
- });
854
- this.quoteDraftService.updateQuoteDraft(flowState);
855
- }
856
- executeStatelessSelectors(request) {
857
- if (!this.quoteDraftService.quoteDraft) {
858
- throw 'QuoteDraft is not initialized';
859
- }
860
- const flowState = this.quoteDraftService.quoteDraft;
861
- return EntityUtil.entries(request.selectors ?? {}).reduce((result, [key, selector]) => {
862
- try {
863
- result.selectors[key] = {
864
- success: true,
865
- result: this.executeSelectorScript(flowState, selector),
866
- };
867
- }
868
- catch (e) {
869
- console.error(e);
870
- result.selectors[key] = {
871
- success: false,
872
- errorMessage: String(e),
873
- };
874
- }
875
- return result;
876
- }, { stateId: '', selectors: {} });
877
- }
878
- getFlowSafe() {
879
- if (!this.flowInfoService.flow) {
880
- throw 'Flow is not defined';
881
- }
882
- return this.flowInfoService.flow;
883
- }
884
- initProcessors$() {
885
- const hasOverrides = Boolean(this.customizationService?.getTemplateConfigurationProcessors);
886
- const flow = this.getFlowSafe();
887
- if (flow.properties.stateful && !hasOverrides) {
888
- // Skip initialization as backend will take processors from SF
889
- return of(undefined);
890
- }
891
- const owners$ = Object.values(this.flowInfoService.templates)
892
- .map(template => {
893
- if (!template) {
894
- return;
895
- }
896
- const localProcessors$ = this.customizationService?.getTemplateConfigurationProcessors?.(template.name) ?? of(null);
897
- return localProcessors$.pipe(switchMap(processors => processors ? of(processors) : this.processorsApiService.fetchConfigurationProcessors$(template.id)), tap$1(processors => {
898
- const processorsMap = processors.reduce((acc, p) => {
899
- acc[p.apiName] = p;
900
- return acc;
901
- }, {});
902
- this.processors[template.id] = processorsMap;
903
- }));
904
- })
905
- .filter(isDefined);
906
- if (!owners$.length) {
907
- return of(undefined);
908
- }
909
- return forkJoin(owners$).pipe(map$1(noop));
910
- }
911
- executeActionScript(request, executable) {
912
- const configurationProcessor = this.processors[executable.ownerId]?.[executable.apiName];
913
- if (!configurationProcessor?.script) {
914
- const scope = this.getScopeByOwnerId(executable.ownerId);
915
- const scopeText = scope ? ` in ${scope}` : '';
916
- throw `ConfigurationProcessor ${executable.apiName}${scopeText} not found`;
917
- }
918
- return this.executeProcessorScript(request, configurationProcessor, executable.inputData);
919
- }
920
- executeSelectorScript(request, executable) {
921
- const configurationProcessor = this.processors[executable.ownerId]?.[executable.apiName];
922
- if (!configurationProcessor?.script) {
923
- const scope = this.getScopeByOwnerId(executable.ownerId);
924
- const scopeText = scope ? ` in ${scope}` : '';
925
- throw `ConfigurationProcessor ${executable.apiName}${scopeText} not found`;
926
- }
927
- return this.executeProcessorScript(request, configurationProcessor, executable.inputData);
928
- }
929
- executeProcessorScript(request, configurationProcessor, inputData) {
930
- const scope = this.getScopeByOwnerId(configurationProcessor.ownerId ?? '');
931
- let functionToExecute = this.executedFunctions[scope + configurationProcessor.apiName];
932
- if (!functionToExecute) {
933
- const script = `${configurationProcessor.script}\nreturn transform;`;
934
- const sourceMap = `\n//# sourceURL=${scope ? scope + '/' : ''}${configurationProcessor.apiName}.js`;
935
- functionToExecute = new Function(script + sourceMap)();
936
- this.executedFunctions[scope + configurationProcessor.apiName] = functionToExecute;
937
- }
938
- return functionToExecute({
939
- request,
940
- inputData,
941
- flowStore: this.flowStore,
942
- });
943
- }
944
- generateRequestId(scope, selectorName, inputData) {
945
- const inputDataHash = UUID.hex(JSON.stringify(inputData) || '').slice(0, 8);
946
- return `${scope}/${selectorName}/${inputDataHash}`;
947
- }
948
- getDefaultExecutionRequestDTO() {
949
- const request = {
950
- actions: [],
951
- selectors: {},
952
- };
953
- if (this.getFlowSafe().properties.standalone) {
954
- return request;
955
- }
956
- const flowEngineTemplateId = this.getOwnerIdByScope(UITemplateType.FLOW_ENGINE);
957
- request.actions?.push({
958
- apiName: 'UPDATE_CONTEXT_PROPERTIES',
959
- ownerId: flowEngineTemplateId,
960
- inputData: this.contextService.resolve().properties,
961
- });
962
- return request;
963
- }
964
- checkStatefulChanges(requestId, selectorResult) {
965
- if (this.trackedStatefulChangesMap.has(requestId)) {
966
- if (!this.initialStatefulData[requestId]) {
967
- this.initialStatefulData[requestId] = selectorResult;
968
- }
969
- const hasChanges = !isEqual(this.initialStatefulData[requestId], selectorResult);
970
- this.trackedStatefulChangesMap.set(requestId, hasChanges);
971
- }
972
- }
973
- }
974
- FlowStateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateService, deps: [{ token: ContextService }, { token: QuoteDraftService }, { token: FlowInfoService }, { token: FlowConfigurationService }, { token: i1.ConfigurationProcessorsApiService }, { token: i1.FlowStateApiService }, { token: i1.QuoteApiService }, { token: i6.ToastService }, { token: FLOW_CUSTOMIZATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
975
- FlowStateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateService });
976
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateService, decorators: [{
977
- type: Injectable
978
- }], ctorParameters: function () { return [{ type: ContextService }, { type: QuoteDraftService }, { type: FlowInfoService }, { type: FlowConfigurationService }, { type: i1.ConfigurationProcessorsApiService }, { type: i1.FlowStateApiService }, { type: i1.QuoteApiService }, { type: i6.ToastService }, { type: undefined, decorators: [{
979
- type: Optional
980
- }, {
981
- type: Inject,
982
- args: [FLOW_CUSTOMIZATION]
983
- }] }]; } });
984
-
985
- const findLineItem = (id, lineItems) => {
986
- return findLineItemWithComparator(lineItems, (li) => li.id === id);
987
- };
988
- const findLineItemWithComparator = (lineItems, comparator) => {
989
- let currentLevel = lineItems;
990
- while (currentLevel.length) {
991
- const found = currentLevel.find(comparator);
992
- if (found) {
993
- return found;
994
- }
995
- currentLevel = flatten(currentLevel.map(parent => parent.lineItems));
996
- }
997
- return;
998
- };
999
- const insertLineItem = (lineItem, parentId, toInsert) => {
1000
- const insertData = lineItem.id === parentId ? [toInsert] : [];
1001
- return {
1002
- ...lineItem,
1003
- lineItems: [
1004
- ...insertData,
1005
- ...lineItem.lineItems.map(li => {
1006
- return insertLineItem(li, parentId, toInsert);
1007
- }),
1008
- ],
1009
- };
1010
- };
1011
- const removeLineItem = (lineItem, idToRemove) => {
1012
- return {
1013
- ...lineItem,
1014
- lineItems: lineItem.lineItems
1015
- .map(li => {
1016
- if (li.id === idToRemove) {
1017
- return;
1018
- }
1019
- else if (li.lineItems.length) {
1020
- return removeLineItem(li, idToRemove);
1021
- }
1022
- return li;
1023
- })
1024
- .filter(r => !!r),
1025
- };
1026
- };
1027
- const replaceLineItem = (lineItem, replaceTo, skipCardinalityCalculation = false) => {
1028
- if (lineItem.id === replaceTo.id) {
1029
- if (!skipCardinalityCalculation) {
1030
- return { ...recalculateCardinalityVariables(lineItem, replaceTo) };
1031
- }
1032
- else {
1033
- return { ...replaceTo };
1034
- }
1035
- }
1036
- return {
1037
- ...lineItem,
1038
- lineItems: lineItem.lineItems.map(li => replaceLineItem(li, replaceTo, skipCardinalityCalculation)),
1039
- };
1040
- };
1041
- const collectCardinalityComputations = (portDomains) => {
1042
- const cardinalityComputations = new Map();
1043
- entries(portDomains).forEach(([key, portDomain]) => {
1044
- cardinalityComputations.set(key, portDomain.properties['cardinalityComputation'] === 'true');
1045
- });
1046
- return cardinalityComputations;
1047
- };
1048
- const calculateCardinalityVariables = (lineItems, cardinalityComputations) => {
1049
- const cardVars = new Map();
1050
- lineItems
1051
- .filter(({ port, type }) => !!port && !!type)
1052
- .forEach(li => {
1053
- if (cardinalityComputations.get(`${li.port}`)) {
1054
- const cardinalityVariableName = `#CV-${li.type}@${li.port}`;
1055
- cardVars.set(cardinalityVariableName, (cardVars.get(cardinalityVariableName) ?? 0) + li.qty);
1056
- }
1057
- });
1058
- return cardVars;
1059
- };
1060
- const cardinalityRegexp = new RegExp('#CV-[a-zA-Z0-9_]+@(?<portName>[a-zA-Z0-9_]+)');
1061
- const recalculateCardinalityVariables = (original, updated) => {
1062
- const cardinalityComputations = collectCardinalityComputations(updated.portDomains ?? original.portDomains ?? {});
1063
- const cardinalityVariables = calculateCardinalityVariables(updated.lineItems, cardinalityComputations);
1064
- const originalCardinalityVariables = calculateCardinalityVariables(original.lineItems, cardinalityComputations);
1065
- originalCardinalityVariables.forEach((value, key) => {
1066
- const execArray = cardinalityRegexp.exec(key);
1067
- const portName = execArray?.groups?.['portName'];
1068
- if (!portName || cardinalityComputations.get(portName)) {
1069
- if (cardinalityVariables.get(key) === value) {
1070
- // no need to update cardinality if no changes
1071
- cardinalityVariables.delete(key);
1072
- }
1073
- else if (!cardinalityVariables.has(key)) {
1074
- // remove last item from port
1075
- cardinalityVariables.set(key, 0);
1076
- }
1077
- }
1078
- });
1079
- return {
1080
- ...updated,
1081
- attributes: upsertAttributes(updated.attributes, [...cardinalityVariables].map(([name, value]) => ({ name, value, cfgStatus: 'Changed' }))),
1082
- };
1083
- };
1084
- const mapAttributes = (attributes) => {
1085
- return attributes.reduce((acc, { name, value }) => ({ ...acc, [name]: value }), {});
1086
- };
1087
- const getAttributes = (attributes, names = []) => {
1088
- const filtered = attributes.filter(({ name }) => names.includes(name));
1089
- return sortBy(filtered, [({ name }) => names.indexOf(name)]);
1090
- };
1091
- const upsertAttributes = (originalAttributes, attributesToUpsert) => {
1092
- return attributesToUpsert.reduce((acc, { name, value }) => {
1093
- const [origAttr] = getAttributes(acc, [name]);
1094
- return [
1095
- ...acc.filter(attr => attr.name !== name),
1096
- { ...(origAttr ?? { name, type: '' }), cfgStatus: origAttr ? 'Changed' : 'User', value },
1097
- ];
1098
- }, originalAttributes);
1099
- };
1100
- const patchAttributes = (rootLineItem, id, attrs, skipCardinalityCalculation = false) => {
1101
- const lineItem = findLineItem(id, [rootLineItem]);
1102
- if (!lineItem) {
1103
- return rootLineItem;
1104
- }
1105
- const attributes = upsertAttributes(lineItem.attributes, attrs);
1106
- return replaceLineItem(rootLineItem, { ...lineItem, attributes }, skipCardinalityCalculation);
1107
- };
1108
- const getAttributeValue = (attributes, name) => attributes.find(attr => attr.name === name)?.value;
1109
- const generateLineItem = (port, type, parentId, attributes = [], lineItems = []) => {
1110
- return {
1111
- id: UUID.UUID(),
1112
- port,
1113
- type,
1114
- actionCode: 'ADD',
1115
- cfgStatus: 'New',
1116
- attributes: attributes.map(({ name, value }) => ({ cfgStatus: 'User', name, value })),
1117
- lineItems,
1118
- parentId,
1119
- qty: 1,
1120
- };
1121
- };
1122
- const getRecommendedPrices = (portDomain, type) => {
1123
- const domainType = portDomain.domainTypes.find(({ name }) => name === type);
1124
- const [net, list] = domainType?.recommendedPrices
1125
- ?.filter(({ chargeMethod }) => chargeMethod === 'ONE_TIME')
1126
- .reduce((acc, rp) => {
1127
- const [netPrice, listPrice] = acc;
1128
- return [netPrice + rp.netPrice, listPrice + rp.listPrice];
1129
- }, [0, 0]) ?? [0, 0];
1130
- return { net, list };
1131
- };
1132
- const getOriginParent = (lineItems, currentLineItem) => {
1133
- let target = currentLineItem;
1134
- while (target && target.rampInstanceId) {
1135
- target = lineItems.find(sub => sub.id === currentLineItem.rampInstanceId);
1136
- }
1137
- return target;
1138
- };
1139
- const assetPredicateFn = (lineItem, assetId) => {
1140
- if (!assetId) {
1141
- return false;
1142
- }
1143
- return lineItem.assetId === assetId || lineItem.openOrderLineItemId === assetId;
1144
- };
1145
- const multiplyLineItems = (lineItem, qty, split) => {
1146
- if (split) {
1147
- const unifyIds = (lineItem) => ({
1148
- ...lineItem,
1149
- id: UUID.UUID(),
1150
- lineItems: lineItem.lineItems.map(unifyIds),
1151
- });
1152
- return map$2(new Array(qty), () => unifyIds(lineItem));
1153
- }
1154
- else {
1155
- return [
1156
- {
1157
- ...lineItem,
1158
- qty: qty,
1159
- },
1160
- ];
1161
- }
1162
- };
1163
- const isTechnicalAttribute = (name) => {
1164
- return name.startsWith('#') || name.startsWith('$');
1165
- };
1166
- const filterOutTechnicalAttributes = (attributes) => {
1167
- return attributes.filter(({ name }) => !isTechnicalAttribute(name));
1168
- };
1169
-
1170
- var lineItem_utils = /*#__PURE__*/Object.freeze({
1171
- __proto__: null,
1172
- assetPredicateFn: assetPredicateFn,
1173
- filterOutTechnicalAttributes: filterOutTechnicalAttributes,
1174
- findLineItem: findLineItem,
1175
- findLineItemWithComparator: findLineItemWithComparator,
1176
- generateLineItem: generateLineItem,
1177
- getAttributeValue: getAttributeValue,
1178
- getAttributes: getAttributes,
1179
- getOriginParent: getOriginParent,
1180
- getRecommendedPrices: getRecommendedPrices,
1181
- insertLineItem: insertLineItem,
1182
- isTechnicalAttribute: isTechnicalAttribute,
1183
- mapAttributes: mapAttributes,
1184
- multiplyLineItems: multiplyLineItems,
1185
- patchAttributes: patchAttributes,
1186
- recalculateCardinalityVariables: recalculateCardinalityVariables,
1187
- removeLineItem: removeLineItem,
1188
- replaceLineItem: replaceLineItem,
1189
- upsertAttributes: upsertAttributes
1190
- });
1191
-
1192
- class RuntimeSettingsService {
1193
- constructor(configurationSettingsApiService) {
1194
- this.configurationSettingsApiService = configurationSettingsApiService;
1195
- this.configurationSettings$ = new BehaviorSubject({});
1196
- this.currencySettings$ = new BehaviorSubject({
1197
- iso: DEFAULT_CURRENCY_ISO_CODE,
1198
- symbol: DEFAULT_CURRENCY_SYMBOL,
1199
- });
1200
- this.shoppingCartSettings$ = new BehaviorSubject([]);
1201
- this.getCurrencySymbol = (locale, currency) => {
1202
- return (0)
1203
- .toLocaleString(locale, { style: 'currency', currency, minimumFractionDigits: 0, maximumFractionDigits: 0 })
1204
- .replace(/\d/g, '')
1205
- .trim();
1206
- };
1207
- }
1208
- create() {
1209
- return this.configurationSettingsApiService.fetchSettings().pipe(map$1(settings => this.parseConfigurationSettings(settings)), tap$1(configurationSettings => {
1210
- this.configurationSettings$.next(configurationSettings);
1211
- this.addShoppingCartSettings(configurationSettings['shopping-cart'] ?? []);
1212
- this.formattingSettings = this.getFormattingSettings();
1213
- }), map$1(() => undefined));
1214
- }
1215
- initCurrency(iso) {
1216
- if (iso) {
1217
- const symbol = this.getCurrencySymbol('en-US', iso);
1218
- this.currencySettings$.next({ iso, symbol });
1219
- if (this.formattingSettings) {
1220
- this.formattingSettings.currencySymbol = symbol;
1221
- }
1222
- }
1223
- }
1224
- getFormattingSettings() {
1225
- if (this.formattingSettings) {
1226
- return this.formattingSettings;
1227
- }
1228
- const shoppingCartSettings = this.getConfigurationSettings()['shopping-cart']?.reduce((acc, setting) => {
1229
- return { ...acc, [setting.id]: setting.properties };
1230
- }, {});
1231
- const currencySettings = this.getCurrencySettings();
1232
- const dateFormat = (validateDateFormat(shoppingCartSettings?.DATE_FORMAT ?? '') && shoppingCartSettings?.DATE_FORMAT) ||
1233
- DEFAULT_DATE_FORMAT;
1234
- const decimalSeparator = shoppingCartSettings?.DECIMAL_SEPARATOR;
1235
- const thousandsSeparator = shoppingCartSettings?.THOUSANDS_SEPARATOR;
1236
- // the number of decimal places can be 0
1237
- const priceScale = shoppingCartSettings?.PRICE_SCALE;
1238
- const decimalsCount = priceScale !== null && priceScale !== '' && !isNaN(Number(priceScale)) && Number(priceScale) >= 0
1239
- ? Number(priceScale)
1240
- : DEFAULT_DECIMALS_COUNT;
1241
- const actionCodeSettings = shoppingCartSettings?.STATUS_LABEL;
1242
- return {
1243
- currencySymbol: currencySettings.symbol,
1244
- dateFormats: getSupportedDateFormats(dateFormat),
1245
- decimalsCount,
1246
- decimalSeparator: decimalSeparator !== undefined && ['.', ','].includes(decimalSeparator)
1247
- ? decimalSeparator
1248
- : DEFAULT_DECIMAL_SEPARATOR,
1249
- // thousands separator can be a blank value, so it can also be null
1250
- thousandsSeparator: thousandsSeparator !== undefined && ['.', ',', '', null].includes(thousandsSeparator)
1251
- ? thousandsSeparator || ''
1252
- : DEFAULT_THOUSANDS_SEPARATOR,
1253
- actionCodeLabels: actionCodeSettings?.length
1254
- ? actionCodeSettings.reduce((result, setting) => ({ ...result, [setting.status_label]: setting.custom_label }), {})
1255
- : DEFAULT_ACTION_CODE_LABELS,
1256
- };
1257
- }
1258
- getConfigurationSettings() {
1259
- return this.configurationSettings$.value;
1260
- }
1261
- getShoppingCartSettings() {
1262
- return this.shoppingCartSettings$.value;
1263
- }
1264
- getCurrencySettings() {
1265
- return this.currencySettings$.value;
1266
- }
1267
- parseConfigurationSettings(settings) {
1268
- return settings.reduce((acc, setting) => {
1269
- switch (setting.key) {
1270
- case 'shopping-cart':
1271
- acc['shopping-cart'] = parseJsonSafely(setting.value, []);
1272
- break;
1273
- case 'navigation':
1274
- acc.navigation = parseJsonSafely(setting.value, {});
1275
- break;
1276
- case 'flows':
1277
- acc.flows = parseJsonSafely(setting.value, []);
1278
- break;
1279
- default:
1280
- acc[setting.key] = setting.value;
1281
- }
1282
- return acc;
1283
- }, {});
1284
- }
1285
- addShoppingCartSettings(settings) {
1286
- // uniqBy removes items with the biggest index
1287
- const newSettings = uniqBy([...settings, ...this.shoppingCartSettings$.value], 'id');
1288
- this.shoppingCartSettings$.next(newSettings);
1289
- }
1290
- }
1291
- RuntimeSettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeSettingsService, deps: [{ token: i1.ConfigurationSettingsApiService }], target: i0.ɵɵFactoryTarget.Injectable });
1292
- RuntimeSettingsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeSettingsService });
1293
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeSettingsService, decorators: [{
1294
- type: Injectable
1295
- }], ctorParameters: function () { return [{ type: i1.ConfigurationSettingsApiService }]; } });
1296
-
1297
- class LineItemWorker {
1298
- constructor(src) {
1299
- this.li = { ...src };
1300
- }
1301
- insert(parentId, toInsert) {
1302
- return new LineItemWorker(insertLineItem(this.li, parentId, toInsert));
1303
- }
1304
- remove(id) {
1305
- return new LineItemWorker(removeLineItem(this.li, id));
1306
- }
1307
- replace(toReplace, skipCardinalityCalculation = false) {
1308
- return new LineItemWorker(replaceLineItem(this.li, toReplace, skipCardinalityCalculation));
1309
- }
1310
- patchAttribute(attrs, id, skipCardinalityCalculation = false) {
1311
- return new LineItemWorker(patchAttributes(this.li, id ?? this.li.id, attrs, skipCardinalityCalculation));
1312
- }
1313
- }
1314
-
1315
- function extractMetadata(uiDefinition) {
1316
- return omit(uiDefinition, [
1317
- 'children',
1318
- 'pages',
1319
- 'components',
1320
- ]);
1321
- }
1322
-
1323
- class ConfigurationService {
1324
- constructor(quoteDraftService, runtimeService, contextService, configurationApiService, messageService, dialogService, runtimeSettings, flowInfoService) {
1325
- this.quoteDraftService = quoteDraftService;
1326
- this.runtimeService = runtimeService;
1327
- this.contextService = contextService;
1328
- this.configurationApiService = configurationApiService;
1329
- this.messageService = messageService;
1330
- this.dialogService = dialogService;
1331
- this.runtimeSettings = runtimeSettings;
1332
- this.flowInfoService = flowInfoService;
1333
- this.mode = ConfigurationMode.SEARCH;
1334
- this.configurationState = new BehaviorSubject(null);
1335
- this.previousConfigurationState = new BehaviorSubject(null);
1336
- this.isLoadingSubj$ = new BehaviorSubject(false);
1337
- this.isLoading$ = this.isLoadingSubj$.asObservable();
1338
- this.hasUnsavedChanges = false;
1339
- }
1340
- reset() {
1341
- this.hasUnsavedChanges = false;
1342
- this.runtimeService.reset();
1343
- this.configurableRamp = undefined;
1344
- this.configurationState.next(null);
1345
- this.previousConfigurationState.next(null);
1346
- }
1347
- patch$(lineItem, options) {
1348
- const source = this.getSnapshot();
1349
- if (!source) {
1350
- return throwError(() => new Error(`Source LineItem not found`));
1351
- }
1352
- const skipCardinalityCalculation = options?.skipCardinalityCalculation || this.contextSnapshot.properties['#skipCardinalityCalculation'] === 'true';
1353
- this.configurableRamp = new LineItemWorker(source).replace(lineItem, skipCardinalityCalculation).li;
1354
- return this.configure().pipe(catchError$1(error => {
1355
- console.error(error);
1356
- if (!this.runtimeService.uiDefinitionProperties.suppressToastMessages) {
1357
- this.messageService.add({ severity: 'error', summary: error });
1358
- }
1359
- // bounce back if configuration call has failed
1360
- const prevState = this.configurationState.value;
1361
- this.configurationState.next(prevState ? { ...prevState } : null);
1362
- return throwError(() => error);
1363
- }), tap(() => {
1364
- if (!this.hasUnsavedChanges) {
1365
- this.hasUnsavedChanges = true;
1366
- }
1367
- }));
1368
- }
1369
- patch(lineItem, options) {
1370
- this.patch$(lineItem, options).subscribe();
1371
- }
1372
- setConfigurableRamp(lineItem) {
1373
- this.configurableRamp = lineItem;
1374
- }
1375
- get() {
1376
- return this.configurationState.pipe(map(state => state?.lineItem), shareReplay$1());
1377
- }
1378
- getSnapshot() {
1379
- return this.configurationState.value?.lineItem ? { ...this.configurationState.value?.lineItem } : undefined;
1380
- }
1381
- getRuntimeModel() {
1382
- const runtimeModel = this.runtimeService.runtimeModel;
1383
- if (!runtimeModel) {
1384
- throw new Error('Runtime model not initialized');
1385
- }
1386
- return runtimeModel;
1387
- }
1388
- getRuntimeContext() {
1389
- const runtimeContext = this.runtimeService.runtimeContext;
1390
- if (!runtimeContext) {
1391
- throw new Error('Runtime context not initialized');
1392
- }
1393
- return runtimeContext;
1394
- }
1395
- get state$() {
1396
- return this.configurationState.asObservable();
1397
- }
1398
- get stateSnapshot() {
1399
- return this.configurationState.value;
1400
- }
1401
- get previousStateSnapshot() {
1402
- return this.previousConfigurationState.value;
1403
- }
1404
- get contextSnapshot() {
1405
- return this.contextService.resolve();
1406
- }
1407
- get context$() {
1408
- return this.contextService.resolve$();
1409
- }
1410
- get charges$() {
1411
- return this.configurationState.pipe(map(state => state?.charges ?? {}));
1412
- }
1413
- get chargesSnapshot() {
1414
- return this.configurationState.value?.charges ?? {};
1415
- }
1416
- get pricePlans$() {
1417
- return this.configurationState.pipe(map(state => state?.pricePlans ?? {}));
1418
- }
1419
- get pricePlansSnapshot() {
1420
- return this.configurationState.value?.pricePlans ?? {};
1421
- }
1422
- get procedureContext$() {
1423
- return this.configurationState.pipe(map(state => state?.procedureContext ?? {}));
1424
- }
1425
- get procedureContextSnapshot() {
1426
- return this.configurationState.value?.procedureContext ?? {};
1427
- }
1428
- configure() {
1429
- return this.configureRequest$(this.generateRequest());
1430
- }
1431
- configureRequest$(configurationRequest) {
1432
- const runtimeContext = this.getRuntimeContext();
1433
- const runtimeModel = this.getRuntimeModel();
1434
- const uiDefinitionProperties = this.getUIDefinitionProperties();
1435
- const mainPricingEnabled = runtimeContext.properties?.PricingEnabled;
1436
- const pricingEnabled = mainPricingEnabled ? mainPricingEnabled === 'true' : uiDefinitionProperties.pricingEnabled;
1437
- const customPriceApi = this.runtimeSettings.getConfigurationSettings()['CUSTOM_PRICE_API'];
1438
- this.isLoadingSubj$.next(true);
1439
- const configure$ = pricingEnabled && customPriceApi
1440
- ? this.configurationApiService.customConfigurePrice({
1441
- url: customPriceApi,
1442
- configurationRequest: this.extendConfigurationRequest(configurationRequest),
1443
- runtimeModel,
1444
- })
1445
- : this.extendedConfigureLineItem$({
1446
- configurationRequest,
1447
- runtimeModel,
1448
- pricingEnabled,
1449
- });
1450
- return configure$.pipe(tap(result => {
1451
- this.contextService.update(result.context);
1452
- this.configurationState.next(result);
1453
- this.previousConfigurationState.next(cloneDeep(result));
1454
- if (result.deletedLineItems?.length) {
1455
- this.showInactiveProductsConfirmation();
1456
- }
1457
- this.configurableRamp = result.lineItem;
1458
- }), map(({ lineItem }) => lineItem), catchError$1(error => throwError(() => {
1459
- const resetState = this.previousConfigurationState.value;
1460
- if (resetState) {
1461
- this.previousConfigurationState.next(cloneDeep(resetState));
1462
- this.configurationState.next(resetState);
1463
- }
1464
- if (error.error) {
1465
- return extractErrorDetails(error.error).join('. ');
1466
- }
1467
- return error.message || JSON.stringify(error);
1468
- })), finalize$1(() => this.isLoadingSubj$.next(false)));
1469
- }
1470
- configureExternal$(props) {
1471
- return this.runtimeService
1472
- .init({ productId: props.productId, defaultQty: props.qty, attributesMap: props.attributesMap })
1473
- .pipe(switchMap$1(() => this.configure()), first(), catchError$1(error => {
1474
- this.messageService.add({ severity: ToastType.error, summary: error });
1475
- throw error;
1476
- }), finalize$1(() => this.reset()));
1477
- }
1478
- configureGuidedSelling$(data) {
1479
- return this.extendedConfigureLineItem$({
1480
- configurationRequest: getGuidedSellingConfigurationRequest(data, this.contextService.resolve()),
1481
- }).pipe(catchError$1(error => {
1482
- if (error instanceof HttpErrorResponse) {
1483
- this.messageService.add({ severity: ToastType.error, summary: error.error.message || error.error });
1484
- }
1485
- throw error;
1486
- }));
1487
- }
1488
- generateRequest(lightMode = true) {
1489
- const lineItem = this.generateLineItem();
1490
- let request = {
1491
- lineItem,
1492
- mode: this.mode,
1493
- step: !this.configurationState.value?.lineItem ? RuntimeStep.START : RuntimeStep.UPDATE,
1494
- attributeDomainMode: 'ALL',
1495
- context: this.contextService.resolve(),
1496
- lineItems: this.quoteDraftService.quoteDraft?.currentState || [],
1497
- asset: this.getAsset(),
1498
- };
1499
- if (lightMode) {
1500
- request = ConfigurationTranslatorUtils.lightenConfigurationRequest(request);
1501
- }
1502
- return request;
1503
- }
1504
- generateLineItem() {
1505
- const runtimeContext = this.getRuntimeContext();
1506
- const uiDefinitionProperties = this.getUIDefinitionProperties();
1507
- let lineItem = this.configurableRamp;
1508
- if (!lineItem) {
1509
- const { initializationProps } = this.runtimeService ?? {};
1510
- lineItem = getDefaultLineItem(runtimeContext, uiDefinitionProperties, initializationProps?.defaultQty);
1511
- // Set default attributes
1512
- if (initializationProps?.attributesMap) {
1513
- const attributes = transform(initializationProps?.attributesMap, (acc, value, name) => acc.push({ name, value }), []);
1514
- lineItem = new LineItemWorker(lineItem).patchAttribute(attributes).li;
1515
- }
1516
- }
1517
- return lineItem;
1518
- }
1519
- getAsset() {
1520
- const lineItem = this.configurableRamp;
1521
- if (!lineItem) {
1522
- return;
1523
- }
1524
- const assetId = lineItem.assetId ?? lineItem.openOrderLineItemId;
1525
- return this.quoteDraftService.assetsState?.initialState.find(li => assetPredicateFn(li, assetId));
1526
- }
1527
- getUIDefinitionProperties() {
1528
- return {
1529
- ...(this.getRuntimeContext().uiDefinitionContainer?.source.properties ?? {}),
1530
- ...(this.runtimeService.uiDefinitionProperties ?? {}),
1531
- };
1532
- }
1533
- showInactiveProductsConfirmation() {
1534
- const confirmationConfig = {
1535
- title: ' ',
1536
- description: 'This quote contains inactive products. Do you want to remove them?',
1537
- primaryButtonLabel: 'Remove products',
1538
- secondaryButtonLabel: 'Back to Quote',
1539
- };
1540
- this.dialogService
1541
- .open(ConfirmationComponent, {
1542
- dismissableMask: false,
1543
- closeOnEscape: false,
1544
- closable: false,
1545
- showHeader: true,
1546
- header: `Inactive Products in Quote`,
1547
- width: '440px',
1548
- data: { confirmationConfig },
1549
- })
1550
- .onClose.subscribe(result => {
1551
- if (!result) {
1552
- const context = this.contextService.resolve();
1553
- window['VELO_BACK_FN'].apply(null, [context.headerId]);
1554
- }
1555
- });
1556
- }
1557
- extendedConfigureLineItem$({ configurationRequest, runtimeModel, pricingEnabled, }) {
1558
- return this.configurationApiService.configureLineItem({
1559
- configurationRequest: this.extendConfigurationRequest(configurationRequest),
1560
- runtimeModel,
1561
- pricingEnabled,
1562
- });
1563
- }
1564
- extendConfigurationRequest(configurationRequest) {
1565
- const procedureName = this.flowInfoService.flow?.properties.procedureName;
1566
- return {
1567
- ...configurationRequest,
1568
- ...(procedureName ? { procedureName } : {}),
1569
- };
1570
- }
1571
- }
1572
- ConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationService, deps: [{ token: QuoteDraftService }, { token: ConfigurationRuntimeService }, { token: ContextService }, { token: i1.ConfigurationApiService }, { token: i5.MessageService }, { token: i6$1.DialogService }, { token: RuntimeSettingsService }, { token: FlowInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
1573
- ConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationService });
1574
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationService, decorators: [{
1575
- type: Injectable
1576
- }], ctorParameters: function () { return [{ type: QuoteDraftService }, { type: ConfigurationRuntimeService }, { type: ContextService }, { type: i1.ConfigurationApiService }, { type: i5.MessageService }, { type: i6$1.DialogService }, { type: RuntimeSettingsService }, { type: FlowInfoService }]; } });
1577
-
1578
- class FlowUpdateService {
1579
- update(rootLineItems, updates, charges) {
1580
- let remainingUpdates = [...updates];
1581
- let currentLevel = rootLineItems;
1582
- while (currentLevel.length && remainingUpdates.length) {
1583
- currentLevel.forEach(li => {
1584
- const unhandledUpdates = [];
1585
- remainingUpdates.forEach(update => {
1586
- let updated = false;
1587
- switch (update.dataType) {
1588
- case 'LINEITEM':
1589
- updated = this.applyLineItemUpdate(li, update, charges);
1590
- break;
1591
- case 'CHARGE':
1592
- updated = this.applyChargeUpdate(li, update);
1593
- break;
1594
- case 'GROUP_CHARGE':
1595
- updated = this.applyChargeGroupUpdate(li, update);
1596
- break;
1597
- default:
1598
- // Unknown dataType. Do not try to handle it anymore
1599
- updated = true;
1600
- }
1601
- if (!updated) {
1602
- unhandledUpdates.push(update);
1603
- }
1604
- });
1605
- remainingUpdates = unhandledUpdates;
1606
- });
1607
- currentLevel = flatten(currentLevel.map(parent => parent.lineItems));
1608
- }
1609
- }
1610
- delete(lineItems, id) {
1611
- const idsToRemove = [id];
1612
- const topLevelLineItem = lineItems.find(li => li.id === id);
1613
- if (topLevelLineItem) {
1614
- // find term-related line items (which are only top level)
1615
- // expired term line items won't be deleted
1616
- let foundTermLineItem = topLevelLineItem;
1617
- while (foundTermLineItem) {
1618
- foundTermLineItem = lineItems.find(li => foundTermLineItem && li.rampInstanceId === foundTermLineItem.id);
1619
- if (foundTermLineItem) {
1620
- idsToRemove.push(foundTermLineItem.id);
1621
- }
1622
- }
1623
- }
1624
- const filtered = lineItems.filter(lineItem => !idsToRemove.includes(lineItem.id));
1625
- return filtered.map(lineItem => new LineItemWorker(lineItem).remove(id).li);
1626
- }
1627
- applyLineItemUpdate(lineItem, update, charges) {
1628
- if (lineItem.id !== update.id) {
1629
- return false;
1630
- }
1631
- switch (update.attributeType) {
1632
- case 'QTY':
1633
- lineItem.qty = update.newValue;
1634
- break;
1635
- case 'EFFECTIVE_START_DATE':
1636
- lineItem.properties['StartDate'] = moment(update.newValue).format('YYYY-MM-DD');
1637
- break;
1638
- case 'END_DATE':
1639
- lineItem.properties['EndDate'] = moment(update.newValue).format('YYYY-MM-DD');
1640
- break;
1641
- case 'PRICE_ADJUSTMENT':
1642
- {
1643
- const charge = lineItem.chargeItems.find(charge => (charges || {})[charge.chargeId]?.main);
1644
- if (charge) {
1645
- charge.priceAdjustment = update.newValue;
1646
- }
1647
- }
1648
- break;
1649
- case 'LIST_PRICE_ADJUSTMENT':
1650
- case 'MARGIN_ADJUSTMENT':
1651
- {
1652
- const charge = lineItem.chargeItems.find(charge => (charges || {})[charge.chargeId]?.main);
1653
- if (charge) {
1654
- charge.listPriceAdjustment = update.newValue;
1655
- }
1656
- }
1657
- break;
1658
- case 'COST_ADJUSTMENT':
1659
- {
1660
- const charge = lineItem.chargeItems.find(charge => (charges || {})[charge.chargeId]?.main);
1661
- if (charge) {
1662
- charge.costAdjustment = update.newValue;
1663
- }
1664
- }
1665
- break;
1666
- default:
1667
- throw new Error(`Not suppored AttributeType for LineItem update: ${update.attributeType}`);
1668
- }
1669
- return true;
1023
+ */
1024
+ const { state } = this.salesTransactionService;
1025
+ if (!state || !request.actions?.length || !this.isInitialized()) {
1026
+ return of(undefined);
1027
+ }
1028
+ else {
1029
+ return this.flowConfiguration.calculate$(state);
1030
+ }
1031
+ }), map(() => this.executeStatelessSelectors(request)), tap(() => this.executionInProgress$.next(false)), catchError$1(e => {
1032
+ this.executionInProgress$.next(false);
1033
+ return throwError(() => e);
1034
+ }));
1670
1035
  }
1671
- applyChargeUpdate(lineItem, update) {
1672
- const foundCharge = lineItem.chargeItems.find(({ id }) => id === update.id);
1673
- if (!foundCharge) {
1674
- return false;
1675
- }
1676
- if (update.attributeType === 'PRICE_ADJUSTMENT') {
1677
- foundCharge.priceAdjustment = update.newValue;
1678
- }
1679
- else if (update.attributeType === 'LIST_PRICE_ADJUSTMENT') {
1680
- foundCharge.listPriceAdjustment = update.newValue;
1681
- }
1682
- else {
1683
- throw new Error(`Not suppored AttributeType for Charge Item update: ${update.attributeType}`);
1036
+ executeStatelessActions(request) {
1037
+ const state = this.salesTransactionService.state;
1038
+ if (!state || !request.actions?.length) {
1039
+ return;
1684
1040
  }
1685
- return true;
1041
+ let flowState = state;
1042
+ request.actions.forEach(action => {
1043
+ try {
1044
+ flowState = this.executeActionScript(flowState, action) ?? flowState;
1045
+ }
1046
+ catch (e) {
1047
+ console.error(e);
1048
+ this.toastService.add({ severity: ToastType.error, summary: String(e) });
1049
+ throw e;
1050
+ }
1051
+ });
1052
+ this.salesTransactionService.setState(flowState);
1686
1053
  }
1687
- applyChargeGroupUpdate(lineItem, update) {
1688
- const foundChargeGroup = ChargeGroupUtils.findChargeGroupById(update.id, lineItem);
1689
- if (!foundChargeGroup) {
1690
- return false;
1691
- }
1692
- if (update.attributeType === 'PRICE_ADJUSTMENT') {
1693
- foundChargeGroup.priceAdjustment = update.newValue;
1694
- }
1695
- else if (update.attributeType === 'LIST_PRICE_ADJUSTMENT') {
1696
- foundChargeGroup.listPriceAdjustment = update.newValue;
1697
- }
1698
- else {
1699
- throw new Error(`Not suppored AttributeType for Charge Group Item update: ${update.attributeType}`);
1054
+ executeStatelessSelectors(request) {
1055
+ if (!this.salesTransactionService.state) {
1056
+ throw 'State is not initialized';
1700
1057
  }
1701
- return true;
1702
- }
1703
- }
1704
- FlowUpdateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowUpdateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1705
- FlowUpdateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowUpdateService });
1706
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowUpdateService, decorators: [{
1707
- type: Injectable
1708
- }] });
1709
-
1710
- class FlowConfigurationService {
1711
- constructor(proceduresApiService, contextService, quoteDraftService, updateService, configurationService, flowInfoService) {
1712
- this.proceduresApiService = proceduresApiService;
1713
- this.contextService = contextService;
1714
- this.quoteDraftService = quoteDraftService;
1715
- this.updateService = updateService;
1716
- this.configurationService = configurationService;
1717
- this.flowInfoService = flowInfoService;
1718
- this.updatedSubj$ = new Subject();
1719
- this.updated$ = this.updatedSubj$.asObservable();
1720
- }
1721
- calculate$(quoteDraft) {
1722
- return this.extendedApply$(quoteDraft).pipe(tap$1(result => {
1723
- // sort the result current state based on the quote draft initial state
1724
- const initialStateIds = quoteDraft.initialState.map(lineItem => lineItem.integrationId);
1725
- result.currentState = result.currentState
1726
- .slice()
1727
- .sort((a, b) => initialStateIds.indexOf(a.integrationId) - initialStateIds.indexOf(b.integrationId));
1728
- this.quoteDraftService.updateQuoteDraft(result);
1729
- }), map$1(noop));
1730
- }
1731
- calculate(quoteDraft) {
1732
- this.calculate$(quoteDraft).subscribe();
1058
+ const flowState = this.salesTransactionService.state;
1059
+ return EntityUtil.entries(request.selectors ?? {}).reduce((result, [key, selector]) => {
1060
+ try {
1061
+ result.selectors[key] = {
1062
+ success: true,
1063
+ result: this.executeSelectorScript(flowState, selector),
1064
+ };
1065
+ }
1066
+ catch (e) {
1067
+ console.error(e);
1068
+ result.selectors[key] = {
1069
+ success: false,
1070
+ errorMessage: String(e),
1071
+ };
1072
+ }
1073
+ return result;
1074
+ }, { stateId: '', selectors: {} });
1733
1075
  }
1734
- update$(updates) {
1735
- const quoteDraft = this.quoteDraftService.quoteDraft;
1736
- if (!quoteDraft) {
1737
- return of(null);
1076
+ initProcessors$() {
1077
+ const hasOverrides = Boolean(this.customizationService?.getTemplateConfigurationProcessors);
1078
+ if (this.flowInfoService.flow.properties.stateful && !hasOverrides) {
1079
+ // Skip initialization as backend will take processors from SF
1080
+ return of(undefined);
1738
1081
  }
1739
- return of([]).pipe(map$1(() => {
1740
- const updatedState = cloneDeep(quoteDraft.currentState);
1741
- this.updateService.update(updatedState, updates, quoteDraft.charges);
1742
- return updatedState;
1743
- }), switchMap(updatedState => this.calculate$({ ...quoteDraft, currentState: updatedState })), map$1(() => this.quoteDraftService.quoteDraft), tap$1(() => this.updatedSubj$.next()), this.handleErrorAndBounceBack());
1744
- }
1745
- update(updates) {
1746
- this.update$(updates).subscribe();
1747
- }
1748
- revert$(lineItemId) {
1749
- const quoteDraft = this.quoteDraftService.quoteDraft;
1750
- const initialCurrentState = this.quoteDraftService.getInitialCurrentState();
1751
- const currentState = this.quoteDraftService.currentState;
1752
- const currentLineItemIndex = currentState.findIndex(({ id }) => id === lineItemId);
1753
- const currentLineItem = currentState[currentLineItemIndex];
1754
- const initialLineItem = initialCurrentState.find(({ integrationId }) => integrationId === currentLineItem?.integrationId);
1755
- if (!quoteDraft || !currentLineItem || !initialLineItem) {
1756
- return of(null);
1082
+ const owners$ = Object.values(this.flowInfoService.templates)
1083
+ .map(template => {
1084
+ if (!template) {
1085
+ return;
1086
+ }
1087
+ const localProcessors$ = this.customizationService?.getTemplateConfigurationProcessors?.(template.name) ?? of(null);
1088
+ return localProcessors$.pipe(switchMap(processors => processors ? of(processors) : this.processorsApiService.fetchConfigurationProcessors$(template.id)), tap(processors => {
1089
+ const processorsMap = processors.reduce((acc, p) => {
1090
+ acc[p.apiName] = p;
1091
+ return acc;
1092
+ }, {});
1093
+ this.processors[template.id] = processorsMap;
1094
+ }));
1095
+ })
1096
+ .filter(isDefined);
1097
+ if (!owners$.length) {
1098
+ return of(undefined);
1757
1099
  }
1758
- const updatedState = cloneDeep(currentState);
1759
- updatedState.splice(currentLineItemIndex, 1, initialLineItem);
1760
- return of([]).pipe(tap$1(() => {
1761
- this.quoteDraftService.setCurrentLineItemState(updatedState);
1762
- }), switchMap(() => this.calculate$({ ...quoteDraft, currentState: updatedState })), map$1(() => this.quoteDraftService.quoteDraft), tap$1(() => this.updatedSubj$.next()), this.handleErrorAndBounceBack());
1763
- }
1764
- revert(lineItemId) {
1765
- this.revert$(lineItemId).subscribe();
1100
+ return forkJoin(owners$).pipe(map(noop));
1766
1101
  }
1767
- delete$(ids) {
1768
- const quoteDraft = this.quoteDraftService.quoteDraft;
1769
- const currentState = this.quoteDraftService.currentState;
1770
- if (!quoteDraft) {
1771
- return of(null);
1102
+ executeActionScript(request, executable) {
1103
+ const configurationProcessor = this.processors[executable.ownerId]?.[executable.apiName];
1104
+ if (!configurationProcessor?.script) {
1105
+ const scope = this.getScopeByOwnerId(executable.ownerId);
1106
+ const scopeText = scope ? ` in ${scope}` : '';
1107
+ throw `ConfigurationProcessor ${executable.apiName}${scopeText} not found`;
1772
1108
  }
1773
- return of([]).pipe(map$1(() => ids.reduce((result, id) => this.updateService.delete(result, id), currentState)), switchMap(updatedState => this.calculate$({ ...quoteDraft, currentState: updatedState })), map$1(() => this.quoteDraftService.quoteDraft), tap$1(() => this.updatedSubj$.next()), this.handleErrorAndBounceBack());
1774
- }
1775
- delete(ids) {
1776
- this.delete$(ids).subscribe();
1109
+ return this.executeProcessorScript(request, configurationProcessor, executable.inputData);
1777
1110
  }
1778
- addTerm$(term) {
1779
- const quoteDraft = this.quoteDraftService.quoteDraft;
1780
- if (!quoteDraft) {
1781
- return of(null);
1111
+ executeSelectorScript(request, executable) {
1112
+ const configurationProcessor = this.processors[executable.ownerId]?.[executable.apiName];
1113
+ if (!configurationProcessor?.script) {
1114
+ const scope = this.getScopeByOwnerId(executable.ownerId);
1115
+ const scopeText = scope ? ` in ${scope}` : '';
1116
+ throw `ConfigurationProcessor ${executable.apiName}${scopeText} not found`;
1782
1117
  }
1783
- const updatedState = [...quoteDraft.currentState, term];
1784
- return of([]).pipe(switchMap(() => this.calculate$({ ...quoteDraft, currentState: updatedState })), map$1(() => this.quoteDraftService.quoteDraft), tap$1(() => this.updatedSubj$.next()), this.handleErrorAndBounceBack());
1118
+ return this.executeProcessorScript(request, configurationProcessor, executable.inputData);
1785
1119
  }
1786
- addToCart$(props) {
1787
- const quoteDraft = this.quoteDraftService.quoteDraft;
1788
- if (!quoteDraft) {
1789
- return of(null);
1120
+ executeProcessorScript(request, configurationProcessor, inputData) {
1121
+ const scope = this.getScopeByOwnerId(configurationProcessor.ownerId ?? '');
1122
+ let functionToExecute = this.executedFunctions[scope + configurationProcessor.apiName];
1123
+ if (!functionToExecute) {
1124
+ const script = `${configurationProcessor.script}\nreturn transform;`;
1125
+ const sourceMap = `\n//# sourceURL=${scope ? scope + '/' : ''}${configurationProcessor.apiName}.js`;
1126
+ functionToExecute = new Function(script + sourceMap)();
1127
+ this.executedFunctions[scope + configurationProcessor.apiName] = functionToExecute;
1790
1128
  }
1791
- return this.configurationService.configureExternal$(props).pipe(map$1(lineItem => {
1792
- const model = this.configurationService.getRuntimeModel();
1793
- const split = model?.types.find(type => type.name === lineItem.type)?.split ?? false;
1794
- const lineItems = multiplyLineItems(lineItem, props.qty ?? 1, split);
1795
- return [...quoteDraft.currentState, ...lineItems];
1796
- }), switchMap(updatedState => this.calculate$({ ...quoteDraft, currentState: updatedState })), map$1(() => this.quoteDraftService.quoteDraft), tap$1(() => this.updatedSubj$.next()), this.handleErrorAndBounceBack());
1797
- }
1798
- get() {
1799
- return this.quoteDraftService.quoteDraft$.pipe(map$1(() => this.quoteDraftService.currentState), shareReplay$1());
1800
- }
1801
- getSnapshot() {
1802
- return this.quoteDraftService?.currentState.slice() ?? [];
1803
- }
1804
- get charges$() {
1805
- return this.quoteDraftService.quoteDraft$.pipe(map$1(({ charges }) => charges));
1806
- }
1807
- get pricePlans$() {
1808
- return this.quoteDraftService.quoteDraft$.pipe(map$1(({ pricePlans }) => pricePlans));
1809
- }
1810
- get activeMetrics$() {
1811
- return this.quoteDraftService.quoteDraft$.pipe(map$1(({ activeMetrics }) => activeMetrics));
1812
- }
1813
- get chargesSnapshot() {
1814
- return this.quoteDraftService.quoteDraft?.charges ?? {};
1815
- }
1816
- get pricePlansSnapshot() {
1817
- return this.quoteDraftService.quoteDraft?.pricePlans ?? {};
1818
- }
1819
- get activeMetricsSnapshot() {
1820
- return this.quoteDraftService.quoteDraft?.activeMetrics ?? [];
1821
- }
1822
- get contextSnapshot() {
1823
- return this.contextService.resolve();
1824
- }
1825
- get context$() {
1826
- return this.contextService.resolve$();
1129
+ return functionToExecute({
1130
+ request,
1131
+ inputData,
1132
+ flowStore: this.flowStore,
1133
+ });
1827
1134
  }
1828
- handleErrorAndBounceBack() {
1829
- return (source$) => {
1830
- return source$.pipe(catchError(error => {
1831
- console.error(error);
1832
- // bounce back if configuration call has failed
1833
- const quoteDraft = this.quoteDraftService.quoteDraft;
1834
- if (quoteDraft) {
1835
- this.quoteDraftService.updateQuoteDraft(quoteDraft);
1836
- this.updatedSubj$.next();
1837
- }
1838
- return throwError(() => error);
1839
- }));
1840
- };
1135
+ generateRequestId(scope, selectorName, inputData) {
1136
+ const inputDataHash = UUID.hex(JSON.stringify(inputData) || '').slice(0, 8);
1137
+ return `${scope}/${selectorName}/${inputDataHash}`;
1841
1138
  }
1842
- extendedApply$(quoteDraft) {
1843
- const request = { ...quoteDraft };
1844
- const procedureName = this.flowInfoService.flow?.properties.procedureName;
1845
- if (procedureName) {
1846
- request.procedureName = procedureName;
1139
+ checkStatefulChanges(requestId, selectorResult) {
1140
+ if (this.trackedStatefulChangesMap.has(requestId)) {
1141
+ if (!this.initialStatefulData[requestId]) {
1142
+ this.initialStatefulData[requestId] = selectorResult;
1143
+ }
1144
+ const hasChanges = !isEqual(this.initialStatefulData[requestId], selectorResult);
1145
+ this.trackedStatefulChangesMap.set(requestId, hasChanges);
1847
1146
  }
1848
- return this.proceduresApiService.apply$(request);
1849
1147
  }
1850
1148
  }
1851
- FlowConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationService, deps: [{ token: i1.ProceduresApiService }, { token: ContextService }, { token: QuoteDraftService }, { token: FlowUpdateService }, { token: ConfigurationService }, { token: FlowInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
1852
- FlowConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationService });
1853
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationService, decorators: [{
1149
+ FlowStateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateService, deps: [{ token: FlowConfigurationService }, { token: FlowInfoService }, { token: i3.FlowStateApiService }, { token: i1.ConfigurationProcessorsApiService }, { token: i1.SalesTransactionApiService }, { token: SalesTransactionService }, { token: i6.ToastService }, { token: FLOW_CUSTOMIZATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1150
+ FlowStateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateService });
1151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateService, decorators: [{
1854
1152
  type: Injectable
1855
- }], ctorParameters: function () { return [{ type: i1.ProceduresApiService }, { type: ContextService }, { type: QuoteDraftService }, { type: FlowUpdateService }, { type: ConfigurationService }, { type: FlowInfoService }]; } });
1856
-
1857
- class FlowConfigurationModule {
1858
- }
1859
- FlowConfigurationModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1860
- FlowConfigurationModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, imports: [ApiModule] });
1861
- FlowConfigurationModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, providers: [FlowConfigurationService, FlowUpdateService], imports: [ApiModule] });
1862
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, decorators: [{
1863
- type: NgModule,
1864
- args: [{
1865
- imports: [ApiModule],
1866
- providers: [FlowConfigurationService, FlowUpdateService],
1867
- }]
1868
- }] });
1153
+ }], ctorParameters: function () { return [{ type: FlowConfigurationService }, { type: FlowInfoService }, { type: i3.FlowStateApiService }, { type: i1.ConfigurationProcessorsApiService }, { type: i1.SalesTransactionApiService }, { type: SalesTransactionService }, { type: i6.ToastService }, { type: undefined, decorators: [{
1154
+ type: Optional
1155
+ }, {
1156
+ type: Inject,
1157
+ args: [FLOW_CUSTOMIZATION]
1158
+ }] }]; } });
1869
1159
 
1870
1160
  class FlowStateConfigurationService {
1871
- constructor(flowInfoService, flowConfigurationService, flowStateApiService, flowStateService) {
1161
+ constructor(flowInfoService, flowStateService, configurationService, salesTransactionService, flowConfigurationService) {
1872
1162
  this.flowInfoService = flowInfoService;
1873
- this.flowConfigurationService = flowConfigurationService;
1874
- this.flowStateApiService = flowStateApiService;
1875
1163
  this.flowStateService = flowStateService;
1876
- this.configurationStateId$ = new BehaviorSubject(null);
1877
- }
1878
- get configurationStateId() {
1879
- return this.configurationStateId$.value;
1164
+ this.configurationService = configurationService;
1165
+ this.salesTransactionService = salesTransactionService;
1166
+ this.flowConfigurationService = flowConfigurationService;
1880
1167
  }
1881
1168
  addToCart$(props) {
1882
1169
  let request$;
@@ -1887,26 +1174,57 @@ class FlowStateConfigurationService {
1887
1174
  request$ = of();
1888
1175
  }
1889
1176
  else {
1890
- const lineItem = generateConfigurationLineItem(props, props.qty);
1891
- request$ = this.flowStateApiService.newConfiguration(stateId, { lineItem }).pipe(tap$1(r => this.configurationStateId$.next(r.stateId)), switchMap(() => {
1892
- if (!this.configurationStateId) {
1893
- return of();
1894
- }
1895
- return this.flowStateApiService.saveConfiguration(stateId, this.configurationStateId).pipe(tap$1(() => this.configurationStateId$.next(null)), map$1(noop));
1896
- }));
1177
+ // TODO: Implement
1178
+ request$ = of();
1897
1179
  }
1898
1180
  }
1899
1181
  else {
1900
- request$ = this.flowConfigurationService.addToCart$(props).pipe(map$1(noop));
1182
+ request$ = this.configureExternal$(props);
1901
1183
  }
1902
- return request$.pipe(switchMap(() => this.flowStateService.executeRequest$({}, true)), map$1(noop));
1184
+ return request$.pipe(switchMap(() => this.flowStateService.executeRequest$({}, true)), map(noop));
1185
+ }
1186
+ configureExternal$(props) {
1187
+ const { state } = this.salesTransactionService;
1188
+ if (!state) {
1189
+ return of();
1190
+ }
1191
+ const stateToConfigure = {
1192
+ ...state,
1193
+ salesTransaction: {
1194
+ ...state.salesTransaction,
1195
+ salesTransactionItems: [
1196
+ {
1197
+ ...generateTransactionItem(props.productId),
1198
+ qty: props.qty ?? 1,
1199
+ stiAttributes: Object.entries(props.attributesMap ?? {}).map(([attributeName, value]) => ({
1200
+ attributeName,
1201
+ value,
1202
+ })),
1203
+ },
1204
+ ],
1205
+ },
1206
+ };
1207
+ return this.configurationService.justConfigureRequest$(stateToConfigure).pipe(switchMap(configurationResult => {
1208
+ const state = this.salesTransactionService.state;
1209
+ const addedProduct = configurationResult.salesTransaction.salesTransactionItems[0];
1210
+ if (!state || !addedProduct) {
1211
+ return of();
1212
+ }
1213
+ return this.flowConfigurationService.calculate$({
1214
+ ...state,
1215
+ salesTransaction: {
1216
+ ...state.salesTransaction,
1217
+ salesTransactionItems: [...state.salesTransaction.salesTransactionItems, addedProduct],
1218
+ },
1219
+ });
1220
+ }));
1903
1221
  }
1904
1222
  }
1905
- FlowStateConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateConfigurationService, deps: [{ token: FlowInfoService }, { token: FlowConfigurationService }, { token: i1.FlowStateApiService }, { token: FlowStateService }], target: i0.ɵɵFactoryTarget.Injectable });
1223
+ FlowStateConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateConfigurationService, deps: [{ token: FlowInfoService }, { token: FlowStateService }, { token: ConfigurationService }, { token: SalesTransactionService }, { token: FlowConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable });
1906
1224
  FlowStateConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateConfigurationService });
1907
1225
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowStateConfigurationService, decorators: [{
1908
1226
  type: Injectable
1909
- }], ctorParameters: function () { return [{ type: FlowInfoService }, { type: FlowConfigurationService }, { type: i1.FlowStateApiService }, { type: FlowStateService }]; } });
1227
+ }], ctorParameters: function () { return [{ type: FlowInfoService }, { type: FlowStateService }, { type: ConfigurationService }, { type: SalesTransactionService }, { type: FlowConfigurationService }]; } });
1910
1228
 
1911
1229
  class IntegrationState {
1912
1230
  constructor() {
@@ -1926,12 +1244,12 @@ class IntegrationState {
1926
1244
  this.action$.next(action);
1927
1245
  }
1928
1246
  listen$(actionType) {
1929
- return this.action$.pipe(filter$1(action => action.type === actionType), map$1(action => action.payload));
1247
+ return this.action$.pipe(filter(action => action.type === actionType), map(action => action.payload));
1930
1248
  }
1931
1249
  listenAll$() {
1932
1250
  return this.action$.asObservable();
1933
1251
  }
1934
- clear() {
1252
+ reset() {
1935
1253
  this.stateSubj$.next({});
1936
1254
  }
1937
1255
  }
@@ -1942,8 +1260,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
1942
1260
  }] });
1943
1261
 
1944
1262
  class ProductImagesService {
1945
- constructor(productApiService) {
1946
- this.productApiService = productApiService;
1263
+ constructor(productsAdminApiService) {
1264
+ this.productsAdminApiService = productsAdminApiService;
1947
1265
  this.imagesMap$ = new BehaviorSubject({});
1948
1266
  }
1949
1267
  getImageUrl$(productId) {
@@ -1951,172 +1269,53 @@ class ProductImagesService {
1951
1269
  this.imagesMap$.next({ ...this.imagesMap$.value, [productId]: '' });
1952
1270
  this.fetchProductImage(productId);
1953
1271
  }
1954
- return this.imagesMap$.pipe(map$1(imagesMap => imagesMap[productId] ?? null), distinctUntilChanged());
1272
+ return this.imagesMap$.pipe(map(imagesMap => imagesMap[productId] ?? null), distinctUntilChanged());
1955
1273
  }
1956
1274
  fetchProductImage(productId) {
1957
- this.productApiService
1275
+ this.productsAdminApiService
1958
1276
  .fetchImage$(productId)
1959
- .pipe(map$1(file => URL.createObjectURL(file)), catchError(() => of('')), tap$1(url => this.imagesMap$.next({ ...this.imagesMap$.value, [productId]: url })))
1277
+ .pipe(map(file => URL.createObjectURL(file)), catchError$1(() => of('')), tap(url => this.imagesMap$.next({ ...this.imagesMap$.value, [productId]: url })))
1960
1278
  .subscribe();
1961
1279
  }
1962
1280
  }
1963
- ProductImagesService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ProductImagesService, deps: [{ token: i1.ProductApiService }], target: i0.ɵɵFactoryTarget.Injectable });
1281
+ ProductImagesService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ProductImagesService, deps: [{ token: i1.ProductsAdminApiService }], target: i0.ɵɵFactoryTarget.Injectable });
1964
1282
  ProductImagesService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ProductImagesService });
1965
1283
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ProductImagesService, decorators: [{
1966
1284
  type: Injectable
1967
- }], ctorParameters: function () { return [{ type: i1.ProductApiService }]; } });
1285
+ }], ctorParameters: function () { return [{ type: i1.ProductsAdminApiService }]; } });
1968
1286
 
1969
- class RuntimeContextService {
1970
- constructor(configurationApiService) {
1971
- this.configurationApiService = configurationApiService;
1972
- }
1973
- getRuntimeContext(productId, offeringId, defaultUIDefinitionId, requiredUIDefinitionId) {
1974
- return this.configurationApiService
1975
- .getRuntimeDataByProductId(productId, offeringId, defaultUIDefinitionId, requiredUIDefinitionId)
1976
- .pipe(map(runtimeData => {
1977
- const uiDefinitionContainer = this.getUIDefinitionContainer(runtimeData);
1978
- const runtimeModel = RuntimeModel.create(runtimeData.types, runtimeData.products);
1979
- const { productName, properties } = Array.from(runtimeModel.components.values()).find(c => c.productId === productId) ?? {};
1980
- const uiDefinitionProperties = uiDefinitionContainer?.source.properties;
1981
- return {
1982
- modelId: runtimeData.modelId,
1983
- uiDefinitionContainer: uiDefinitionContainer,
1984
- runtimeModel: runtimeModel,
1985
- runtimeMode: RuntimeMode.PROD,
1986
- productId: productId,
1987
- productType: properties?.['displayName'] || productName,
1988
- offeringId: offeringId,
1989
- properties: {
1990
- PricingEnabled: uiDefinitionProperties?.pricingEnabled ? 'true' : 'false',
1991
- PriceListId: uiDefinitionProperties?.priceList,
1992
- },
1993
- };
1994
- }));
1995
- }
1996
- getUIDefinitionContainer(runtimeData) {
1997
- const containers = runtimeData.uiDefinitions.filter(container => isNotLegacyUIDefinition(container.source));
1998
- return containers.find(container => container.source.primary) ?? containers[0];
1287
+ class CatalogProductsService {
1288
+ constructor() {
1289
+ this.stateSubj$ = new BehaviorSubject(null);
1290
+ this.state$ = this.stateSubj$.asObservable().pipe(filter(isDefined));
1999
1291
  }
2000
- }
2001
- RuntimeContextService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeContextService, deps: [{ token: i1.ConfigurationApiService }], target: i0.ɵɵFactoryTarget.Injectable });
2002
- RuntimeContextService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeContextService });
2003
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: RuntimeContextService, decorators: [{
2004
- type: Injectable
2005
- }], ctorParameters: function () { return [{ type: i1.ConfigurationApiService }]; } });
2006
-
2007
- class ConfigurationRuntimeService {
2008
- constructor(apiService, contextService, runtimeContextService) {
2009
- this.apiService = apiService;
2010
- this.contextService = contextService;
2011
- this.runtimeContextService = runtimeContextService;
2012
- this._isInitialized = false;
2013
- this.uiDefinitionProperties = {};
1292
+ get state() {
1293
+ return this.stateSubj$.getValue();
2014
1294
  }
2015
1295
  reset() {
2016
- this._isInitialized = false;
2017
- this._runtimeContext = undefined;
2018
- this.initializationProps = undefined;
2019
- this.uiDefinitionProperties = {};
2020
- }
2021
- initTestMode(uiDefinitionContainer) {
2022
- this.uiDefinitionProperties = uiDefinitionContainer.source.properties ?? {};
2023
- const uiDefinitionExternals = uiDefinitionContainer.source.externals ?? {};
2024
- return combineLatest([
2025
- this.apiService.getRuntimeDataByModelId(uiDefinitionContainer.modelId),
2026
- this.contextService.initTestMode(),
2027
- ]).pipe(first(), map(([runtimeData, context]) => {
2028
- this.contextService.update({
2029
- properties: {
2030
- ...this.runtimeContext?.properties,
2031
- ...context.properties,
2032
- ModelId: uiDefinitionContainer.modelId,
2033
- PricingEnabled: this.uiDefinitionProperties.pricingEnabled ? 'true' : 'false',
2034
- PriceListId: this.uiDefinitionProperties.priceList,
2035
- offeringId: this.uiDefinitionProperties.offeringId,
2036
- ...uiDefinitionExternals,
2037
- },
2038
- });
2039
- this._runtimeContext = {
2040
- modelId: uiDefinitionContainer.modelId,
2041
- runtimeModel: RuntimeModel.create(runtimeData.types, runtimeData.products),
2042
- runtimeMode: RuntimeMode.TEST,
2043
- uiDefinitionContainer,
2044
- };
2045
- return this._runtimeContext;
2046
- }), tap(() => (this._isInitialized = true)));
2047
- }
2048
- init(props) {
2049
- this.initializationProps = props;
2050
- const context = this.contextService.resolve();
2051
- return this.runtimeContextService
2052
- .getRuntimeContext(props.productId, props.offeringId, props.defaultUIDefinitionId, props.requiredUIDefinitionId)
2053
- .pipe(tap(runtimeContext => {
2054
- this.uiDefinitionProperties = runtimeContext.uiDefinitionContainer?.source.properties ?? {};
2055
- const { PriceListId } = context.properties ?? {};
2056
- const mergeContext = {
2057
- ...runtimeContext,
2058
- properties: {
2059
- ...runtimeContext.properties,
2060
- ...context.properties,
2061
- PricingEnabled: PriceListId ? 'true' : 'false',
2062
- },
2063
- };
2064
- this.id15to18('AccountId', mergeContext.properties);
2065
- this._runtimeContext = mergeContext;
2066
- if (context.properties && this._runtimeContext.properties?.StartDate) {
2067
- this.contextService.update({
2068
- properties: {
2069
- ...this._runtimeContext.properties,
2070
- ...context.properties,
2071
- },
2072
- });
2073
- }
2074
- return this._runtimeContext;
2075
- }), tap(() => (this._isInitialized = true)));
2076
- }
2077
- overrideUIDefinition(uiDefinitionContainer) {
2078
- if (!this._runtimeContext) {
2079
- return;
2080
- }
2081
- this._runtimeContext.uiDefinitionContainer = uiDefinitionContainer;
2082
- this.uiDefinitionProperties = uiDefinitionContainer.source.properties ?? {};
2083
- }
2084
- id15to18(propertyName, source) {
2085
- if (!source) {
2086
- return;
2087
- }
2088
- const value = source[propertyName];
2089
- if (typeof value === 'string' && value.length === 15) {
2090
- source[propertyName] = SalesforceIdUtils.generateId18FromId15(value);
2091
- }
2092
- }
2093
- get isInitialized() {
2094
- return this._isInitialized;
2095
- }
2096
- get runtimeModel() {
2097
- return this.runtimeContext?.runtimeModel;
1296
+ this.stateSubj$.next(null);
2098
1297
  }
2099
- get runtimeContext() {
2100
- return this._runtimeContext;
1298
+ setState(state) {
1299
+ this.stateSubj$.next(state);
2101
1300
  }
2102
1301
  }
2103
- ConfigurationRuntimeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationRuntimeService, deps: [{ token: i1.ConfigurationApiService }, { token: ContextService }, { token: RuntimeContextService }], target: i0.ɵɵFactoryTarget.Injectable });
2104
- ConfigurationRuntimeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationRuntimeService });
2105
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationRuntimeService, decorators: [{
1302
+ CatalogProductsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: CatalogProductsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1303
+ CatalogProductsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: CatalogProductsService });
1304
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: CatalogProductsService, decorators: [{
2106
1305
  type: Injectable
2107
- }], ctorParameters: function () { return [{ type: i1.ConfigurationApiService }, { type: ContextService }, { type: RuntimeContextService }]; } });
1306
+ }] });
2108
1307
 
2109
1308
  class ConfigurationStateService {
2110
- constructor(configurationRuntimeService, configurationService, quoteDraftService, toastService, flowStateService, flowInfoService, flowConfigurationService, flowStateApiService, quoteApiService) {
1309
+ constructor(configurationRuntimeService, configurationService, flowStateService, flowInfoService, flowConfigurationService, flowStateApiService, salesTransactionService, salesTransactionApiService, toastService) {
2111
1310
  this.configurationRuntimeService = configurationRuntimeService;
2112
1311
  this.configurationService = configurationService;
2113
- this.quoteDraftService = quoteDraftService;
2114
- this.toastService = toastService;
2115
1312
  this.flowStateService = flowStateService;
2116
1313
  this.flowInfoService = flowInfoService;
2117
1314
  this.flowConfigurationService = flowConfigurationService;
2118
1315
  this.flowStateApiService = flowStateApiService;
2119
- this.quoteApiService = quoteApiService;
1316
+ this.salesTransactionService = salesTransactionService;
1317
+ this.salesTransactionApiService = salesTransactionApiService;
1318
+ this.toastService = toastService;
2120
1319
  this.isInitialized$ = new BehaviorSubject(false);
2121
1320
  this.canceledConfiguration$ = new Subject();
2122
1321
  this.NOT_INITIALIZED = Symbol();
@@ -2140,9 +1339,9 @@ class ConfigurationStateService {
2140
1339
  request$ = this.initStateful$();
2141
1340
  }
2142
1341
  else {
2143
- request$ = this.initStateless$();
1342
+ request$ = this.configurationService.init$();
2144
1343
  }
2145
- return request$.pipe(finalize(() => {
1344
+ return request$.pipe(take(1), tap(() => {
2146
1345
  this.isInitialized$.next(true);
2147
1346
  this.canceledConfiguration$ = new Subject();
2148
1347
  }));
@@ -2156,10 +1355,11 @@ class ConfigurationStateService {
2156
1355
  this.configurationStore = {};
2157
1356
  this.executedFunctions = {};
2158
1357
  this.configurationService.reset();
1358
+ this.configurationRuntimeService.reset();
2159
1359
  }
2160
1360
  execute$(exec) {
2161
1361
  const request = this.execToRequest(exec);
2162
- return this.executeRequest$(request).pipe(map$1(result => {
1362
+ return this.executeRequest$(request).pipe(map(result => {
2163
1363
  // Keep only requested results
2164
1364
  const actualSelectors = Object.entries(result.selectors).reduce((trunk, [requestId, result]) => {
2165
1365
  if (exec.selectors?.[requestId]) {
@@ -2181,7 +1381,7 @@ class ConfigurationStateService {
2181
1381
  }
2182
1382
  // prevent parallel configuration requests in stateless mode
2183
1383
  if (!this.statelessExecutionRequest$) {
2184
- this.statelessExecutionRequest$ = executionRequest$.pipe(shareReplay$1(), take$1(1), finalize(() => (this.statelessExecutionRequest$ = null)));
1384
+ this.statelessExecutionRequest$ = executionRequest$.pipe(shareReplay(), take(1), finalize$1(() => (this.statelessExecutionRequest$ = null)));
2185
1385
  }
2186
1386
  return this.statelessExecutionRequest$;
2187
1387
  }
@@ -2195,7 +1395,7 @@ class ConfigurationStateService {
2195
1395
  },
2196
1396
  },
2197
1397
  });
2198
- return this.executeRequest$(request).pipe(map$1(response => response.selectors[requestId]));
1398
+ return this.executeRequest$(request).pipe(map(response => response.selectors[requestId]));
2199
1399
  }
2200
1400
  subscribe$(selectorName, inputData = {}, options) {
2201
1401
  const requestId = UUID.UUID();
@@ -2218,56 +1418,50 @@ class ConfigurationStateService {
2218
1418
  this.executeRequest$(request).subscribe();
2219
1419
  }
2220
1420
  }
2221
- return subscription.data$.pipe(filter$1(data => data != this.NOT_INITIALIZED), map$1(data => data), distinctUntilChanged(), finalize(() => {
1421
+ return subscription.data$.pipe(filter(data => data != this.NOT_INITIALIZED), map(data => data), distinctUntilChanged(), finalize$1(() => {
2222
1422
  if (!this.subscriptions[requestId]?.data$.observed) {
2223
1423
  delete this.subscriptions[requestId];
2224
1424
  }
2225
1425
  }), takeUntil(this.canceledConfiguration$));
2226
1426
  }
2227
- saveConfiguration(flow) {
1427
+ saveConfiguration() {
2228
1428
  if (this.isStatefulConfiguration) {
2229
- return this.flowStateApiService
2230
- .saveConfiguration(this.flowStateService.stateId ?? '', this.stateId ?? '')
2231
- .pipe(switchMap(r => this.flowStateService.executeRequest$({}, true).pipe(map$1(() => r))));
1429
+ return this.flowStateApiService.saveConfiguration(this.flowStateService.stateId ?? '', this.stateId ?? '').pipe(switchMap(r => this.flowStateService.executeRequest$({}, true).pipe(map(() => r))), map(r => ({ id: r.quoteId })));
1430
+ }
1431
+ const state = this.salesTransactionService.state;
1432
+ if (!state) {
1433
+ return of({ id: '' });
1434
+ }
1435
+ const { standalone } = this.flowInfoService.flow.properties;
1436
+ if (standalone) {
1437
+ const request = {
1438
+ transactionContext: state,
1439
+ flowId: this.flowInfoService.flow.id,
1440
+ };
1441
+ return this.salesTransactionApiService.save(request).pipe(switchMap(r => this.flowStateService.executeRequest$({}, true).pipe(map(() => r))), map(id => ({ id })));
1442
+ }
1443
+ const transactionContext = this.salesTransactionService.state;
1444
+ const configurationRoot = this.configurationService.root;
1445
+ if (!transactionContext || !configurationRoot) {
1446
+ return of({ id: '' });
1447
+ }
1448
+ const stateItems = transactionContext.salesTransaction.salesTransactionItems;
1449
+ const isNewTransactionItem = stateItems.every(ti => ti.id !== configurationRoot.id);
1450
+ let salesTransactionItems;
1451
+ if (isNewTransactionItem) {
1452
+ salesTransactionItems = [...stateItems, configurationRoot];
2232
1453
  }
2233
1454
  else {
2234
- if (!flow) {
2235
- const quoteDraft = this.quoteDraftService.quoteDraft;
2236
- if (!quoteDraft) {
2237
- return of({ quoteId: '' });
2238
- }
2239
- const rootLineItem = this.configurationService.getSnapshot();
2240
- const asset = this.configurationService.getAsset();
2241
- const currentState = rootLineItem ? [rootLineItem] : [];
2242
- const initialState = asset ? [asset] : [];
2243
- return this.quoteApiService.upsertQuote({ ...quoteDraft, currentState, initialState });
2244
- }
2245
- else {
2246
- const quoteDraft = this.quoteDraftService.quoteDraft;
2247
- const lineItem = this.configurationService.getSnapshot();
2248
- if (!quoteDraft || !lineItem) {
2249
- return of({ quoteId: '' });
2250
- }
2251
- const isNewLineItem = quoteDraft.currentState.every(li => li.id !== lineItem.id);
2252
- let currentState;
2253
- if (isNewLineItem) {
2254
- currentState = [...quoteDraft.currentState, lineItem];
2255
- }
2256
- else {
2257
- currentState = quoteDraft.currentState.map(li => (li.id === lineItem.id ? lineItem : li));
2258
- }
2259
- const asset = this.configurationService.getAsset();
2260
- const initialState = [...(this.quoteDraftService.quoteDraft?.initialState ?? [])];
2261
- if (asset) {
2262
- if (!initialState.some(li => li.id === asset.id)) {
2263
- initialState.push(asset);
2264
- }
2265
- }
2266
- return this.flowConfigurationService
2267
- .calculate$({ ...quoteDraft, currentState, initialState })
2268
- .pipe(map$1(() => ({ quoteId: '' })));
2269
- }
1455
+ salesTransactionItems = stateItems.map(ti => (ti.id === configurationRoot.id ? configurationRoot : ti));
2270
1456
  }
1457
+ const newState = {
1458
+ ...transactionContext,
1459
+ salesTransaction: {
1460
+ ...transactionContext.salesTransaction,
1461
+ salesTransactionItems,
1462
+ },
1463
+ };
1464
+ return this.flowConfigurationService.calculate$(newState).pipe(switchMap(() => this.flowStateService.executeRequest$({}, true)), map(() => ({ id: '' })));
2271
1465
  }
2272
1466
  cancelConfiguration() {
2273
1467
  if (!this.isInitialized$.value) {
@@ -2286,36 +1480,32 @@ class ConfigurationStateService {
2286
1480
  return this.flowInfoService.flow?.properties.stateful ?? false;
2287
1481
  }
2288
1482
  initStateful$() {
2289
- this.ownerId = this.configurationRuntimeService.runtimeContext?.uiDefinitionContainer?.id ?? '';
2290
- const lineItemId = this.configurationRuntimeService.runtimeContext?.properties?.lineItemId;
2291
- if (!this.flowStateService.stateId) {
1483
+ this.ownerId = this.configurationRuntimeService.uiDefinitionContainer?.id ?? '';
1484
+ const { productId, transactionItemId } = this.flowInfoService.context;
1485
+ if (!productId || !this.flowStateService.stateId) {
2292
1486
  return of(undefined);
2293
1487
  }
2294
- const container = this.configurationRuntimeService.runtimeContext?.uiDefinitionContainer;
2295
- const lineItem = this.configurationService.generateLineItem();
1488
+ const container = this.configurationRuntimeService.uiDefinitionContainer;
2296
1489
  let request$;
2297
- if (!lineItemId) {
1490
+ if (!transactionItemId) {
2298
1491
  request$ = this.flowStateApiService.newConfiguration(this.flowStateService.stateId, {
2299
- lineItem,
1492
+ transactionItem: generateTransactionItem(productId),
2300
1493
  actionsOverride: container?.actions?.map(processor => ({ ...processor, ownerId: this.ownerId })),
2301
1494
  selectorsOverride: container?.selectors?.map(processor => ({ ...processor, ownerId: this.ownerId })),
2302
1495
  });
2303
1496
  }
2304
1497
  else {
2305
1498
  request$ = this.flowStateApiService.startConfiguration(this.flowStateService.stateId, {
2306
- lineItemId,
1499
+ transactionItemId,
2307
1500
  actionsOverride: container?.actions?.map(processor => ({ ...processor, ownerId: this.ownerId })),
2308
1501
  selectorsOverride: container?.selectors?.map(processor => ({ ...processor, ownerId: this.ownerId })),
2309
1502
  });
2310
1503
  }
2311
- return request$.pipe(map$1(r => {
1504
+ return request$.pipe(map(r => {
2312
1505
  this.stateId = r.stateId;
2313
1506
  return undefined;
2314
1507
  }));
2315
1508
  }
2316
- initStateless$() {
2317
- return this.configurationService.configure().pipe(map$1(() => undefined));
2318
- }
2319
1509
  execToRequest(exec) {
2320
1510
  return {
2321
1511
  actions: exec.actions?.map(action => ({
@@ -2355,37 +1545,35 @@ class ConfigurationStateService {
2355
1545
  else {
2356
1546
  execution$ = this.executeStateless$(fullRequest);
2357
1547
  }
2358
- return execution$.pipe(tap$1(result => this.handleSelectorsResponse(result.selectors)));
1548
+ return execution$.pipe(tap(result => this.handleSelectorsResponse(result.selectors)));
2359
1549
  }
2360
1550
  executeStateless$(request) {
2361
1551
  this.executionInProgress$.next(true);
2362
- return of(undefined).pipe(switchMap(() => {
1552
+ return this.configurationService.state$.pipe(first(), switchMap(state => {
2363
1553
  // Apply actions and execute configuration/price call
2364
1554
  // No need to run configuration if no actions in the request
2365
1555
  if (!request.actions?.length) {
2366
1556
  return of(undefined);
2367
1557
  }
2368
- let configurationRequest = this.configurationService.generateRequest(false);
2369
1558
  request.actions.forEach(action => {
2370
- configurationRequest = this.executeActionScript(configurationRequest, action) ?? configurationRequest;
1559
+ state = this.executeActionScript(state, action) ?? state;
2371
1560
  });
2372
- configurationRequest = ConfigurationTranslatorUtils.lightenConfigurationRequest(configurationRequest);
2373
- return this.configurationService.configureRequest$(configurationRequest);
2374
- }), map$1(() => {
1561
+ return this.configurationService.configure$(state);
1562
+ }), map(() => {
2375
1563
  // Run selectors and apply them to the state
2376
- const configurationState = this.configurationService.stateSnapshot;
1564
+ const configurationState = this.configurationService.state;
2377
1565
  if (!configurationState) {
2378
1566
  return { stateId: '', selectors: {} };
2379
1567
  }
2380
1568
  return this.runStatelessSelectors(request, configurationState);
2381
- }), tap$1(() => this.executionInProgress$.next(false)), catchError(error => {
2382
- const configurationState = this.configurationService.previousStateSnapshot;
1569
+ }), tap(() => this.executionInProgress$.next(false)), catchError$1(error => {
1570
+ const configurationState = this.configurationService.previousState;
2383
1571
  if (configurationState) {
2384
1572
  const selectorsResult = this.runStatelessSelectors(request, configurationState);
2385
1573
  this.handleSelectorsResponse(selectorsResult.selectors);
2386
1574
  }
2387
1575
  this.executionInProgress$.next(false);
2388
- if (!this.configurationRuntimeService.uiDefinitionProperties.suppressToastMessages) {
1576
+ if (!this.configurationRuntimeService.uiDefinitionProps.suppressToastMessages) {
2389
1577
  this.toastService.add({ severity: ToastType.error, summary: String(error) });
2390
1578
  }
2391
1579
  return throwError(() => error);
@@ -2406,21 +1594,21 @@ class ConfigurationStateService {
2406
1594
  };
2407
1595
  this.executionInProgress$.next(true);
2408
1596
  return this.flowStateApiService.executeConfiguration(this.flowStateService.stateId, this.stateId, request);
2409
- }), tap$1(({ stateId }) => (this.stateId = stateId)), share(), tap$1(() => this.executionInProgress$.next(false)), catchError(e => {
1597
+ }), tap(({ stateId }) => (this.stateId = stateId)), share(), tap(() => this.executionInProgress$.next(false)), catchError$1(e => {
2410
1598
  this.executionInProgress$.next(false);
2411
1599
  return throwError(() => e);
2412
1600
  }));
2413
1601
  }
2414
1602
  executeStateful$(request) {
2415
- return this.executionInProgress$.pipe(filter$1(inProgress => !inProgress), take$1(1), switchMap(() =>
1603
+ return this.executionInProgress$.pipe(filter(inProgress => !inProgress), take(1), switchMap(() =>
2416
1604
  // make sure stream switches to statefulExecutionRequest$ before pushing an execution request
2417
1605
  combineLatest([
2418
1606
  this.statefulExecutionRequest$,
2419
- of(undefined).pipe(tap$1(() => this.statefulRequestStream$.next(request))),
2420
- ])), map$1(([response]) => response), take$1(1));
1607
+ of(undefined).pipe(tap(() => this.statefulRequestStream$.next(request))),
1608
+ ])), map(([response]) => response), take(1));
2421
1609
  }
2422
1610
  executeActionScript(request, processor) {
2423
- const { actions } = this.configurationRuntimeService.runtimeContext?.uiDefinitionContainer ?? {};
1611
+ const { actions } = this.configurationRuntimeService.uiDefinitionContainer ?? {};
2424
1612
  const configurationProcessor = actions?.find(action => action.apiName === processor.apiName);
2425
1613
  if (!configurationProcessor?.script) {
2426
1614
  throw `ConfigurationProcessor ${processor.apiName} not found`;
@@ -2428,7 +1616,7 @@ class ConfigurationStateService {
2428
1616
  return this.executeProcessorScript(request, configurationProcessor, processor.inputData);
2429
1617
  }
2430
1618
  executeSelectorScript(request, processor) {
2431
- const { selectors } = this.configurationRuntimeService.runtimeContext?.uiDefinitionContainer ?? {};
1619
+ const { selectors } = this.configurationRuntimeService.uiDefinitionContainer ?? {};
2432
1620
  const configurationProcessor = selectors?.find(selector => selector.apiName === processor.apiName);
2433
1621
  if (!configurationProcessor?.script) {
2434
1622
  throw `ConfigurationProcessor ${processor.apiName} not found`;
@@ -2469,25 +1657,54 @@ class ConfigurationStateService {
2469
1657
  }, { stateId: '', selectors: {} });
2470
1658
  }
2471
1659
  }
2472
- ConfigurationStateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationStateService, deps: [{ token: ConfigurationRuntimeService }, { token: ConfigurationService }, { token: QuoteDraftService }, { token: i6.ToastService }, { token: FlowStateService }, { token: FlowInfoService }, { token: FlowConfigurationService }, { token: i1.FlowStateApiService }, { token: i1.QuoteApiService }], target: i0.ɵɵFactoryTarget.Injectable });
1660
+ ConfigurationStateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationStateService, deps: [{ token: ConfigurationRuntimeService }, { token: ConfigurationService }, { token: FlowStateService }, { token: FlowInfoService }, { token: FlowConfigurationService }, { token: i3.FlowStateApiService }, { token: SalesTransactionService }, { token: i1.SalesTransactionApiService }, { token: i6.ToastService }], target: i0.ɵɵFactoryTarget.Injectable });
2473
1661
  ConfigurationStateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationStateService });
2474
1662
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationStateService, decorators: [{
2475
1663
  type: Injectable
2476
- }], ctorParameters: function () { return [{ type: ConfigurationRuntimeService }, { type: ConfigurationService }, { type: QuoteDraftService }, { type: i6.ToastService }, { type: FlowStateService }, { type: FlowInfoService }, { type: FlowConfigurationService }, { type: i1.FlowStateApiService }, { type: i1.QuoteApiService }]; } });
1664
+ }], ctorParameters: function () { return [{ type: ConfigurationRuntimeService }, { type: ConfigurationService }, { type: FlowStateService }, { type: FlowInfoService }, { type: FlowConfigurationService }, { type: i3.FlowStateApiService }, { type: SalesTransactionService }, { type: i1.SalesTransactionApiService }, { type: i6.ToastService }]; } });
2477
1665
 
2478
1666
  class ConfigurationModule {
2479
1667
  }
2480
1668
  ConfigurationModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2481
1669
  ConfigurationModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationModule, imports: [ConfirmationDialogModule, ApiModule] });
2482
- ConfigurationModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationModule, providers: [ConfigurationRuntimeService, RuntimeContextService, ConfigurationService, ConfigurationStateService], imports: [ConfirmationDialogModule, ApiModule] });
1670
+ ConfigurationModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationModule, providers: [
1671
+ ConfigurationService,
1672
+ ConfigurationStateService,
1673
+ ConfigurationRuntimeService,
1674
+ TestModeConfigurationService,
1675
+ GuidedSellingService,
1676
+ ], imports: [ConfirmationDialogModule, ApiModule] });
2483
1677
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ConfigurationModule, decorators: [{
2484
1678
  type: NgModule,
2485
1679
  args: [{
2486
1680
  imports: [ConfirmationDialogModule, ApiModule],
2487
- providers: [ConfigurationRuntimeService, RuntimeContextService, ConfigurationService, ConfigurationStateService],
1681
+ providers: [
1682
+ ConfigurationService,
1683
+ ConfigurationStateService,
1684
+ ConfigurationRuntimeService,
1685
+ TestModeConfigurationService,
1686
+ GuidedSellingService,
1687
+ ],
1688
+ }]
1689
+ }] });
1690
+
1691
+ class FlowConfigurationModule {
1692
+ }
1693
+ FlowConfigurationModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1694
+ FlowConfigurationModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, imports: [ApiModule] });
1695
+ FlowConfigurationModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, providers: [FlowConfigurationService], imports: [ApiModule] });
1696
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FlowConfigurationModule, decorators: [{
1697
+ type: NgModule,
1698
+ args: [{
1699
+ imports: [ApiModule],
1700
+ providers: [FlowConfigurationService],
2488
1701
  }]
2489
1702
  }] });
2490
1703
 
1704
+ const FORMATTING_SETTINGS_TOKEN = new InjectionToken('Summary of formatting settings for variant types of data, e.g. numbers, text, dates, etc');
1705
+
1706
+ const UI_DEFINITION_VERSION = 3;
1707
+
2491
1708
  const DEFAULT_FORMATTING_SETTINGS = {
2492
1709
  currencySymbol: DEFAULT_CURRENCY_SYMBOL,
2493
1710
  decimalsCount: DEFAULT_DECIMALS_COUNT,
@@ -2501,14 +1718,14 @@ class SdkCoreModule {
2501
1718
  SdkCoreModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SdkCoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2502
1719
  SdkCoreModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: SdkCoreModule, imports: [ConfigurationModule, FlowConfigurationModule] });
2503
1720
  SdkCoreModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SdkCoreModule, providers: [
2504
- ContextService,
2505
1721
  FlowInfoService,
2506
- QuoteDraftService,
2507
1722
  ProductImagesService,
2508
1723
  IntegrationState,
2509
1724
  FlowStateService,
2510
1725
  FlowStateConfigurationService,
2511
1726
  RuntimeSettingsService,
1727
+ SalesTransactionService,
1728
+ CatalogProductsService,
2512
1729
  {
2513
1730
  provide: FORMATTING_SETTINGS_TOKEN,
2514
1731
  useExisting: RuntimeSettingsService,
@@ -2519,14 +1736,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
2519
1736
  args: [{
2520
1737
  imports: [ConfigurationModule, FlowConfigurationModule],
2521
1738
  providers: [
2522
- ContextService,
2523
1739
  FlowInfoService,
2524
- QuoteDraftService,
2525
1740
  ProductImagesService,
2526
1741
  IntegrationState,
2527
1742
  FlowStateService,
2528
1743
  FlowStateConfigurationService,
2529
1744
  RuntimeSettingsService,
1745
+ SalesTransactionService,
1746
+ CatalogProductsService,
2530
1747
  {
2531
1748
  provide: FORMATTING_SETTINGS_TOKEN,
2532
1749
  useExisting: RuntimeSettingsService,
@@ -2582,6 +1799,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
2582
1799
  }]
2583
1800
  }] });
2584
1801
 
1802
+ function filterSuccessfulExecute() {
1803
+ return (source) => source.pipe(filter((result) => result.success), map(r => r.result));
1804
+ }
1805
+
2585
1806
  class DatePipe {
2586
1807
  constructor() {
2587
1808
  this.locale = inject(LOCALE_ID);
@@ -2701,5 +1922,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
2701
1922
  * Generated bundle index. Do not edit.
2702
1923
  */
2703
1924
 
2704
- export { ActionCodePipe, CalendarDirective, ConfigurationRuntimeService, ConfigurationService, ConfigurationStateService, ContextService, DEFAULT_FORMATTING_SETTINGS, DatePipe, FLOW_CUSTOMIZATION, FORMATTING_SETTINGS_TOKEN, FlowConfigurationModule, FlowConfigurationService, FlowInfoService, FlowStateConfigurationService, FlowStateService, FlowUpdateService, IntegrationState, LineItemWorker, NumberPipe, PricePipe, ProductImagesService, QuoteDraftService, RuntimeMode, RuntimeOperation, RuntimeSettingsService, RuntimeStep, SdkCoreModule, SdkDirectivesModule, SdkPipesModule, UI_DEFINITION_VERSION, assetPredicateFn, extractMetadata, filterOutTechnicalAttributes, findLineItem, findLineItemWithComparator, generateConfigurationLineItem, generateLineItem, getAttributeValue, getAttributes, getDefaultLineItem, getGuidedSellingConfigurationRequest, getOriginParent, getRecommendedPrices, insertLineItem, isTechnicalAttribute, lineItem_utils as lineItemUtils, mapAttributes, multiplyLineItems, patchAttributes, recalculateCardinalityVariables, removeLineItem, replaceLineItem, upsertAttributes };
1925
+ export { ActionCodePipe, CalendarDirective, CatalogProductsService, ConfigurationRuntimeService, ConfigurationService, ConfigurationStateService, DEFAULT_FORMATTING_SETTINGS, DatePipe, FLOW_CUSTOMIZATION, FORMATTING_SETTINGS_TOKEN, FlowConfigurationService, FlowInfoService, FlowStateConfigurationService, FlowStateService, GuidedSellingService, IntegrationState, NumberPipe, PricePipe, ProductImagesService, RuntimeSettingsService, SalesTransactionService, SdkCoreModule, SdkDirectivesModule, SdkPipesModule, TestModeConfigurationService, TransactionItemWorker, UI_DEFINITION_VERSION, extractMetadata, filterSuccessfulExecute, findTransactionItem, findTransactionItemWithComparator, generateTransactionItem, insertTransactionItem, removeTransactionItem, replaceTransactionItem };
2705
1926
  //# sourceMappingURL=veloceapps-sdk-core.mjs.map