@nuskin/ns-shop 7.1.0-brw-988.1 → 7.1.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/ns-shop",
3
- "version": "7.1.0-brw-988.1",
3
+ "version": "7.1.0",
4
4
  "description": "The description that will amaze and astound your audience when they read it",
5
5
  "main": "src/shop.js",
6
6
  "scripts": {
@@ -26,8 +26,10 @@
26
26
  "@nuskin/ns-common-lib": "1.4.7",
27
27
  "@nuskin/ns-feature-flags": "1.4.7",
28
28
  "@nuskin/ns-loyalty-web": "1.5.6",
29
- "@nuskin/ns-product-lib": "2.17.0",
29
+ "@nuskin/ns-product-lib": "2.19.1",
30
30
  "@nuskin/nuskinjquery": "2.3.1",
31
+ "@nuskin/order-model": "3.1.3",
32
+ "@nuskin/product-lib": "2.2.1",
31
33
  "axios": "1.6.5",
32
34
  "decimal.js": "10.4.3",
33
35
  "jp-conversion": "0.0.7",
@@ -40,8 +42,8 @@
40
42
  "@nuskin/exclusive-offer-sdk": "1.2.4",
41
43
  "@nuskin/ns-account": "5.9.2",
42
44
  "@nuskin/ns-jsanalyzer": "1.0.1",
43
- "@nuskin/ns-product": "3.50.0",
44
- "@nuskin/ns-util": "4.5.4",
45
+ "@nuskin/ns-product": "3.50.5",
46
+ "@nuskin/ns-util": "4.6.1",
45
47
  "axios-mock-adapter": "1.22.0",
46
48
  "babel-cli": "6.26.0",
47
49
  "babel-core": "6.26.3",
package/src/cart/cart.js CHANGED
@@ -832,9 +832,12 @@ export default function Cart(cartData) {
832
832
  };
833
833
 
834
834
  this.updateProductEventPrice = function(item, activeEvents) {
835
+ let eventNameAdded = false;
835
836
  const user = UserService.getUser();
836
837
  const priceType = ShopContext.getPriceType(item.isAdr(), user);
838
+ const eventName = item.product.eventName;
837
839
  if (item.product.setPriceAndPvFromType(priceType, activeEvents)) {
840
+ if (!eventName && item.product.eventName) eventNameAdded = true;
838
841
  SalesEventService.logAnalyticInfo(
839
842
  'product-price-to-event-price',
840
843
  item.product.eventName,
@@ -848,15 +851,20 @@ export default function Cart(cartData) {
848
851
  }
849
852
  });
850
853
  }
854
+ return eventNameAdded;
851
855
  };
852
856
 
853
857
  this.updateEventPrices = function(activeEvents) {
858
+ let eventNameAdded = false;
854
859
  getCartItems({cartItems: true}).forEach(item => {
855
- this.updateProductEventPrice(item, activeEvents);
860
+ if (this.updateProductEventPrice(item, activeEvents))
861
+ eventNameAdded = true;
856
862
  });
863
+ return eventNameAdded;
857
864
  };
858
865
 
859
866
  this.setMissingEventNames = async (order) => {
867
+ let cartUpdated = false;
860
868
  const orderItems = this.getItems({cartOrderItems: true});
861
869
  let nameSet = new Set();
862
870
  let itemsChecked = [];
@@ -875,6 +883,7 @@ export default function Cart(cartData) {
875
883
  if (itemEvents.includes(ien)) {
876
884
  // set this items eventName if another item already has it set.
877
885
  item.product.eventName = ien;
886
+ cartUpdated = true;
878
887
  }
879
888
  return !!item.product.eventName; // causes loop to stop if true
880
889
  });
@@ -896,6 +905,7 @@ export default function Cart(cartData) {
896
905
  itemEvents.some((ie) => {
897
906
  if (eventStatuses[ie]) {
898
907
  // set the status if event is active.
908
+ cartUpdated = true;
899
909
  item.product.eventName == ie;
900
910
  SalesEventService.logAnalyticInfo(
901
911
  'cart-eventname-fixed', ie,
@@ -906,6 +916,7 @@ export default function Cart(cartData) {
906
916
  })
907
917
  });
908
918
  }
919
+ return cartUpdated;
909
920
  }
910
921
 
911
922
  this.getCartInfo = function(options) {
@@ -34,6 +34,7 @@ export default {
34
34
  hasItems,
35
35
  hasEventItems,
36
36
  hasPreviewItems,
37
+ hasDangerousGoods,
37
38
  getItemCnt,
38
39
  addProductToCart,
39
40
  addSkuToCart,
@@ -229,10 +230,23 @@ function updateItemPrices() {
229
230
  }
230
231
 
231
232
  async function checkForMissingEventNames(order) {
233
+ let outOfSync = false;
232
234
  await awaitForConfig();
233
235
  const cart = _getCart();
234
- await cart.setMissingEventNames(order);
236
+
237
+ // check to see if cart item has eventName but sapItem does not.
238
+ const orderItems = cart.getItems({cartOrderItems: true});
239
+ orderItems.map((item) => {
240
+ const sapItem = order.sapItems.find((sapItem) => (
241
+ sapItem.sku === item.product.sku && sapItem.isAdr === item.adr
242
+ ));
243
+ if (sapItem && item.product.eventName && !sapItem.eventName)
244
+ outOfSync = true;
245
+ });
246
+
247
+ let updated = await cart.setMissingEventNames(order);
235
248
  setCart(cart);
249
+ return updated || outOfSync;
236
250
  }
237
251
 
238
252
  function getCartProperty(key) {
@@ -285,6 +299,14 @@ function hasPreviewItems() {
285
299
  return _getCart().hasPreviewItems();
286
300
  }
287
301
 
302
+ function hasDangerousGoods(options = {cartOrderItems: true}) {
303
+ let retVal = false;
304
+ _getCart().getItems(options).forEach((item) => {
305
+ retVal = retVal || item.product.dangerousGoods;
306
+ });
307
+ return retVal;
308
+ }
309
+
288
310
  function getItemCnt(options) {
289
311
  return _getCart().getItemCnt(options);
290
312
  }
@@ -354,10 +376,11 @@ async function addProductToCart(options) {
354
376
  }
355
377
 
356
378
  options.product.isBackOrdered = (options.product.inventory === "BACKORDER") ? true : false
357
-
379
+
358
380
  const language = options.product.lang || options.product.language;
359
381
  options.product.lang = language;
360
382
  options.product.language = language;
383
+ const eventName = options.product.eventName;
361
384
 
362
385
  let itemKey = cart.addProduct({
363
386
  id: options.id,
@@ -377,6 +400,8 @@ async function addProductToCart(options) {
377
400
  });
378
401
 
379
402
  const item = itemKey ? cart.getItemByKey(itemKey) : null;
403
+ // eventName would get nulled out if sapItem
404
+ item.product.eventName = eventName;
380
405
  setCart(cart, item ? !item.isSapLineItem() : true);
381
406
  return itemKey;
382
407
  }
@@ -489,7 +514,10 @@ async function getAddToCartQty(product) {
489
514
  retVal = product.maxQuantity - cartQty;
490
515
  if (product.isExclusive) {
491
516
  try {
492
- const qual = await QualificationService.getQualification(product.sku)
517
+ const qual = await QualificationService.getQualification(product.sku);
518
+ if (!qual) {
519
+ return 0;
520
+ }
493
521
  const productIdentifier = qual.productId || qual.sku;
494
522
  cartQty = await getBaseSkuCartQuantity(productIdentifier)
495
523
  retVal = product.maxQuantity - cartQty;
@@ -1407,8 +1435,10 @@ const cartServiceConfigCallback = async (configs) => {
1407
1435
  if (_activeEvents != undefined) {
1408
1436
  activeEvents = _activeEvents;
1409
1437
  const cart = _getCart();
1410
- cart.updateEventPrices(activeEvents)
1411
- setCart(cart);
1438
+ if (cart.updateEventPrices(activeEvents)) {
1439
+ events.setValue(events.shop.CART_EVENT_PRICE_UPDATED, [activeEvents]);
1440
+ setCart(cart);
1441
+ }
1412
1442
  }
1413
1443
  }, true);
1414
1444
  events.publish(events.salesevent.POLL_MARKET_CONFIG);
@@ -0,0 +1,274 @@
1
+ import {productLib} from '@nuskin/product-lib';
2
+ import {RunConfigService, events, UrlService, BrowserDetection} from '@nuskin/ns-util';
3
+ import { getConfiguration } from '@nuskin/configuration-sdk';
4
+ import {AccountManager} from '@nuskin/ns-account';
5
+ import {PriceType, Product} from '@nuskin/ns-product-lib';
6
+
7
+ const extractProductData = (data, sku) => {
8
+ let retVal;
9
+
10
+ if (Array.isArray(data.variants) && data.variants.length > 0) {
11
+ retVal = data.variants.find((variant) => variant.sku === sku) || data.variants[0];
12
+ retVal.variantSelectLabel = data.variantSelectLabel;
13
+ } else if (data.bundle) {
14
+ retVal = data.bundle;
15
+ retVal.title = data.title;
16
+ retVal.productImages = data.productImages;
17
+ }
18
+
19
+ return retVal;
20
+ }
21
+
22
+ const addPrice = (productData, priceTypeKey, subKey, priceValue) => {
23
+ if (!['Points', 'cv', 'price', 'pv'].includes(priceTypeKey)) {
24
+ // if the priceTypeKey is not one of these, then we don't want it to show.
25
+ return;
26
+ }
27
+ if (priceTypeKey === 'pv') {
28
+ priceTypeKey = 'psv';
29
+ }
30
+ if (priceTypeKey === 'cv') {
31
+ priceTypeKey = 'csv';
32
+ }
33
+
34
+ if (productData[priceTypeKey] === undefined) {
35
+ if (priceTypeKey === 'Points') {
36
+ if (!productData.price) {
37
+ productData.price = {};
38
+ }
39
+ productData.price.PTS = priceValue;
40
+ return;
41
+ } else {
42
+ productData[priceTypeKey] = {};
43
+ }
44
+ }
45
+ productData[priceTypeKey][subKey] = priceValue;
46
+ }
47
+
48
+ const convertPricing = (pricing, productData) => {
49
+ if (pricing) {
50
+ Object.keys(pricing).forEach((channelKey) => {
51
+ Object.keys(pricing[channelKey]).forEach((contextKey) => {
52
+ Object.keys(pricing[channelKey][contextKey]).forEach((priceTypeKey) => {
53
+ const priceValue = pricing[channelKey][contextKey][priceTypeKey];
54
+ switch (channelKey) {
55
+ case 'wholesale':
56
+ switch (contextKey) {
57
+ case 'webOrder':
58
+ addPrice(productData, priceTypeKey, 'WWHL', priceValue);
59
+ break;
60
+ case 'webAdr':
61
+ case 'WADW':
62
+ case 'ADR5':
63
+ addPrice(productData, priceTypeKey, 'WADW', priceValue);
64
+ break;
65
+ case 'order':
66
+ case 'WHL':
67
+ addPrice(productData, priceTypeKey, 'WHL', priceValue);
68
+ break;
69
+ case 'adr':
70
+ addPrice(productData, priceTypeKey, 'ADW', priceValue);
71
+ break;
72
+ case 'ADR10':
73
+ case 'WADWD':
74
+ addPrice(productData, priceTypeKey, 'WADWD', priceValue);
75
+ break;
76
+ default:
77
+ addPrice(
78
+ productData,
79
+ priceTypeKey,
80
+ `${contextKey}-WWHL`,
81
+ priceValue
82
+ );
83
+ break;
84
+ }
85
+ break;
86
+ case 'retail':
87
+ switch (contextKey) {
88
+ case 'webOrder':
89
+ addPrice(productData, priceTypeKey, 'WRTL', priceValue);
90
+ break;
91
+ case 'webAdr':
92
+ addPrice(productData, priceTypeKey, 'WADR', priceValue);
93
+ break;
94
+ case 'order':
95
+ case 'RTL':
96
+ addPrice(productData, priceTypeKey, 'RTL', priceValue);
97
+ break;
98
+ case 'adr':
99
+ addPrice(productData, priceTypeKey, 'ADR', priceValue);
100
+ break;
101
+ default:
102
+ addPrice(
103
+ productData,
104
+ priceTypeKey,
105
+ `${contextKey}-WRTL`,
106
+ priceValue
107
+ );
108
+ break;
109
+ }
110
+ break;
111
+ }
112
+ });
113
+ });
114
+ });
115
+ }
116
+ }
117
+
118
+ const createDataFromSkuSearch = (searchData, options) => {
119
+ if (!searchData) {
120
+ return new Product();
121
+ }
122
+ let product = new Product();
123
+
124
+ if (searchData) {
125
+ product.sku = options.sku;
126
+ product.country = options.country;
127
+ product.lang = options.language;
128
+ product.isExclusive = searchData.isExclusive;
129
+ if (Array.isArray(searchData.productImages) && searchData.productImages.length > 0) {
130
+ product.setFullImage(searchData.productImages[0].url);
131
+ product.setThumbnail(searchData.productImages[0].thumbnail);
132
+ product.setImageAltText(searchData.productImages[0].altText);
133
+ // product.setProductCarouselImages(???searchData.contents.imageCarousel);
134
+ }
135
+ // product.productLabels = ???
136
+ product.title = searchData.title;
137
+ product.shortDescr = searchData.description;
138
+ // product.longDescr = langObj['longDescription']; looks like it is deprecated
139
+ product.dangerousGoods = searchData.dangerousGoods === true;
140
+ product.ingredients = searchData.ingredients;
141
+ product.benefits = searchData.benefits;
142
+ product.usage = searchData.usage;
143
+ product.resources = searchData.resources;
144
+ // product.videos = searchData.???;
145
+ // product.contentSection =searchData.???;
146
+ // product.sizeWeight = ???;
147
+ product.size = searchData.size;
148
+ product.nettoWeight = searchData.nettoWeight;
149
+ product.salesLabel = searchData.salesLabel;
150
+ // product.movie = searchData.???;
151
+ // product.youtube = searchData.???;
152
+ product.salesEventText = searchData.salesText;
153
+ product.scanQualified = searchData.scanQualifiedCount;
154
+ // product.division = searchData.???
155
+ product.custTypes = Array.isArray(searchData.customerTypes) && searchData.customerTypes.map((ct) => {
156
+ if (ct === 'Preferred') return '30';
157
+ else if (ct === 'Retail') return '20';
158
+ else if (ct === '') return '10';
159
+ });
160
+ product.restrictedMarkets = searchData.restrictedMarkets;
161
+ // if (addOns) {
162
+ // product.addOns = addOns;
163
+ // } else {
164
+ // product.addOns = [];
165
+ // }
166
+ if (options.isGroupOffer) product.isGroupOffer = options.isGroupOffer;
167
+ if (options.isPersonalOffer) product.isPersonalOffer = options.isPersonalOffer;
168
+
169
+ product.variantsLabel = searchData.variantLabel;
170
+ product.variantDropdownLabel = searchData.variantSelectLabel;
171
+ product.shade = searchData.variantColor;
172
+
173
+ const pricing = JSON.parse(searchData.pricingJson);
174
+ const orderTypes = [];
175
+ if (searchData.purchaseTypes.buyOnce) orderTypes.push('order');
176
+ if (searchData.purchaseTypes.subscription) orderTypes.push('adr');
177
+ let status = {
178
+ sku: options.sku,
179
+ globalProductId: searchData.globalId,
180
+ status: searchData.status.status === 'sellable' ? 'RELEASED_FOR_SALE' : 'NOT_RELEASED_FOR_SALE',
181
+ availableQuantity: searchData.availableQuantity,
182
+ maxQuantity: searchData.maxQuantity,
183
+ locallyProduced: searchData.locallyProduced, // ???
184
+ backorderedAvailableDate: searchData.status.isBackordered > 0 ? searchData.status.backorderedAvailableDate : null,
185
+ orderType: orderTypes, // searchData.channels.map((channel) => channel.toLowerCase()),
186
+ childSkus: null // ???
187
+ };
188
+ convertPricing(pricing, status);
189
+ product.addPricingFromStatus(status);
190
+ }
191
+
192
+ // Note: this mapping was originally created for the product data in AEM. This product
193
+ // data comes from content stack and is not identical to what is in AEM. There may
194
+ // need to be some tweaks in here. ESPECIALLY when the data gets moved to the
195
+ // bundle field (vs variants) in the product data.
196
+
197
+ return product;
198
+ }
199
+
200
+ const handleDetailResponse = async (responseData, options) => {
201
+ let retVal = {success: true},
202
+ dataForProduct = createDataFromSkuSearch(responseData, options);
203
+
204
+ if (dataForProduct.sku) {
205
+ retVal.product = new Product(dataForProduct);
206
+
207
+ const siteUrl = UrlService.getSiteUrl();
208
+ const isEdge = BrowserDetection.isEdge();
209
+ const isFirefox = BrowserDetection.isFirefox();
210
+
211
+ // set the base url for images, etc
212
+ retVal.product.setBaseUrl(siteUrl);
213
+
214
+ // fix image paths for non-edge/firefox
215
+ if (!isEdge && !isFirefox) {
216
+ retVal.product.fullImage = retVal.product.fullImage
217
+ ? `${retVal.product.fullImage.split("?")[0]}?format=pjpg`
218
+ : undefined;
219
+ retVal.product.thumbnail = retVal.product.thumbnail
220
+ ? `${retVal.product.thumbnail.split("?")[0]}?format=pjpg`
221
+ : undefined;
222
+ }
223
+ } else {
224
+ retVal.success = false;
225
+ retVal.failedSku = options.sku;
226
+ }
227
+
228
+ if (retVal.product && options.priceType) {
229
+ const {Cart: cartCfg} = await getConfiguration(['Cart']);
230
+ const priceType = cartCfg.showWholeSalePricing && !AccountManager.isLoggedIn()
231
+ ? PriceType.WWHL
232
+ : options.priceType;
233
+ retVal.product.setPriceAndPvFromType(priceType);
234
+ }
235
+
236
+ return retVal;
237
+ }
238
+
239
+ const getProductDetail = async (options) => {
240
+ let response;
241
+
242
+ // Hit the PMD and get all the data for the product including the price information.
243
+ try {
244
+ response = await productLib.getProduct({
245
+ fromId: options.sku,
246
+ env: RunConfigService.getEnvironmentCode(),
247
+ market: options.country,
248
+ language: options.language
249
+ })
250
+ } catch (e) {
251
+ throw {error: e, failedSku: options.sku, type: events.errors.PRODUCT_LOOKUP};
252
+ }
253
+
254
+ return extractProductData(response.data, options.sku);
255
+ }
256
+
257
+ const getProductBySku = async (options) => {
258
+ const data = await getProductDetail(options);
259
+
260
+ let result = await handleDetailResponse(data, options);
261
+
262
+ return result;
263
+ }
264
+
265
+ const getProductData = async (options) => {
266
+ const data = await getProductDetail(options);
267
+
268
+ return createDataFromSkuSearch(data, options);
269
+ }
270
+
271
+ export {
272
+ getProductBySku,
273
+ getProductData
274
+ }
@@ -20,7 +20,8 @@ const shoppingContextCartTypes = {
20
20
 
21
21
  const DEFAULT_CART_TYPE = 'USER';
22
22
 
23
- let cartContents = null;
23
+ let requestStatus = 'idle';
24
+ let cartPromise = null;
24
25
 
25
26
  export default {
26
27
  addProductToEquinoxCart,
@@ -46,8 +47,15 @@ function _getEquinoxSession() {
46
47
  method: 'GET',
47
48
  endpoint: 'customers'
48
49
  }
50
+ const customerSession = sessionStorage.getItem('customerSession') ? JSON.parse(sessionStorage.getItem('customerSession')) : ''
51
+ if (customerSession === '') {
52
+ sessionStorage.setItem('customerSession', true)
53
+ return _equinoxRequest(equinoxRequestOptions)
54
+ } else {
55
+ return null
56
+ }
57
+
49
58
 
50
- return _equinoxRequest(equinoxRequestOptions);
51
59
  }
52
60
 
53
61
  /**
@@ -216,22 +224,25 @@ function _getCartShoppingContext() {
216
224
  async function getEquinoxCart() {
217
225
 
218
226
  const cartType = _getCartShoppingContext();
219
-
227
+
220
228
  const equinoxRequestOptions = {
221
229
  method: 'GET',
222
230
  endpoint: `carts/${cartType}`
223
231
  }
224
- if (!cartContents){
225
- cartContents = _equinoxRequest(equinoxRequestOptions).then(result => {
226
- cartContents = result;
227
- });
232
+ if(requestStatus === 'pending'){
233
+ return await resolveCartPromise();
228
234
  }
235
+ if (requestStatus === 'idle'){
236
+ requestStatus = 'pending';
237
+ cartPromise = _equinoxRequest(equinoxRequestOptions);
238
+ return await resolveCartPromise();
239
+ }
240
+ }
229
241
 
230
- await cartContents
231
-
232
- // if this is a promise, this will resolve it
233
- // otherwise, it won't do anything
234
- return cartContents;
242
+ async function resolveCartPromise () {
243
+ const response = await cartPromise;
244
+ requestStatus = 'idle';
245
+ return response;
235
246
  }
236
247
 
237
248
  /**
@@ -262,7 +273,6 @@ async function getAddToCartQty(product) {
262
273
  const qualification = await QualificationService.getQualification(product.sku)
263
274
  qualifiedQuantity = qualification.isConsumable ? qualification.quantity : 0
264
275
  } catch (err) {
265
- console.error(err)
266
276
  qualifiedQuantity = 0;
267
277
  }
268
278
  }
@@ -394,6 +404,7 @@ function _assembleChildSkus(requestData, options) {
394
404
  if(personalOffer != null && productWithVariant.length > 0 && productWithVariant[0].variantSelected){
395
405
  selectedVariants = productWithVariant[0].variantSelected;
396
406
  }
407
+ if (personalOffer != null && selectedVariants && cs.skuId != selectedVariants[cs.productId] && (cs.type !== "BUNDLE" && cs.type !== "OPTIONAL")) return null
397
408
  const childSku =
398
409
  (personalOffer != null && selectedVariants && selectedVariants[cs.productId] && config.MySite_graphql_active)
399
410
  ? {
@@ -414,6 +425,7 @@ function _assembleChildSkus(requestData, options) {
414
425
 
415
426
  return childSku;
416
427
  });
428
+ requestData.skus = requestData.skus.filter(n => n)
417
429
  }
418
430
 
419
431
  return requestData;
@@ -459,7 +471,6 @@ const runConfigCallback = async (runConfig) => {
459
471
  const publishEquinoxCartCount = (options) => {
460
472
  getEquinoxCart().then((response) => {
461
473
  const cart = response.data;
462
- cartContents = null;
463
474
  events.publish(events.shop.CART_UPDATED, { cartInfo: { qty: cart.value.count }, ...options });
464
475
  });
465
476
  }
@@ -1,10 +1,10 @@
1
- import $ from '@nuskin/nuskinjquery';
2
1
  import {PriceType, Product} from '@nuskin/ns-product-lib';
3
- import {RunConfigService, util, events, BrowserDetection, UrlService} from '@nuskin/ns-util';
2
+ import {RunConfigService, events, util, BrowserDetection, UrlService} from '@nuskin/ns-util';
4
3
  import {UserService, AccountManager} from '@nuskin/ns-account';
5
4
  import ProductStatusService from '../product/ProductStatusService.js';
6
5
  import _ from 'lodash';
7
6
  import { getConfiguration } from '@nuskin/configuration-sdk';
7
+ import { getProductBySku as getCsProductBySku, getProductData as getCsProductData } from './csProductHelper.js';
8
8
  import axios from 'axios';
9
9
 
10
10
  let ProductService = function() {
@@ -21,24 +21,13 @@ let ProductService = function() {
21
21
  * @returns {null}
22
22
  */
23
23
  getProductBySku: async function(_options) {
24
- let options = verifyLocaleFields(_options),
25
- promises = [getProductDetail(options)];
26
-
27
- promises.push(getProductStatus(options));
28
-
29
- let values = await Promise.all(promises);
30
-
31
- let result = await handleDetailResponse(values[0], options);
32
-
33
- if (values[1] && values[1][0]) {
34
- handleStatusResponse(result.product, values[1][0], options);
24
+ const options = verifyLocaleFields(_options)
25
+ const {Cart: cartCfg} = await getConfiguration(['Cart']);
26
+ if (cartCfg.useContentStackProductData) {
27
+ return await getCsProductBySku(options)
35
28
  } else {
36
- // Fallback for product quantity on a failed product status call.
37
- // This is done to prevent the product detail component from locking up unnecessarily.
38
- result.product.availableQuantity = 10000;
29
+ return await legacyGetProductBySku(options);
39
30
  }
40
-
41
- return result;
42
31
  },
43
32
 
44
33
  /**
@@ -47,35 +36,34 @@ let ProductService = function() {
47
36
  * @param {string} sku - ex. 01111155
48
37
  * @returns {Promise}
49
38
  */
50
- getProductData: function(sku, country, language) {
51
- if(!sku) return;
52
- let optionsData = country ? {country} : {};
53
- if(language)
54
- optionsData.language = language;
55
-
56
- let tokenizedSku = tokenizeSku(sku),
57
- url,
58
- options = verifyLocaleFields(optionsData);
59
-
60
- url = UrlService.getSiteUrl() + "/content/products/" + tokenizedSku + "/" +
61
- options.language + ".service." + options.country + ".json";
62
-
63
- return new Promise((resolve, reject) => {
64
- $.ajax({
65
- type: 'GET',
66
- url: url,
67
- success: function(response) {
68
- resolve(createDataFromSkuSearch(response, options));
69
- },
70
- error: function(response) {
71
- console.error("There was a problem retrieving product data:", response);
72
- reject(response);
39
+ getProductData: async function(sku, country, language) {
40
+ let retVal;
41
+
42
+ if (sku) {
43
+ const optionsData = {
44
+ country: country ? country : undefined,
45
+ language: language ? language : undefined,
46
+ sku
47
+ };
48
+ const options = verifyLocaleFields(optionsData);
49
+ const {Cart: cartCfg} = await getConfiguration(['Cart']);
50
+
51
+ try {
52
+
53
+ if (cartCfg.useContentStackProductData) {
54
+ retVal = await getCsProductData(options);
55
+ } else {
56
+ const tokenizedSku = tokenizeSku(sku);
57
+ const url = UrlService.getSiteUrl() + "/content/products/" + tokenizedSku + "/" +
58
+ options.language + ".service." + options.country + ".json";
59
+ const response = await axios.get(url);
60
+ retVal = createDataFromSkuSearch(response, options);
73
61
  }
74
- });
75
- });
76
-
77
-
78
-
62
+ } catch (err) {
63
+ console.error("There was a problem retrieving product data", err);
64
+ }
65
+ }
66
+ return retVal;
79
67
  }
80
68
  };
81
69
 
@@ -84,6 +72,26 @@ let ProductService = function() {
84
72
  // Private Methods
85
73
  //
86
74
  // ---------------------------------------------
75
+ async function legacyGetProductBySku(options) {
76
+ const promises = [getProductDetail(options)];
77
+
78
+ promises.push(getProductStatus(options));
79
+
80
+ let values = await Promise.all(promises);
81
+
82
+ let result = await handleDetailResponse(values[0], options);
83
+
84
+ if (values[1] && values[1][0]) {
85
+ handleStatusResponse(result.product, values[1][0], options);
86
+ } else {
87
+ // Fallback for product quantity on a failed product status call.
88
+ // This is done to prevent the product detail component from locking up unnecessarily.
89
+ result.product.availableQuantity = 10000;
90
+ }
91
+
92
+ return result;
93
+ }
94
+
87
95
  async function getProductDetail(_options) {
88
96
  let options = _options;
89
97
  let url = await getSkuSearchUrl(options);