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