@nuskin/ns-product-lib 2.6.1-cx24-3607.4 → 2.6.1-cx24-337701.2

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,31 +1,18 @@
1
- ## [2.6.1-cx24-3607.4](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.6.1-cx24-3607.3...v2.6.1-cx24-3607.4) (2023-03-16)
1
+ ## [2.6.1-cx24-337701.2](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.6.1-cx24-337701.1...v2.6.1-cx24-337701.2) (2023-03-19)
2
2
 
3
3
 
4
4
  ### Fix
5
5
 
6
- * The variant drop down label ([3e6b9f5](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/3e6b9f5e422b71c3e5f73d5a62f0491343ed7afb))
6
+ * The variant drop down label ([973f145](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/973f1455a91127d575a8fc7d26e7e78d05f1f0a4))
7
7
 
8
- ## [2.6.1-cx24-3607.3](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.6.1-cx24-3607.2...v2.6.1-cx24-3607.3) (2023-03-16)
8
+ ## [2.6.1-cx24-337701.1](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.6.0...v2.6.1-cx24-337701.1) (2023-03-19)
9
9
 
10
10
 
11
11
  ### Fix
12
12
 
13
- * check for imageURL ([5d56bae](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/5d56baeb4c148cc667cc3c9321fb72e87216c921))
14
-
15
- ## [2.6.1-cx24-3607.2](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.6.1-cx24-3607.1...v2.6.1-cx24-3607.2) (2023-03-16)
16
-
17
-
18
- ### Fix
19
-
20
- * (equinox-enabled) skip product mapping when an error occurs in PLP #CX24-3607 ([49fa749](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/49fa7499b390aa84cc887fc631037363421d252a)), closes [#CX24-3607](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-3607)
21
-
22
- ## [2.6.1-cx24-3607.1](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.6.0...v2.6.1-cx24-3607.1) (2023-03-15)
23
-
24
-
25
- ### Fix
26
-
27
- * (equinox-enabled) skip product mapping when an error occurs in PLP #CX24-3607 ([950c165](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/950c1650115f92badc5b898b5df722568b034afe)), closes [#CX24-3607](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-3607)
28
- * Cannot read properties of undefined (reading 'qty') in PLP #CX24-3607 ([8cde88f](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/8cde88f2f61279d20794a0e43696187c4326ca28)), closes [#CX24-3607](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-3607)
13
+ * The variant drop down label ([bd60148](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/bd60148d1a50e895d36139932740fe4ee7f9f50a))
14
+ * The variant drop down label ([749b476](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/749b47605995405886460b29f20411a21e45fb68))
15
+ * The variant drop down label ([bc555ab](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/bc555abec97bca95fc0ba18a0eb4f0a0c9cd537a))
29
16
 
30
17
  # [2.6.0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.5.2...v2.6.0) (2023-03-13)
31
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/ns-product-lib",
3
- "version": "2.6.1-cx24-3607.4",
3
+ "version": "2.6.1-cx24-337701.2",
4
4
  "description": "This project contains shared Product models and code between the backend and frontend.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1,11 +1,10 @@
1
1
  /**
2
- * @description This model represents the mapped values of a product
3
2
  * @typedef Product
4
3
  * @type {object}
5
- * @property {ProductChildSku[]} childSkus
4
+ * @property {ChildSku[]} childSkus
6
5
  * @property {Inventory} [inventoryProperties]
7
- *
8
- * @typedef ProductChildSku
6
+ *
7
+ * @typedef ChildSku
9
8
  * @type {object}
10
9
  * @property {string} productId
11
10
  * @property {string} skuId
@@ -13,52 +12,14 @@
13
12
  * @property {number} skuQuantity
14
13
  * @property {string} availableChannels
15
14
  * @property {Inventory} [inventory]
16
- *
17
- * ---
18
- *
19
- * @description This model represents a product within an Equinox response.
20
- * @typedef EquinoxProduct
21
- * @type {object}
22
- * @property {string} identifier
23
- * @property {EquinoxProductSKU[]} sku
24
- * @property {"kit"|"bundle"} [type]
25
- *
26
- * @typedef EquinoxProductSKU
27
- * @type {object}
28
- * @property {boolean} default
29
- * For multi-variant products, this indicates that this is the searched SKU
30
- * when using catalogs/search endpoint.
31
- * @property {string} identifier
32
- * @property {Inventory} inventoryProperties
33
- * @property {EquinoxProductProperties} properties
34
- *
35
- * @typedef EquinoxProductProperties
36
- * @type {object}
37
- * @property {string} availableChannels
38
- *
39
- * ---
40
- *
41
- * Types common to Product model and Equinox Product model
42
15
  *
43
16
  * @typedef Inventory
44
17
  * @type {object}
45
18
  * @property {number} atpQty
46
19
  * @property {boolean} backOrdered
47
- *
48
- * ---
49
- *
50
- * Standalone types. These are types not related to Product
51
- * and Equinox Product models.
52
- *
53
- * @typedef KitSKUQuantity
54
- * @type {object}
55
- * @property {string} sku
56
- * @property {number} qty
57
20
  */
58
21
  const availableQuantity = require('./availableQuantity');
59
- const childSKU = require('./childSKU');
60
22
 
61
23
  module.exports = {
62
- mapAvailableQuantity: availableQuantity,
63
- mapChildSKU: childSKU
24
+ mapAvailableQuantity: availableQuantity
64
25
  };
@@ -5,7 +5,7 @@ const contentstack = require('./contentstack/contentstack');
5
5
  const Product = require("./product");
6
6
  const CustomerTypes = require('./models/customerTypes');
7
7
  const ProductStatus = require("./models/productStatus");
8
- const { mapAvailableQuantity, mapChildSKU } = require('./equinox-helpers');
8
+ const { mapAvailableQuantity } = require('./equinox-helpers');
9
9
 
10
10
  const productTypes = {
11
11
  kit: 'kit'
@@ -129,9 +129,15 @@ const ProductData = {
129
129
  */
130
130
  eqProductVariantMapper: function (eqVariant) {
131
131
 
132
- let imageURL = eqVariant.properties.imageURL ? eqVariant.properties.imageURL : '';
133
- let thumbnailImage = imageURL ? imageURL + '?width=40' : ''
132
+ let imageURL = eqVariant.properties.imageURL;
133
+ const regex = /\d+\.\d+/
134
+ let thumbnailImage = ''
134
135
 
136
+ if (imageURL.includes('contentstack')) {
137
+ thumbnailImage = imageURL + '?width=40'
138
+ } else {
139
+ thumbnailImage = imageURL.replace(regex, '40.40')
140
+ }
135
141
 
136
142
  const { eventName, eventLabels, computedPrice, defaultProductPrice } = this.getEqProductPromotions(eqVariant);
137
143
  const productPrice = eventName ? defaultProductPrice : eqVariant.priceFacets["Regular Price"];
@@ -337,137 +343,151 @@ const ProductData = {
337
343
  }
338
344
  },
339
345
 
346
+ moveArray: function (arr, from, to) {
347
+ arr.splice(to, 0, arr.splice(from, 1)[0]);
348
+ return arr;
349
+ },
350
+
351
+
340
352
  eqProductMapper: async function (productDataResponse, skus) {
353
+ // console.log(productDataResponse, skus);
341
354
  let count = 0;
342
355
  let variants = {};
343
356
  const products = [];
344
357
 
345
358
  for (const productData of productDataResponse) {
346
- try {
347
- let product = (productData.type && productData.type === "kit") ? productData : productData.sku[count];
348
- let imageURL = product.properties.imageURL ? product.properties.imageURL : '';
349
- let thumbnailImage = imageURL ? imageURL + '?width=40' : ''
350
-
351
-
352
- if (productData.sku && productData.sku.length > 1) {
353
- // exclude base product from variants
354
- productData.sku.filter(v => v.identifier.substring(2, 4) !== "55").map(variant => {
355
- variants[variant.identifier] = this.eqProductVariantMapper(variant);
356
- return variant;
357
- });
359
+ let product = (productData.type && productData.type === "kit") ? productData : productData.sku[count];
360
+ let imageURL = product.properties.imageURL;
361
+ const regex = /\d+\.\d+/
362
+ let thumbnailImage = ''
363
+
364
+ if (imageURL.includes('contentstack')) {
365
+ thumbnailImage = imageURL + '?width=40'
366
+ } else {
367
+ thumbnailImage = imageURL.replace(regex, '40.40')
368
+ }
369
+
370
+ if (productData.sku && productData.sku.length > 1) {
371
+ // exclude base product from variants
372
+ productData.sku.filter(v => v.identifier.substring(2, 4) !== "55").map(variant => {
373
+ variants[variant.identifier] = this.eqProductVariantMapper(variant);
374
+ return variant;
375
+ });
376
+
377
+ //check variants for default and put it in the first element of the variants array
378
+ if (variants.length > 1) {
379
+ let defaultKey = variants.map(e => e.default).indexOf(true);
380
+ variants = this.moveArray(variants, defaultKey, 0);
358
381
  }
359
382
 
360
- const {
361
- eventName,
362
- eventLabels,
363
- computedPrice,
364
- defaultProductPrice
365
- } = this.getEqProductPromotions(product);
366
- const productPrice = eventName ? defaultProductPrice : product.priceFacets["Regular Price"];
367
- const discountedPrice = eventName ? computedPrice : product.priceFacets["Regular Price"];
368
-
369
- product.childSkus = await this.fetchChildSkus(product);
370
- product.availableQuantity = mapAvailableQuantity(product);
371
- product = {
372
- ...product,
373
- "sku": product.identifier,
374
- "globalProductID": productData.identifier,
375
- "title": productData.properties.name,
376
- "country": product.properties.market,
377
- "language": "en",
378
- "shortDescr": productData.properties.description,
379
- "longDescr": productData.properties.productDetailsDescription,
380
- "fullImage": imageURL,
381
- "imageAltText": productData.properties.name,
382
- "productCarouselImages": [
383
- {
384
- "contentType": "img",
385
- "src": "/content/products/24/00/35/24003529/jcr:content/fullImage.imgw.1280.1280.png",
386
- "alt": ""
387
- }
388
- ],
389
- "thumbnail": thumbnailImage,
390
- "ingredients": productData.properties.ingredients,
391
- "benefits": productData.properties.benefits,
392
- "usage": productData.properties.usage,
393
- "resources": product.properties.resources,
394
- "videos": "",
395
- "movie": "",
396
- "youtube": "",
397
- "salesEventText": "",
398
- "contentSection": [
399
- {
400
- "sectionContent": "<div class=\"contentSections\"></div>\n"
401
- }
402
- ],
403
- "scanQualified": productData.properties.scanQualifiedCount,
404
- "maxQuantity": 999,
405
- "points": "",
406
- "cv": (product.priceFacets.CV) ? product.priceFacets.CV : '',
407
- "pv": product.priceFacets.PV,
408
- "priceType": "WRTL",
409
- "price": discountedPrice,
410
- "priceMap": {
411
- "WRTL": productPrice,
412
- "WADW-WRTL": product.priceFacets["Regular Price"],
413
- "WADR": product.priceFacets["Regular Price"],
414
- "RTL": product.priceFacets["Regular Price"],
415
- "WADW": product.priceFacets["Wholesale Price"],
416
- "WHL": product.priceFacets["Wholesale Price"],
417
- "WWHL": product.priceFacets["Wholesale Price"]
418
- },
419
- "cvMap": {
420
- "WWHL": (product.priceFacets.CV) ? product.priceFacets.CV : '',
421
- "WADW": (product.priceFacets.CV) ? product.priceFacets.CV : '',
422
- "WHL": (product.priceFacets.CV) ? product.priceFacets.CV : ''
423
- },
424
- "pvMap": {
425
- "WWHL": product.priceFacets.PV,
426
- "WADW": product.priceFacets.PV,
427
- "WHL": product.priceFacets.PV
428
- },
429
- "orderTypes": this._setOrderType(product.properties),
430
- "custTypes": this.switchCustType(product.properties.customerTypes),
431
- "division": productData.properties.division,
432
- "backOrderDate": null,
433
- "locallyProduced": false,
434
- "agelocme": null,
435
- "count": "",
436
- "flavor": "",
437
- "size": product.properties.size,
438
- "shade": "",
439
- "status": this.switchStatusFromEquinox(product.properties.productStatus),
440
- "variantType": "Other",
441
- "variantDropdownLabel": product.properties.variantLabel || "",
442
- "variantDropdownPlaceholder": "Select Type",
443
- "variantsLabel": product.properties.variantLabel || "",
444
- "groupOffer": false,
445
- "personalOffer": false,
446
- "savedEventName": eventName,
447
- "salesLabel": eventLabels,
448
- "eventName": eventName,
449
- "sizeWeight": '',
450
- "nettoWeight": "",
451
- "variants": variants,
452
- "searchScore": 0,
453
- "isExclusive": product.properties.isExclusive || false,
454
- "marketAttributes": {
455
- "discount": true,
456
- "redeem": true,
457
- "earn": true
458
- },
459
- "restrictedMarkets": [],
460
- "addOns": [],
461
- "inventory": product.inventory || "", //inventory label
462
- "equinoxProductId": productData.identifier
463
- };
464
-
465
- products.push(new Product(product));
466
- } catch (err) {
467
- console.error('Unable to map the product', productData.identifier, ':', err);
468
- console.error('Product info:', productDataResponse, skus);
469
- continue;
470
383
  }
384
+
385
+ const {
386
+ eventName,
387
+ eventLabels,
388
+ computedPrice,
389
+ defaultProductPrice
390
+ } = this.getEqProductPromotions(product);
391
+ const productPrice = eventName ? defaultProductPrice : product.priceFacets["Regular Price"];
392
+ const discountedPrice = eventName ? computedPrice : product.priceFacets["Regular Price"];
393
+
394
+ product.childSkus = await this.fetchChildSkus(product);
395
+ product.availableQuantity = mapAvailableQuantity(product);
396
+ product = {
397
+ ...product,
398
+ "sku": product.identifier,
399
+ "globalProductID": productData.identifier,
400
+ "title": productData.properties.name,
401
+ "country": product.properties.market,
402
+ "language": "en",
403
+ "shortDescr": productData.properties.description,
404
+ "longDescr": productData.properties.productDetailsDescription,
405
+ "fullImage": imageURL,
406
+ "imageAltText": productData.properties.name,
407
+ "productCarouselImages": [
408
+ {
409
+ "contentType": "img",
410
+ "src": "/content/products/24/00/35/24003529/jcr:content/fullImage.imgw.1280.1280.png",
411
+ "alt": ""
412
+ }
413
+ ],
414
+ "thumbnail": thumbnailImage,
415
+ "ingredients": productData.properties.ingredients,
416
+ "benefits": productData.properties.benefits,
417
+ "usage": productData.properties.usage,
418
+ "resources": product.properties.resources,
419
+ "videos": "",
420
+ "movie": "",
421
+ "youtube": "",
422
+ "salesEventText": "",
423
+ "contentSection": [
424
+ {
425
+ "sectionContent": "<div class=\"contentSections\"></div>\n"
426
+ }
427
+ ],
428
+ "scanQualified": productData.properties.scanQualifiedCount,
429
+ "maxQuantity": 999,
430
+ "points": "",
431
+ "cv": (product.priceFacets.CV) ? product.priceFacets.CV : '',
432
+ "pv": product.priceFacets.PV,
433
+ "priceType": "WRTL",
434
+ "price": discountedPrice,
435
+ "priceMap": {
436
+ "WRTL": productPrice,
437
+ "WADW-WRTL": product.priceFacets["Regular Price"],
438
+ "WADR": product.priceFacets["Regular Price"],
439
+ "RTL": product.priceFacets["Regular Price"],
440
+ "WADW": product.priceFacets["Wholesale Price"],
441
+ "WHL": product.priceFacets["Wholesale Price"],
442
+ "WWHL": product.priceFacets["Wholesale Price"]
443
+ },
444
+ "cvMap": {
445
+ "WWHL": (product.priceFacets.CV) ? product.priceFacets.CV : '',
446
+ "WADW": (product.priceFacets.CV) ? product.priceFacets.CV : '',
447
+ "WHL": (product.priceFacets.CV) ? product.priceFacets.CV : ''
448
+ },
449
+ "pvMap": {
450
+ "WWHL": product.priceFacets.PV,
451
+ "WADW": product.priceFacets.PV,
452
+ "WHL": product.priceFacets.PV
453
+ },
454
+ "orderTypes": this._setOrderType(product.properties),
455
+ "custTypes": this.switchCustType(product.properties.customerTypes),
456
+ "division": productData.properties.division,
457
+ "backOrderDate": null,
458
+ "locallyProduced": false,
459
+ "agelocme": null,
460
+ "count": "",
461
+ "flavor": "",
462
+ "size": product.properties.size,
463
+ "shade": "",
464
+ "status": this.switchStatusFromEquinox(product.properties.productStatus),
465
+ "variantType": "Other",
466
+ "variantDropdownLabel": product.properties.variantLabel || "",
467
+ "variantDropdownPlaceholder": "Select Type",
468
+ "variantsLabel": product.properties.variantLabel || "",
469
+ "groupOffer": false,
470
+ "personalOffer": false,
471
+ "savedEventName": eventName,
472
+ "salesLabel": eventLabels,
473
+ "eventName": eventName,
474
+ "sizeWeight": '',
475
+ "nettoWeight": "",
476
+ "variants": variants,
477
+ "searchScore": 0,
478
+ "isExclusive": product.properties.isExclusive || false,
479
+ "marketAttributes": {
480
+ "discount": true,
481
+ "redeem": true,
482
+ "earn": true
483
+ },
484
+ "restrictedMarkets": [],
485
+ "addOns": [],
486
+ "inventory": product.inventory || "", //inventory label
487
+ "equinoxProductId": productData.identifier
488
+ };
489
+
490
+ products.push(new Product(product));
471
491
  }
472
492
 
473
493
  let data = {
@@ -510,7 +530,7 @@ const ProductData = {
510
530
  type: 'SKUKIT',
511
531
  availableChannels: product.properties.availableChannels
512
532
  },
513
- ...res.data.product.map(p => mapChildSKU(kits, p))
533
+ ...res.data.product.map(p => this.buildChildSkus(kits, p))
514
534
  ];
515
535
 
516
536
  return childSkus;
@@ -519,6 +539,23 @@ const ProductData = {
519
539
  return [];
520
540
  },
521
541
 
542
+ buildChildSkus: function (kits, product) {
543
+ const sku = product.sku[0];
544
+ const kit = kits.filter(k => k.sku === sku.identifier)[0];
545
+
546
+ return {
547
+ productId: product.identifier,
548
+ skuId: sku.identifier,
549
+ type: 'MANDATORY',
550
+ skuQuantity: kit.qty,
551
+ availableChannels: sku.properties.availableChannels,
552
+ inventory: {
553
+ atpQty: sku.inventoryProperties.atpQty,
554
+ backOrdered: sku.inventoryProperties.backOrdered
555
+ }
556
+ }
557
+ },
558
+
522
559
  /**
523
560
  *
524
561
  * Map status from equinox to legacy
@@ -1,31 +0,0 @@
1
- /**
2
- * childSKU maps a product variant. Used mainly in subscription.
3
- *
4
- * @param {import('.').KitSKUQuantity[]} kits
5
- * @param {import('.').EquinoxProduct} product
6
- */
7
- function childSKU(kits, product) {
8
- const sku = product.sku.filter(sku => sku.default)[0];
9
- if (!sku) {
10
- throw Error('Unable to find the default SKU.');
11
- }
12
-
13
- const kit = kits.filter(k => k.sku === sku.identifier)[0];
14
- if (!kit) {
15
- throw Error('SKU kit does not exist in the list of available variants.');
16
- }
17
-
18
- return {
19
- productId: product.identifier,
20
- skuId: sku.identifier,
21
- type: 'MANDATORY',
22
- skuQuantity: kit.qty,
23
- availableChannels: sku.properties.availableChannels,
24
- inventory: {
25
- atpQty: sku.inventoryProperties.atpQty,
26
- backOrdered: sku.inventoryProperties.backOrdered
27
- }
28
- }
29
- }
30
-
31
- module.exports = childSKU;