@nuskin/ns-product-lib 2.4.0-cx24-2462.1.1 → 2.4.1-cx12-5910.1

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,21 @@
1
- # [2.4.0-cx24-2462.1.1](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.3.0...v2.4.0-cx24-2462.1.1) (2022-10-20)
1
+ ## [2.4.1-cx12-5910.1](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.4.0...v2.4.1-cx12-5910.1) (2022-10-26)
2
+
3
+
4
+ ### Fix
5
+
6
+ * try catch block for generating env (#CX12-5910) ([86930c3](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/86930c31a70bfe35a5136bc338ec618e04d860eb)), closes [#CX12-5910](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX12-5910)
7
+
8
+ # [2.4.0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.3.0...v2.4.0) (2022-10-26)
2
9
 
3
10
 
4
11
  ### Fix
5
12
 
6
13
  * To make multiple products work (#CX24-2444) ([ce4c483](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/ce4c483b7fbb0527e60045d8174fd503a67e63fa)), closes [#CX24-2444](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-2444)
7
14
 
15
+ ### New
16
+
17
+ * added support for inventory label (#CX24-2186) ([3e27481](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/3e2748106cd6098086dbd6b738964deabacc875d)), closes [#CX24-2186](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-2186)
18
+
8
19
  ### Release
9
20
 
10
21
  * Automated changes by GitLab pipeline [skip ci] ([8f75316](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/8f75316b692ddccda5b7bea830ee6dc625b942c7))
@@ -12,7 +23,8 @@
12
23
 
13
24
  ### Update
14
25
 
15
- * map product images to carousel images (CX24-2462) ([1e17c6e](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/1e17c6ec39e54b4bdb2bb804c997eb14c9e501d5))
26
+ * added support for variant and price (#CX24-2186) ([e0bf8f2](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/e0bf8f280a838dfa4cc613e5bc34d254dbdc8e1a)), closes [#CX24-2186](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-2186)
27
+ * added variant label (#CX24-2186) ([4c223b3](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/4c223b34438ed73cb824716cacb93482486f8195)), closes [#CX24-2186](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-2186)
16
28
 
17
29
  # [2.3.0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.2.0...v2.3.0) (2022-10-14)
18
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/ns-product-lib",
3
- "version": "2.4.0-cx24-2462.1.1",
3
+ "version": "2.4.1-cx12-5910.1",
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": {
@@ -3,8 +3,19 @@ const axios = require('axios');
3
3
  const { getEnvironmentFromUrl } = require('@nuskin/ns-common-lib');
4
4
  const config = require('./environment');
5
5
 
6
+ let env = 'unknown';
7
+
8
+ // ns-product-lib should be multi-platform compatible i.e. lambda, web, or react native etc.
9
+ try {
10
+ env = getEnvironmentFromUrl(window.location.host);
11
+ } catch (error) {
12
+ console.log("getting env from url not supported. window is likely unavailable:");
13
+ console.log("Name: ", error.name);
14
+ console.log("Message: ", error.message);
15
+ console.log("Stack Trace: ", error.stack);
16
+ }
17
+
6
18
  // contentstack HTTP service
7
- const env = getEnvironmentFromUrl(window.location.host);
8
19
  const envConfig = config.getCredentials(env);
9
20
  const baseURL = `${envConfig.url}/stacks/${envConfig.apiKey}?environment=${envConfig.env}`;
10
21
  const headers = {
package/src/product.js CHANGED
@@ -72,6 +72,10 @@ const Product = function(productData) {
72
72
  // agelocme stuff
73
73
  this.agelocme = null; // object containing agelocme information (like code, label, name)
74
74
 
75
+ //equinox inventory / stock label
76
+ //@example "IN STOCK"
77
+ this.inventory = "";
78
+
75
79
  this.setMarketAttributes = function(productStatus) {
76
80
  if (productStatus.marketAttributes) {
77
81
  this.marketAttributes = productStatus.marketAttributes;
@@ -518,6 +522,7 @@ const Product = function(productData) {
518
522
  retData.marketAttributes = this.marketAttributes;
519
523
  retData.restrictedMarkets = this.restrictedMarkets;
520
524
  retData.addOns = this.addOns;
525
+ retData.inventory = this.inventory;
521
526
 
522
527
  return retData;
523
528
  };
@@ -626,6 +631,7 @@ const Product = function(productData) {
626
631
  this.marketAttributes = productData.marketAttributes;
627
632
  this.addOns = productData.addOns || [];
628
633
  this.restrictedMarkets = productData.restrictedMarkets || [];
634
+ this.inventory = productData.inventory || "";
629
635
 
630
636
  if (data.priceType) {
631
637
  this.addPricing(data.priceType, data.price);
@@ -1,15 +1,15 @@
1
1
  "use strict";
2
2
  const axios = require("axios");
3
3
  const contentstack = require('./contentstack/contentstack');
4
- const product = require("./product");
4
+ const Product = require("./product");
5
5
 
6
6
  /** @type {*} */
7
7
  const ProductData = {
8
8
  /**
9
- * @param {string[]} skus
10
- * @param {string} locale
11
- * @param {string} market
12
- * @param {boolean} isEquinoxEnabled
9
+ * @param {string[]} skus
10
+ * @param {string} locale
11
+ * @param {string} market
12
+ * @param {boolean} isEquinoxEnabled
13
13
  */
14
14
  getProductData: async function (skus, locale, market, isEquinoxEnabled = false) {
15
15
  const localeMarket = `${locale}_${market}`;
@@ -28,7 +28,7 @@ const ProductData = {
28
28
  getProductFromEquinox: async function (skus, locale, storeID) {
29
29
  const filter = '{"filters":[{"field":"index_key_skuId","operation":"IN","value":"' + skus.toString() + '"}]}';
30
30
  axios.defaults.withCredentials = true;
31
-
31
+
32
32
  const url = await contentstack.getKongUrl() + `/orchestrationservices/storefront/catalogs/search/`;
33
33
  console.log("Dynamic URL", url)
34
34
  const href = `${url}?filter=${encodeURI(filter)}`;
@@ -78,7 +78,7 @@ const ProductData = {
78
78
  responseType: 'json'
79
79
  });
80
80
  },
81
-
81
+
82
82
  /**
83
83
  * @param {contentstack.MarketConfig} marketConfig
84
84
  */
@@ -90,21 +90,149 @@ const ProductData = {
90
90
  };
91
91
  },
92
92
 
93
+ /**
94
+ * Map product variant
95
+ * @todo remove unnecessary fields
96
+ * @param {*} eqVariant
97
+ * @returns Array<Product>
98
+ */
99
+ eqProductVariantMapper : function (eqVariant) {
100
+
101
+ let imageURL = eqVariant.properties.imageURL;
102
+ const regex = /\d+.\d+/
103
+ let thumbnailImage = ''
104
+
105
+ if (imageURL.includes('contentstack')) {
106
+ thumbnailImage = imageURL + '?width=40'
107
+ } else {
108
+ thumbnailImage = imageURL.replace(regex,'40.40')
109
+ }
110
+
111
+ return {
112
+ "sku": eqVariant.identifier,
113
+ "globalProductID": eqVariant.identifier,
114
+ "title": eqVariant.properties.name,
115
+ "country": eqVariant.properties.market,
116
+ "language": "en",
117
+ "shortDescr": eqVariant.properties.description,
118
+ "longDescr": eqVariant.properties.productDetailsDescription,
119
+ "fullImage": imageURL,
120
+ "imageAltText": eqVariant.properties.name,
121
+ "productCarouselImages": [
122
+ {
123
+ "contentType": "img",
124
+ "src": "/content/products/24/00/35/24003529/jcr:content/fullImage.imgw.1280.1280.png",
125
+ "alt": ""
126
+ }
127
+ ],
128
+ "thumbnail": thumbnailImage,
129
+ "ingredients": eqVariant.properties.ingredients,
130
+ "benefits": eqVariant.properties.benefits,
131
+ "usage": eqVariant.properties.usage,
132
+ "resources": eqVariant.properties.resources,
133
+ "videos": "",
134
+ "movie": "",
135
+ "youtube": "",
136
+ "salesEventText": "",
137
+ "contentSection": [
138
+ {
139
+ "sectionContent": "<div class=\"contentSections\"><div class=\"contentSection section\"><div>\n<h3>BENEFITS</h3>\n<div>\n<div class=\"sectionContent parsys\"><div class=\"text parbase section\">\n<p>Green tea has been used in China for thousands of years for its health-preserving and revitalizing power. Modern science has identified powerful antioxidants in green tea called polyphenols. One group of polyphenols called catechins is particularly potent and is highly effective at neutralizing free radicals at the cellular level. Catechins support healthy cell function while providing antioxidant protection to critical cell structures such as DNA. Clinical studies show catechins interfere with the production of certain enzymes involved in cell damage. Additionally, catechins have been demonstrated to cause a thermogenic effect that enhances the body s metabolic rate. Tegreen 97<sup>®</sup> from Pharmanex is a proprietary, highly concentrated extract of the catechins found in green tea. Tegreen 97<sup>®</sup> is one of the most potent antioxidant supplements on the market with a 97 percent polyphenol content, 65% catechins. Each Tegreen 97<sup>®</sup> capsule contains the catechin equivalent of approximately seven cups of green tea and is 99.5 percent caffeine free.</p>\r\n\n</div>\n\n</div>\n\n</div>\n</div>\n</div>\n<div class=\"contentSection section\"><div>\n<h3>USAGE</h3>\n<div>\n<div class=\"sectionContent parsys\"><div class=\"text parbase section\">\n<p>As a dietary supplement, take one (1) to four (4) capsules daily; preferably one (1) to two (2) each morning and evening with food. Store in a cool, dry place.</p>\r\n\n</div>\n\n</div>\n\n</div>\n</div>\n</div>\n<div class=\"contentSection section\"><div>\n<h3>INGREDIENTS</h3>\n<div>\n<div class=\"sectionContent parsys\"><div class=\"text parbase section\">\n<table border=\"1\" cellspacing=\"1\" cellpadding=\"0\" width=\"360\"><tbody>\r\n<tr>\r\n<td><b>Nutritional Facts</b></td>\r\n<td><b>Amount</b></td>\r\n<td><b>% Daily Value</b></td>\r\n</tr>\r\n<tr>\r\n<td colspan=\"3\"><b>Serving Size: 1 Capsule<br>\r\nServings Per Container: 120</b></td>\r\n</tr>\r\n<tr>\r\n<td width=\"55%\">Green tea leaf (20:1) Extract (<i>Camellia sinensis</i></td>\r\n<td width=\"20%\">250 mg</td>\r\n<td width=\"25%\">&nbsp;</td>\r\n</tr>\r\n<tr>\r\n<td width=\"55%\" colspan=\"3\">* Daily Value not established</td>\r\n</tr>\r\n<tr>\r\n<td width=\"55%\" colspan=\"3\"><b>Other Ingredients: Gelatin, Silicon Dioxide, Microcrystalline Cellulose, Magnesium Stearate.</b></td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n<p>&nbsp;</p>\r\n\n</div>\n\n</div>\n\n</div>\n</div>\n</div>\n</div>\n"
140
+ }
141
+ ],
142
+ "scanQualified": eqVariant.properties.scanQualifiedCount,
143
+ "availableQuantity": eqVariant.inventoryProperties.atpQty,
144
+ "maxQuantity": 999,
145
+ "points": "",
146
+ "cv": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : '',
147
+ "pv":eqVariant.priceFacets.PV,
148
+ "priceType": "WRTL",
149
+ "price": eqVariant.priceFacets["Regular Price"],
150
+ "priceMap": {
151
+ "WRTL": eqVariant.priceFacets["Regular Price"],
152
+ "WADW-WRTL": eqVariant.priceFacets["Regular Price"],
153
+ "WADR": 9999.01,
154
+ "RTL": eqVariant.priceFacets["Regular Price"],
155
+ "WWHL": eqVariant.priceFacets["Wholesale Price"],
156
+ "WADW": 9998.01,
157
+ "WHL": eqVariant.priceFacets["Wholesale Price"]
158
+ },
159
+ "cvMap": {
160
+ "WWHL": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : '',
161
+ "WADW": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : '',
162
+ "WHL": (eqVariant.priceFacets.CV) ? eqVariant.priceFacets.CV : ''
163
+ },
164
+ "pvMap": {
165
+ "WWHL": eqVariant.priceFacets.PV,
166
+ "WADW": eqVariant.priceFacets.PV,
167
+ "WHL": eqVariant.priceFacets.PV
168
+ },
169
+ "orderTypes": {
170
+ "adr": true,
171
+ "order": true,
172
+ "zpfc": false,
173
+ "zadp": true,
174
+ "ars": true,
175
+ "kiosk": true,
176
+ "mobile": true,
177
+ "preferred customer": true,
178
+ "retail": true,
179
+ "web": true,
180
+ "web display": true
181
+ },
182
+ "division": eqVariant.properties.division,
183
+ "backOrderDate": null,
184
+ "locallyProduced": false,
185
+ "agelocme": null,
186
+ "count": "",
187
+ "flavor": "",
188
+ "size": eqVariant.properties.size,
189
+ "shade": "",
190
+ "status": this.switchStatusFromEquinox(eqVariant.properties.status),
191
+ "variantType": "Other",
192
+ "variantDropdownLabel": eqVariant.properties.variantLabel || "",
193
+ "variantDropdownPlaceholder": "Select Type",
194
+ "variantsLabel": eqVariant.properties.variantLabel || "",
195
+ "groupOffer": false,
196
+ "personalOffer": false,
197
+ "savedEventName": null,
198
+ "salesLabel": "",
199
+ "eventName": null,
200
+ "sizeWeight": '',
201
+ "nettoWeight": "",
202
+ "searchScore": 0,
203
+ "isExclusive": false,
204
+ "marketAttributes": {
205
+ "discount": true,
206
+ "redeem": true,
207
+ "earn": true
208
+ },
209
+ "restrictedMarkets": [],
210
+ "addOns": []
211
+ };
212
+ },
213
+
93
214
  eqProductMapper: function (productDataResponse) {
94
215
  let prod = [];
95
216
  let count = 0;
217
+ let variants = {};
96
218
 
97
219
  let prodArr = productDataResponse.map((data) => {
98
220
  let imageURL = data.sku[count].properties.imageURL;
99
221
  const regex = /\d+.\d+/
100
222
  let thumbnailImage = ''
101
-
223
+
102
224
  if (imageURL.includes('contentstack')) {
103
225
  thumbnailImage = imageURL + '?width=40'
104
226
  } else {
105
227
  thumbnailImage = imageURL.replace(regex,'40.40')
106
228
  }
107
- const skuProperties = data.sku[count].properties;
229
+
230
+ if (data.sku && data.sku.length > 1) {
231
+ data.sku.map(variant => {
232
+ variants[variant.identifier] = this.eqProductVariantMapper(variant);
233
+ return variant;
234
+ });
235
+ }
108
236
 
109
237
  prod = {
110
238
  "sku": data.sku[count].identifier,
@@ -116,14 +244,13 @@ const ProductData = {
116
244
  "longDescr": data.properties.productDetailsDescription,
117
245
  "fullImage": imageURL,
118
246
  "imageAltText": data.properties.name,
119
- productCarouselImages: skuProperties.productImages
120
- ? JSON.parse(skuProperties.productImages).map(img => (
121
- {
122
- contentType: /\.jpg/i.test(img.url) ? 'img' : 'video',
123
- src: img.url,
124
- alt: img.alt
125
- }
126
- )) : [],
247
+ "productCarouselImages": [
248
+ {
249
+ "contentType": "img",
250
+ "src": "/content/products/24/00/35/24003529/jcr:content/fullImage.imgw.1280.1280.png",
251
+ "alt": ""
252
+ }
253
+ ],
127
254
  "thumbnail": thumbnailImage,
128
255
  "ingredients": data.properties.ingredients,
129
256
  "benefits": data.properties.benefits,
@@ -139,7 +266,7 @@ const ProductData = {
139
266
  }
140
267
  ],
141
268
  "scanQualified": data.properties.scanQualifiedCount,
142
- "availableQuantity": 999,
269
+ "availableQuantity": data.sku[count].inventoryProperties.atpQty,
143
270
  "maxQuantity": 999,
144
271
  "points": "",
145
272
  "cv": (data.sku[count].priceFacets.CV) ? data.sku[count].priceFacets.CV : '',
@@ -151,9 +278,9 @@ const ProductData = {
151
278
  "WADW-WRTL": data.sku[count].priceFacets["Regular Price"],
152
279
  "WADR": 9999.01,
153
280
  "RTL": data.sku[count].priceFacets["Regular Price"],
154
- "WWHL": 9998.01,
155
281
  "WADW": 9998.01,
156
- "WHL": 9998.01
282
+ "WHL": data.sku[count].priceFacets["Wholesale Price"],
283
+ "WWHL": data.sku[count].priceFacets["Wholesale Price"]
157
284
  },
158
285
  "cvMap": {
159
286
  "WWHL": (data.sku[count].priceFacets.CV) ? data.sku[count].priceFacets.CV : '',
@@ -190,9 +317,9 @@ const ProductData = {
190
317
  "shade": "",
191
318
  "status": this.switchStatusFromEquinox(data.sku[count].properties.productStatus),
192
319
  "variantType": "Other",
193
- "variantDropdownLabel": "Select Type",
320
+ "variantDropdownLabel": data.sku[count].properties.variantLabel || "",
194
321
  "variantDropdownPlaceholder": "Select Type",
195
- "variantsLabel": "Select Type",
322
+ "variantsLabel": data.sku[count].properties.variantLabel || "",
196
323
  "groupOffer": false,
197
324
  "personalOffer": false,
198
325
  "savedEventName": null,
@@ -200,8 +327,7 @@ const ProductData = {
200
327
  "eventName": null,
201
328
  "sizeWeight": '',
202
329
  "nettoWeight": "",
203
- "variants": {
204
- },
330
+ "variants": variants,
205
331
  "searchScore": 0,
206
332
  "isExclusive": data.sku[count].properties.isExclusive,
207
333
  "marketAttributes": {
@@ -210,9 +336,11 @@ const ProductData = {
210
336
  "earn": true
211
337
  },
212
338
  "restrictedMarkets": [],
213
- "addOns": []
339
+ "addOns": [],
340
+ "inventory": data.sku[count].inventory || "" //inventory label
341
+
214
342
  };
215
- let newProduct = new product(prod);
343
+ let newProduct = new Product(prod);
216
344
  return newProduct
217
345
  })
218
346
 
@@ -255,13 +383,13 @@ const ProductData = {
255
383
  },
256
384
 
257
385
  /**
258
- *
259
- * @param {*} custType
260
- *
386
+ *
387
+ * @param {*} custType
388
+ *
261
389
  */
262
390
  switchCustType: function (custType) {
263
391
  let newCustType = [];
264
- if (custType.includes('Brand Affiliate - Business Entity') || custType.includes('Brand Affiliate - Individual'))
392
+ if (custType.includes('Brand Affiliate - Business Entity') || custType.includes('Brand Affiliate - Individual'))
265
393
  newCustType.push(10)
266
394
  if (custType.includes('Retail Customer'))
267
395
  newCustType.push(20)