@nuskin/ns-product-lib 2.13.0-cx24-100723.3 → 2.13.0-cx24-5107.10

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,24 +1,88 @@
1
- # [2.13.0-cx24-100723.3](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-100723.2...v2.13.0-cx24-100723.3) (2023-10-10)
1
+ # [2.13.0-cx24-5107.10](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.9...v2.13.0-cx24-5107.10) (2023-10-10)
2
2
 
3
3
 
4
- ### New
4
+ ### Fix
5
5
 
6
- * Handle adding variants from bundle ([cc8f8e0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/cc8f8e04d44d6a84894122a7e63cd72b48b724b0))
6
+ * bundle, kit, backorder product type issue ([e7c1979](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/e7c19790b2623aff5aaae1e11280b80229db4cc3))
7
7
 
8
- # [2.13.0-cx24-100723.2](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-100723.1...v2.13.0-cx24-100723.2) (2023-10-07)
8
+ # [2.13.0-cx24-5107.9](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.8...v2.13.0-cx24-5107.9) (2023-10-05)
9
9
 
10
10
 
11
- ### New
11
+ ### Fix
12
12
 
13
- * Handle adding variants from bundle ([a6ae5ac](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/a6ae5ac1f1e5c3b68c11f54a22d9db000f6222d3))
14
- * Handle adding variants from bundle ([8499d68](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/8499d6818cfbd2526da23dea42fd89e288d52ff3))
13
+ * switch off legacy product data api ([62ca7a0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/62ca7a0c3a3901e98c88340e5652fbec77575a7e))
15
14
 
16
- # [2.13.0-cx24-100723.1](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.12.0...v2.13.0-cx24-100723.1) (2023-10-07)
15
+ # [2.13.0-cx24-5107.8](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.7...v2.13.0-cx24-5107.8) (2023-10-03)
17
16
 
18
17
 
19
- ### New
18
+ ### Fix
19
+
20
+ * variants label ([4d217a2](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/4d217a2e8c390cb12e5c3f379bd7296f10df20aa))
21
+
22
+ # [2.13.0-cx24-5107.7](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.6...v2.13.0-cx24-5107.7) (2023-09-29)
23
+
24
+
25
+ ### Fix
26
+
27
+ * single variant ([91fc1c4](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/91fc1c40aa0ac055b330373983f0055d8455176c))
28
+
29
+ # [2.13.0-cx24-5107.6](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.5...v2.13.0-cx24-5107.6) (2023-09-29)
30
+
31
+
32
+ ### Fix
33
+
34
+ * added productData count ([4896fc3](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/4896fc38b9ac841de4ac825659d58500c3bd360b))
35
+ * remove config log ([72739a9](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/72739a9a893ccfa8b3ca76056eab088f5dddef28))
36
+
37
+ # [2.13.0-cx24-5107.5](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.4...v2.13.0-cx24-5107.5) (2023-09-28)
38
+
39
+
40
+ ### Fix
41
+
42
+ * single variant ([3464822](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/3464822e8b3cbdba7ba576ff19247becb00e8a73))
43
+
44
+ # [2.13.0-cx24-5107.4](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.3...v2.13.0-cx24-5107.4) (2023-09-28)
45
+
46
+
47
+ ### Fix
48
+
49
+ * data structure issue ([e262ff6](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/e262ff66889e28159a68bd7f6916a4bed5fe191c))
50
+ * productData ([fdf13c9](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/fdf13c9634c93a0413163cda297f2080457dad43))
51
+
52
+ # [2.13.0-cx24-5107.3](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.2...v2.13.0-cx24-5107.3) (2023-09-28)
53
+
54
+
55
+ ### Fix
56
+
57
+ * http request ([29f5933](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/29f593301621d1daf21b124dc044cc3ca439458e))
58
+
59
+ # [2.13.0-cx24-5107.2](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.13.0-cx24-5107.1...v2.13.0-cx24-5107.2) (2023-09-28)
60
+
61
+
62
+ ### Fix
63
+
64
+ * empty productById ([e4e455c](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/e4e455c34bae3558a429e4cce7c3226517ed6631))
65
+
66
+ # [2.13.0-cx24-5107.1](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.12.0...v2.13.0-cx24-5107.1) (2023-09-28)
67
+
68
+
69
+ ### Fix
70
+
71
+ * directory issue on jest ([41f8afa](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/41f8afa725923b472e33da741874e7ae9feeea73))
72
+ * file directory issue ([568d935](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/568d935f7575dfe18a33cd430d01e17ed3020080))
73
+ * kit and bundle ([5a4f13d](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/5a4f13d10ab87fa5ebfbe549ecb3df0c803f2296))
74
+ * linter ([1bf15af](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/1bf15afee64c0db411e794c5c3181ecbcbf64893))
75
+ * linter error (#CX24-5107) ([03f5abc](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/03f5abcd4940a91c2c04665b24e460813894eeba)), closes [#CX24-5107](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-5107)
76
+ * multi variants ([33ccfdd](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/33ccfdd979e4c229e82814e8b3a0aa93c7a1e14a))
77
+ * odd space in require ([f242b4d](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/f242b4dc696de968607b3c14340c60c3e7baa898))
78
+ * remove old code ([461e70e](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/461e70e1a4d5b1507c940a32bd6c645d5e3f8fef))
79
+ * sonar qube issue ([461a4b9](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/461a4b9007390608ba99b182ef698cc0cd1922cc))
80
+ * unit testing ([cda18ce](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/cda18ce61a0e411df889a2d2939898c54aba6c36))
81
+ * unitest issue in pipeline ([48b99f3](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/48b99f375d1f357f6c5e906a00a09f3ad31042e4))
82
+
83
+ ### Update
20
84
 
21
- * Handle adding variants from bundle ([244e0df](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/244e0df048215fabd63b899442ccc82d753dad9d))
85
+ * use graphql for product data (#CX24-5092) ([9e13973](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/commit/9e139736e08eea59707164dec78ee4dc9542d4ec)), closes [#CX24-5092](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/issues/CX24-5092)
22
86
 
23
87
  # [2.12.0](https://code.tls.nuskin.io/ns-am/product/js-libs/ns-product-lib/compare/v2.11.0...v2.12.0) (2023-09-22)
24
88
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/ns-product-lib",
3
- "version": "2.13.0-cx24-100723.3",
3
+ "version": "2.13.0-cx24-5107.10",
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,27 +1,13 @@
1
1
  const mapBackOrderDate = require('./backOrderDate');
2
2
 
3
-
4
3
  /**
5
4
  * childSKU maps a product variant. Used mainly in subscription.
6
5
  *
7
6
  * @param {import('.').KitSKUQuantity[]} kits
8
7
  * @param {import('.').EquinoxNormalProduct} product
9
8
  */
10
- function childSKUBundle(kits, product, identifier) {
11
- let sku;
12
- let personalOffer = sessionStorage.getItem('personalOffer')
13
- if (personalOffer.active) {
14
- const skuAdd = personalOffer.products.filter((p) => {
15
- return p.sku === identifier
16
- })[0]
17
- sku = product.sku.filter((sku) => {
18
- return sku.identifier == skuAdd.variantSelected[product.identifier]
19
- })[0]
20
- } else {
21
- sku = product.sku.filter(sku => sku.default)[0];
22
- }
23
-
24
-
9
+ function childSKUBundle(kits, product) {
10
+ const sku = product.sku.filter(sku => sku.default)[0];
25
11
  if (!sku) {
26
12
  throw Error('Unable to find the default SKU.');
27
13
  }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ const CustomerTypes = {
4
+ BrandAffiliate: "BrandAffiliate",
5
+ Preferred: "Preferred",
6
+ PreferredCustomer: "Preferred Customer",
7
+ Retail: "Retail",
8
+ properties: {
9
+ BRAND_AFFILIATE: { stringKey: "DIST", code: 10 },
10
+ RETAIL: { stringKey: "CUST", code: 20 },
11
+ PREFERRED: { stringKey: "preferred", code: 30 },
12
+ PREFERRED_CUSTOMER: { stringKey: "PREF", code: 30 }
13
+ }
14
+ };
15
+
16
+ module.exports = CustomerTypes;
@@ -0,0 +1,32 @@
1
+ const { getEnvironmentFromUrl } = require('@nuskin/ns-common-lib');
2
+
3
+ const config = {
4
+ dev: {
5
+ url: 'https://test.nuskin.com/product-api/graphql',
6
+ env: 'dev'
7
+ },
8
+ test: {
9
+ url: 'https://test.nuskin.com/product-api/graphql',
10
+ env: 'test'
11
+ },
12
+ prod: {
13
+ url: 'https://nuskin.com/product-api/graphql',
14
+ env: 'public'
15
+ }
16
+ };
17
+
18
+ /**
19
+ * Get product-api graphQL base URL based on web URL
20
+ * @returns {string} baseUrl (default: prod env url )
21
+ */
22
+ function graphQlUrl () {
23
+ const env = getEnvironmentFromUrl(window.location.host);
24
+
25
+ if (!config[env]) {
26
+ return config['prod'].url;
27
+ }
28
+
29
+ return config[env].url;
30
+ }
31
+
32
+ module.exports = graphQlUrl;
@@ -0,0 +1,7 @@
1
+ const getProduct = require('./product');
2
+ const graphQlUrl = require('./graphQlUrl');
3
+
4
+ module.exports = {
5
+ getProduct,
6
+ getGraphQlUrl: graphQlUrl
7
+ }
@@ -0,0 +1,416 @@
1
+ const axios = require('axios');
2
+ const { getProductByIdQuery } = require('./query');
3
+ const getGraphQlUrl = require('./graphQlUrl')
4
+ const ProductStatus = require("../models/productStatus");
5
+ const CustomerTypes = require('./customerTypes');
6
+ const Product = require("../product");
7
+
8
+ const defaultPayload = {
9
+ operationName: "getProduct",
10
+ useContentSource: "CS"
11
+ };
12
+
13
+ /**
14
+ * graphQl Http request
15
+ * @param {obj} payload
16
+ * @returns {Promise}
17
+ */
18
+ async function graphQlHttpRequest (payload) {
19
+ const url = getGraphQlUrl();
20
+ return await axios.request({
21
+ method: 'post',
22
+ url: url,
23
+ data: payload,
24
+ responseType: 'json'
25
+ });
26
+
27
+ }
28
+
29
+ /**
30
+ * Get product by ID
31
+ * @todo map promotions coming from promotions API
32
+ * @param {string} id
33
+ * @param {string} market
34
+ * @param {string} locale
35
+ * @param {obj} config
36
+ */
37
+ async function getProduct(id, market, locale, config) {
38
+
39
+ const productData = {
40
+ products: [],
41
+ count: 0
42
+ };
43
+
44
+ const payload = {
45
+ ...defaultPayload,
46
+ query: getProductByIdQuery,
47
+ variables: { id, market, locale }
48
+ }
49
+
50
+ try {
51
+ const { data } = await graphQlHttpRequest(payload);
52
+
53
+ if (data && data.data && data.data.productById) {
54
+ const product = mapProduct(data.data.productById, market, locale, config);
55
+ productData.products.push(new Product(product));
56
+ productData.count = productData.products.length;
57
+ }
58
+
59
+ } catch (e) {
60
+ console.log(`Unable to fetch product detail for SKU ${id}`);
61
+ }
62
+
63
+ return {
64
+ data: {
65
+ "status": 200,
66
+ "messages": [],
67
+ "data": productData
68
+ }
69
+ };
70
+ }
71
+
72
+ /**
73
+ *
74
+ * Map product data to be product card consumable structure *
75
+ * @param {object} product
76
+ * @param {string} market
77
+ * @param {string} locale
78
+ * @param {object} config
79
+ * @returns {object} Product
80
+ */
81
+ // eslint-disable-next-line no-unused-vars
82
+ function mapProduct(product, market, locale, config) {
83
+ const kitBundleProducts = product.bundle;
84
+ let variants = product.variants || [];
85
+
86
+
87
+ if (kitBundleProducts) {
88
+
89
+ //merge kitBundleProducts and bundle attribute level
90
+ //since bundle level has totalPrice,availableChannels, etc
91
+ variants.push({
92
+ ...product,
93
+ ...kitBundleProducts,
94
+ productDetails: {
95
+ description: product.description
96
+ }
97
+ });
98
+ }
99
+
100
+ //serves as parent
101
+ const defaultVariant = variants[0];
102
+ const productDetail = {
103
+ "sku": defaultVariant.sku || product.id,
104
+ "globalProductID":product.id,
105
+ "title": defaultVariant.title,
106
+ "country": market,
107
+ "language": locale,
108
+ "shortDescr": defaultVariant.description,
109
+ "longDescr": defaultVariant.productDetails.description,
110
+ "fullImage": defaultVariant.productImages[0].url,
111
+ "imageAltText": defaultVariant.productImages[0].alt,
112
+ "thumbnail": defaultVariant.productImages[0].thumbnail,
113
+ "ingredients": defaultVariant.ingredients,
114
+ "benefits": defaultVariant.benefits,
115
+ "usage": defaultVariant.usage,
116
+ "resources": defaultVariant.resoruces,
117
+ "availableQuantity": defaultVariant.availableQuantity,
118
+ "maxQuantity": defaultVariant.maxQuantity,
119
+ "points": "",
120
+ "cv": (defaultVariant.points) ? defaultVariant.points.wholesale.cv : 0,
121
+ "pv": (defaultVariant.points) ? defaultVariant.points.wholesale.pv : 0,
122
+ "priceType": "WRTL",
123
+ "price": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.retail : defaultVariant.price.retail,
124
+ "priceMap": {
125
+ "WRTL": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.retail : defaultVariant.price.retail,
126
+ "WADW-WRTL": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.retailSubscription : defaultVariant.price.retail,
127
+ "WADR": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.retailSubscription : defaultVariant.price.retailSubscription, //retail ADR (subscription) price
128
+ "RTL": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.retail : defaultVariant.price.retail,
129
+ "WWHL": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.wholesale : defaultVariant.price.wholesale,
130
+ "WADW": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.wholesaleSubscription : defaultVariant.price.wholesaleSubscription,//wholesale ADR (subscription price)
131
+ "WHL": (defaultVariant.totalPrice) ? defaultVariant.totalPrice.wholesale : defaultVariant.price.wholesale
132
+ },
133
+ "cvMap": {
134
+ "WWHL": (defaultVariant.points) ? defaultVariant.points.wholesale.cv : 0,
135
+ "WADW": (defaultVariant.points) ? defaultVariant.points.subscription.cv : 0,
136
+ "WHL": (defaultVariant.points) ? defaultVariant.points.wholesale.cv : 0
137
+ },
138
+ "pvMap": {
139
+ "WWHL": (defaultVariant.points) ? defaultVariant.points.wholesale.pv : 0,
140
+ "WADW": (defaultVariant.points) ? defaultVariant.points.subscription.pv : 0,
141
+ "WHL": (defaultVariant.points) ? defaultVariant.points.wholesale.pv : 0
142
+ },
143
+ "orderTypes": mapOrderTypes(defaultVariant.availableChannels, defaultVariant.purchaseTypes),
144
+ "custTypes": mapCustomerTypes(defaultVariant.customerTypes),
145
+ "backOrderDate": defaultVariant.status.backorderedAvailableDate,
146
+ "size": defaultVariant.size,
147
+ "status": mapProductStatus(defaultVariant.status.status),
148
+ "variantType": "Other",
149
+ "variantDropdownLabel": product.variantSelectLabel || '',
150
+ "variantDropdownPlaceholder": "Select Type",
151
+ "variantsLabel": defaultVariant.variantLabel || '',
152
+ "groupOffer": false,
153
+ "personalOffer": false,
154
+ "savedEventName": '',
155
+ "salesLabel": defaultVariant.salesLabel || defaultVariant.salesText,
156
+ "eventName": defaultVariant.salesLabel || defaultVariant.salesText,
157
+ "sizeWeight": '',
158
+ "nettoWeight": "",
159
+ "searchScore": 0,
160
+ "isExclusive": defaultVariant.isExclusive || false,
161
+ "equinoxProductId": product.id,
162
+ "properties": {
163
+ ...defaultVariant
164
+ }
165
+
166
+ }
167
+
168
+ //map only if it is normal product
169
+ if (product.variants && !kitBundleProducts) {
170
+ productDetail.variants = mapVariants(product);
171
+ }
172
+
173
+ if (kitBundleProducts) {
174
+
175
+ //assemble childSku
176
+ //1st elememt should be parent product
177
+ //graphql returns product type lowercase, this will cause add to cart error if not uppercase
178
+ productDetail.childSkus = [
179
+ {
180
+ availableChannels: Array.isArray(kitBundleProducts.availableChannels) ? kitBundleProducts.availableChannels.join(',') : kitBundleProducts.availableChannels,
181
+ productId: product.id,
182
+ skuId: product.id,
183
+ type: kitBundleProducts.type.toUpperCase()
184
+ },
185
+ ...mapChildSKU(kitBundleProducts)
186
+ ];
187
+ }
188
+
189
+ return productDetail;
190
+ }
191
+
192
+ /**
193
+ * Map product variants
194
+ * @param {*} product
195
+ * @returns {Array<object>} productVariants
196
+ */
197
+ function mapVariants(product) {
198
+
199
+ //return if it has no variant
200
+ if (!product.variants || (product.variants && product.variants.length === 1)) {
201
+ return [];
202
+ }
203
+
204
+ const variants = [];
205
+
206
+ product.variants.forEach(variant => {
207
+ const sku = variant.sku || variant.id;
208
+ variants[sku] = {
209
+ "sku": sku,
210
+ "globalProductID": product.id || variant.globalId,
211
+ "title": variant.title,
212
+ "shortDescr": variant.description,
213
+ "longDescr": variant.productDetails.description,
214
+ "fullImage": variant.productImages[0].url,
215
+ "imageAltText": variant.productImages[0].alt,
216
+ "thumbnail": variant.productImages[0].thumbnail,
217
+ "ingredients": variant.ingredients,
218
+ "benefits": variant.benefits,
219
+ "usage": variant.usage,
220
+ "resources": variant.resoruces,
221
+ "availableQuantity": variant.availableQuantity,
222
+ "maxQuantity": variant.maxQuantity,
223
+ "points": "",
224
+ "cv": (variant.points) ? variant.points.wholesale.cv : 0,
225
+ "pv": (variant.points) ? variant.points.wholesale.pv : 0,
226
+ "priceType": "WRTL",
227
+ "price": (variant.totalPrice) ? variant.totalPrice.retail : variant.price.retail,
228
+ "priceMap": {
229
+ "WRTL": (variant.totalPrice) ? variant.totalPrice.retail : variant.price.retail,
230
+ "WADW-WRTL": (variant.totalPrice) ? variant.totalPrice.retailSubscription : variant.price.retail,
231
+ "WADR": (variant.totalPrice) ? variant.totalPrice.retailSubscription : variant.price.retailSubscription, //retail ADR (subscription) price
232
+ "RTL": (variant.totalPrice) ? variant.totalPrice.retail : variant.price.retail,
233
+ "WWHL": (variant.totalPrice) ? variant.totalPrice.wholesale : variant.price.wholesale,
234
+ "WADW": (variant.totalPrice) ? variant.totalPrice.wholesaleSubscription : variant.price.wholesaleSubscription,//wholesale ADR (subscription price)
235
+ "WHL": (variant.totalPrice) ? variant.totalPrice.wholesale : variant.price.wholesale
236
+ },
237
+ "cvMap": {
238
+ "WWHL": (variant.points) ? variant.points.wholesale.cv : 0,
239
+ "WADW": (variant.points) ? variant.points.subscription.cv : 0,
240
+ "WHL": (variant.points) ? variant.points.wholesale.cv : 0
241
+ },
242
+ "pvMap": {
243
+ "WWHL": (variant.points) ? variant.points.wholesale.pv : 0,
244
+ "WADW": (variant.points) ? variant.points.subscription.pv : 0,
245
+ "WHL": (variant.points) ? variant.points.wholesale.pv : 0
246
+ },
247
+ "orderTypes": mapOrderTypes(variant.availableChannels, variant.purchaseTypes),
248
+ "custTypes": mapCustomerTypes(variant.customerTypes),
249
+ "backOrderDate": variant.status.backorderedAvailableDate,
250
+ "size": variant.size,
251
+ "status": mapProductStatus(variant.status.status),
252
+ "variantType": "Other",
253
+ "variantDropdownLabel": variant.variantLabel || '',
254
+ "variantDropdownPlaceholder": "Select Type",
255
+ "variantsLabel": variant.variantLabel || '',
256
+ "variants": [],
257
+ "groupOffer": false,
258
+ "personalOffer": false,
259
+ "savedEventName": '',
260
+ "salesLabel": variant.salesLabel || variant.salesText,
261
+ "eventName": variant.salesLabel || variant.salesText,
262
+ "sizeWeight": '',
263
+ "nettoWeight": "",
264
+ "searchScore": 0,
265
+ "isExclusive": variant.isExclusive || false,
266
+ "equinoxProductId": product.id,
267
+ "properties": {
268
+ ...product
269
+ }
270
+ }
271
+ });
272
+
273
+ return variants;
274
+ }
275
+
276
+ /**
277
+ * map product kit bundle child SKUs
278
+ * @param {*} kitBundleProducts
279
+ * @returns {array} kitBundleProducts
280
+ */
281
+ function mapChildSKU(kitBundleProducts) {
282
+ if (!kitBundleProducts || !kitBundleProducts.kitProducts) {
283
+ return [];
284
+ }
285
+
286
+ return kitBundleProducts.kitProducts.map((kitProduct) => {
287
+ const { product } = kitProduct;
288
+ const defaultVariant = product.variants[0];
289
+ return {
290
+ productId: product.id,
291
+ skuId: defaultVariant.sku,
292
+ type: 'MANDATORY',
293
+ skuQuantity: kitProduct.quantity,
294
+ availableChannels: Array.isArray(kitBundleProducts.availableChannels) ? kitBundleProducts.availableChannels.join(',') : kitBundleProducts.availableChannels,
295
+ inventory: {
296
+ atpQty: defaultVariant.availableQuantity,
297
+ backOrdered: defaultVariant.status.isBackordered,
298
+ backOrderedQty: defaultVariant.availableQuantity
299
+ }
300
+ }
301
+ });
302
+ }
303
+
304
+ /**
305
+ * map EQ customer types to supported product card customer types
306
+ * @param {Array<string>} eqCustomerTypes
307
+ * @returns{string} customer types
308
+ */
309
+ function mapCustomerTypes(eqCustomerTypes) {
310
+ if (!eqCustomerTypes) {
311
+ return "";
312
+ }
313
+
314
+ const custTypes = eqCustomerTypes;
315
+
316
+ let newCustType = [];
317
+ if (custTypes.includes(CustomerTypes.BrandAffiliate)) {
318
+ newCustType.push(CustomerTypes.properties.BRAND_AFFILIATE.code);
319
+ }
320
+
321
+ if (custTypes.includes(CustomerTypes.Retail)) {
322
+ newCustType.push(CustomerTypes.properties.RETAIL.code);
323
+ }
324
+
325
+ if (custTypes.includes(CustomerTypes.Preferred) || custTypes.includes(CustomerTypes.PreferredCustomer)) {
326
+ newCustType.push(CustomerTypes.properties.PREFERRED.code);
327
+ }
328
+
329
+ return newCustType.toString()
330
+ }
331
+
332
+ /**
333
+ * Map Order Types
334
+ * @param {Array<string>} availableChannels
335
+ * @param {object} purchaseTypes
336
+ * @returns {object} orderTypes
337
+ */
338
+ function mapOrderTypes(availableChannels, purchaseTypes) {
339
+
340
+ let orderTypes = {
341
+ "adr": false,
342
+ "order": false,
343
+ "zpfc": false,
344
+ "zadp": false,
345
+ "ars": false,
346
+ "kiosk": false,
347
+ "mobile": false,
348
+ "preferred customer": false,
349
+ "retail": false,
350
+ "web": false,
351
+ "web display": false
352
+ };
353
+
354
+ if (availableChannels) {
355
+ let availableChannelsArr = Array.isArray(availableChannels) ? availableChannels : availableChannels.split(',');
356
+
357
+ availableChannelsArr.forEach(channel => {
358
+ if (channel == 'arsPhone')
359
+ orderTypes.ars = true
360
+ if (channel == 'web') {
361
+ orderTypes.order = true
362
+ orderTypes.web = true
363
+ }
364
+ if (channel == 'kiosk')
365
+ orderTypes.kiosk = true
366
+ if (channel == 'mobile')
367
+ orderTypes.mobile = true
368
+ if (channel == 'subscription')
369
+ orderTypes.adr = true
370
+ });
371
+ }
372
+
373
+ if (purchaseTypes && purchaseTypes.buyOnce) {
374
+ orderTypes.web = true
375
+ orderTypes.order = true
376
+ }
377
+ if (purchaseTypes && purchaseTypes.subscription) {
378
+ orderTypes.adr = true
379
+ }
380
+
381
+ return orderTypes;
382
+ }
383
+
384
+ /**
385
+ * Map product status from Equinox format to Product card format
386
+ * @param {string} status
387
+ * @returns {string} status
388
+ */
389
+ function mapProductStatus (status) {
390
+ const { equinoxStatus } = ProductStatus;
391
+ let newStatus = '';
392
+ switch (status.toLowerCase()) {
393
+ case equinoxStatus.SELLABLE:
394
+ newStatus = ProductStatus.ReleasedForSale;
395
+ break;
396
+ case equinoxStatus.PREVIEW_PRODUCT:
397
+ newStatus = ProductStatus.NotReleasedForSale;
398
+ break;
399
+ case equinoxStatus.DISCONTINUED:
400
+ newStatus = ProductStatus.Discontinued;
401
+ break;
402
+ case equinoxStatus.STOPPED:
403
+ newStatus = ProductStatus.Discontinued;
404
+ break;
405
+ case equinoxStatus.REPLACEMENT:
406
+ newStatus = ProductStatus.NotReleasedForSale;
407
+ break;
408
+ default:
409
+ newStatus = ProductStatus.NotReleasedForSale;
410
+ break;
411
+ }
412
+
413
+ return newStatus;
414
+ }
415
+
416
+ module.exports = getProduct;
@@ -0,0 +1,535 @@
1
+ "use strict";
2
+
3
+ // eslint-disable-next-line max-len
4
+ const getProductByIdQuery = `query getProduct($id: String!, $market: String, $language: String, $useContentSource: String, $okta: String) {
5
+ productById(
6
+ id: $id
7
+ market: $market
8
+ language: $language
9
+ useContentSource: $useContentSource
10
+ okta: $okta
11
+ ) {
12
+ ...Product
13
+ bundle {
14
+ ...Kit
15
+ __typename
16
+ }
17
+ __typename
18
+ }
19
+ }
20
+
21
+ fragment Product on Product {
22
+ id
23
+ slug
24
+ title
25
+ secondaryTitle
26
+ productImages {
27
+ url
28
+ alt
29
+ thumbnail
30
+ __typename
31
+ }
32
+ salesLabel
33
+ salesText
34
+ description
35
+ salesDisclaimer
36
+ variantSelectLabel
37
+ variants {
38
+ ...Variant
39
+ __typename
40
+ }
41
+ features {
42
+ image {
43
+ url
44
+ alt
45
+ thumbnail
46
+ __typename
47
+ }
48
+ subtitle
49
+ features
50
+ backgroundColor
51
+ textColor
52
+ __typename
53
+ }
54
+ productDetails {
55
+ description
56
+ includedItems
57
+ highlights {
58
+ iconUrl
59
+ label
60
+ __typename
61
+ }
62
+ originCountry
63
+ importer
64
+ warnings
65
+ __typename
66
+ }
67
+ benefits {
68
+ benefits
69
+ image {
70
+ url
71
+ alt
72
+ thumbnail
73
+ __typename
74
+ }
75
+ youTubeVideoId
76
+ __typename
77
+ }
78
+ results {
79
+ summary
80
+ results {
81
+ percentage
82
+ text
83
+ __typename
84
+ }
85
+ report {
86
+ url
87
+ text
88
+ __typename
89
+ }
90
+ image {
91
+ url
92
+ alt
93
+ thumbnail
94
+ __typename
95
+ }
96
+ youTubeVideoId
97
+ __typename
98
+ }
99
+ sustainability {
100
+ youTubeVideoId
101
+ image {
102
+ url
103
+ __typename
104
+ }
105
+ description
106
+ highlights {
107
+ image {
108
+ url
109
+ __typename
110
+ }
111
+ description
112
+ __typename
113
+ }
114
+ __typename
115
+ }
116
+ usage {
117
+ steps
118
+ recommendations
119
+ warnings
120
+ additionalText
121
+ image {
122
+ url
123
+ alt
124
+ thumbnail
125
+ __typename
126
+ }
127
+ youTubeVideoId
128
+ markdown
129
+ __typename
130
+ }
131
+ resources {
132
+ title
133
+ url
134
+ image {
135
+ url
136
+ alt
137
+ thumbnail
138
+ __typename
139
+ }
140
+ __typename
141
+ }
142
+ warranty
143
+ faqs {
144
+ question
145
+ answers
146
+ __typename
147
+ }
148
+ ingredients {
149
+ productName
150
+ allIngredients
151
+ otherIngredients
152
+ activeIngredients
153
+ inactiveIngredients
154
+ ingredientDisclaimers
155
+ markdown
156
+ keyIngredients {
157
+ image {
158
+ url
159
+ alt
160
+ thumbnail
161
+ __typename
162
+ }
163
+ name
164
+ description
165
+ __typename
166
+ }
167
+ nutritionInformationImage {
168
+ url
169
+ alt
170
+ __typename
171
+ }
172
+ __typename
173
+ }
174
+ disclaimers
175
+ disclaimerWarnings {
176
+ icon {
177
+ url
178
+ alt
179
+ __typename
180
+ }
181
+ markdown
182
+ __typename
183
+ }
184
+ seoInformation {
185
+ metaDescription
186
+ metaTitle
187
+ canonicalURL
188
+ ogImage {
189
+ url
190
+ alt
191
+ __typename
192
+ }
193
+ __typename
194
+ }
195
+ thirdPartyScripts
196
+ productDataSource {
197
+ source
198
+ webBaseUrl
199
+ apiBaseUrl
200
+ storeId
201
+ __typename
202
+ }
203
+ error {
204
+ name
205
+ errors
206
+ lines
207
+ message
208
+ status
209
+ __typename
210
+ }
211
+ upSellProductIds
212
+ crossProductIds
213
+ __typename
214
+ }
215
+
216
+ fragment Variant on Variant {
217
+ sku
218
+ globalId
219
+ slug
220
+ variantLabel
221
+ variantColor
222
+ availableChannels
223
+ availableQuantity
224
+ customerTypes
225
+ maxQuantity
226
+ title
227
+ size
228
+ productImages {
229
+ url
230
+ alt
231
+ thumbnail
232
+ __typename
233
+ }
234
+ salesLabel
235
+ salesText
236
+ description
237
+ salesDisclaimer
238
+ nettoWeight
239
+ features {
240
+ image {
241
+ url
242
+ alt
243
+ thumbnail
244
+ __typename
245
+ }
246
+ subtitle
247
+ features
248
+ backgroundColor
249
+ textColor
250
+ __typename
251
+ }
252
+ productDetails {
253
+ description
254
+ includedItems
255
+ highlights {
256
+ iconUrl
257
+ label
258
+ __typename
259
+ }
260
+ originCountry
261
+ importer
262
+ warnings
263
+ __typename
264
+ }
265
+ benefits {
266
+ benefits
267
+ image {
268
+ url
269
+ alt
270
+ thumbnail
271
+ __typename
272
+ }
273
+ youTubeVideoId
274
+ __typename
275
+ }
276
+ results {
277
+ summary
278
+ results {
279
+ percentage
280
+ text
281
+ __typename
282
+ }
283
+ report {
284
+ url
285
+ text
286
+ __typename
287
+ }
288
+ image {
289
+ url
290
+ alt
291
+ thumbnail
292
+ __typename
293
+ }
294
+ youTubeVideoId
295
+ __typename
296
+ }
297
+ usage {
298
+ steps
299
+ recommendations
300
+ warnings
301
+ additionalText
302
+ image {
303
+ url
304
+ alt
305
+ thumbnail
306
+ __typename
307
+ }
308
+ youTubeVideoId
309
+ markdown
310
+ __typename
311
+ }
312
+ resources {
313
+ title
314
+ url
315
+ image {
316
+ url
317
+ alt
318
+ thumbnail
319
+ __typename
320
+ }
321
+ __typename
322
+ }
323
+ faqs {
324
+ question
325
+ answers
326
+ __typename
327
+ }
328
+ ingredients {
329
+ productName
330
+ allIngredients
331
+ otherIngredients
332
+ activeIngredients
333
+ inactiveIngredients
334
+ ingredientDisclaimers
335
+ markdown
336
+ keyIngredients {
337
+ image {
338
+ url
339
+ alt
340
+ thumbnail
341
+ __typename
342
+ }
343
+ name
344
+ description
345
+ __typename
346
+ }
347
+ nutritionInformationImage {
348
+ url
349
+ alt
350
+ __typename
351
+ }
352
+ __typename
353
+ }
354
+ isExclusive
355
+ price {
356
+ retail
357
+ wholesale
358
+ retailSales
359
+ wholesaleSales
360
+ retailSubscription
361
+ wholesaleSubscription
362
+ currencyCode
363
+ __typename
364
+ }
365
+ totalPrice {
366
+ retail
367
+ wholesale
368
+ retailSales
369
+ wholesaleSales
370
+ retailSubscription
371
+ wholesaleSubscription
372
+ currencyCode
373
+ __typename
374
+ }
375
+ points {
376
+ wholesale {
377
+ cv
378
+ pv
379
+ __typename
380
+ }
381
+ subscription {
382
+ cv
383
+ pv
384
+ __typename
385
+ }
386
+ __typename
387
+ }
388
+ totalPoints {
389
+ wholesale {
390
+ cv
391
+ pv
392
+ __typename
393
+ }
394
+ subscription {
395
+ cv
396
+ pv
397
+ __typename
398
+ }
399
+ __typename
400
+ }
401
+ pricingJson
402
+ availableQuantity
403
+ maxQuantity
404
+ status {
405
+ isBackordered
406
+ backorderedAvailableDate
407
+ status
408
+ __typename
409
+ }
410
+ purchaseTypes {
411
+ buyOnce
412
+ subscription
413
+ __typename
414
+ }
415
+ marketAttributes {
416
+ redeem
417
+ earn
418
+ __typename
419
+ }
420
+ disclaimers
421
+ disclaimerWarnings {
422
+ icon {
423
+ url
424
+ alt
425
+ __typename
426
+ }
427
+ markdown
428
+ __typename
429
+ }
430
+ restrictedMarkets
431
+ matchingVariant
432
+ shadeable
433
+ productType
434
+ primaryBrand
435
+ brandFamily
436
+ __typename
437
+ }
438
+
439
+ fragment Kit on Kit {
440
+ id
441
+ type
442
+ price {
443
+ currencyCode
444
+ retail
445
+ wholesale
446
+ retailSales
447
+ wholesaleSales
448
+ retailSubscription
449
+ wholesaleSubscription
450
+ __typename
451
+ }
452
+ totalPrice {
453
+ currencyCode
454
+ retail
455
+ wholesale
456
+ retailSales
457
+ wholesaleSales
458
+ retailSubscription
459
+ wholesaleSubscription
460
+ __typename
461
+ }
462
+ points {
463
+ wholesale {
464
+ cv
465
+ pv
466
+ __typename
467
+ }
468
+ subscription {
469
+ cv
470
+ pv
471
+ __typename
472
+ }
473
+ __typename
474
+ }
475
+ totalPoints {
476
+ wholesale {
477
+ cv
478
+ pv
479
+ __typename
480
+ }
481
+ subscription {
482
+ cv
483
+ pv
484
+ __typename
485
+ }
486
+ __typename
487
+ }
488
+ retailDiscount
489
+ wholesaleDiscount
490
+ pvDiscount
491
+ cvDiscount
492
+ sbDiscount
493
+ grpDiscount
494
+ availableChannels
495
+ customerTypes
496
+ purchaseTypes {
497
+ buyOnce
498
+ subscription
499
+ __typename
500
+ }
501
+ status {
502
+ status
503
+ isBackordered
504
+ backorderedAvailableDate
505
+ __typename
506
+ }
507
+ availableQuantity
508
+ chargeShipping
509
+ dangerousGoods
510
+ excludeFromSearch
511
+ isExclusive
512
+ marketAttributes {
513
+ discount
514
+ redeem
515
+ earn
516
+ __typename
517
+ }
518
+ restrictedMarkets
519
+ scanQualifiedCount
520
+ kitProducts {
521
+ quantity
522
+ isMandatory
523
+ product {
524
+ ...Product
525
+ __typename
526
+ }
527
+ __typename
528
+ }
529
+ __typename
530
+ }`
531
+
532
+
533
+ module.exports = {
534
+ getProductByIdQuery
535
+ };
@@ -7,7 +7,7 @@ const CustomerTypes = require('./models/customerTypes');
7
7
  const ProductStatus = require("./models/productStatus");
8
8
  const { mapBackOrderDate, mapAvailableQuantity, mapChildSKU, mapChildSKUBundle } = require('./equinox-helpers');
9
9
  const { productNotFoundInterceptor } = require('./equinox-helpers/interceptors');
10
-
10
+ const { getProduct } = require('./graph-ql');
11
11
  const productTypes = {
12
12
  kit: 'kit',
13
13
  bundle: 'bundle'
@@ -19,19 +19,17 @@ const ProductData = {
19
19
  * @param {string[]} skus
20
20
  * @param {string} locale
21
21
  * @param {string} market
22
- * @param {boolean} isEquinoxEnabled
23
22
  */
24
- getProductData: async function (skus, locale, market, isEquinoxEnabled = false) {
23
+ getProductData: async function (skus, locale, market) {
25
24
  const localeMarket = `${locale}_${market}`;
26
25
 
27
- if (isEquinoxEnabled) {
28
- const config = (await getConfiguration(['Equinox_Markets'])).Equinox_Markets;
29
-
30
- if (config.country_code === market && config.active) {
31
- return await this.getProductFromEquinox(skus, localeMarket, config);
32
- }
26
+ const config = (await getConfiguration(['Equinox_Markets'])).Equinox_Markets;
27
+ if (config.active) {
28
+ return await getProduct(skus[0], market, locale, config);
29
+ } else {
30
+ return await this.getProductFromLegacy(skus, localeMarket);
33
31
  }
34
- return await this.getProductFromLegacy(skus, localeMarket);
32
+
35
33
  },
36
34
 
37
35
  getProductFromEquinox: async function (skus, locale, config) {
@@ -60,7 +58,8 @@ const ProductData = {
60
58
 
61
59
  const shoppingContext = window && window.aem && window.aem.ShoppingContext && window.aem.ShoppingContext.getShoppingContext();
62
60
 
63
- if ((shoppingContext && shoppingContext.context === 'storefront') || window.location.hostname.includes(".mynuskin.com")) {
61
+ if ((shoppingContext && shoppingContext.context === 'storefront')
62
+ || window.location.hostname.includes(".mynuskin.com")) {
64
63
  config.API_Base_URLs = config.MySite_API_Base_URLs
65
64
  }
66
65
 
@@ -144,7 +143,7 @@ const ProductData = {
144
143
  * @param {obj} inventory
145
144
  * @returns {number} qty
146
145
  */
147
- getAvailableQty: function (inventory) {
146
+ getAvailableQty: function(inventory) {
148
147
  if (!inventory || (!inventory.hasOwnProperty('backOrdered')
149
148
  || !inventory.hasOwnProperty('atpQty') || !inventory.hasOwnProperty('backOrderedQty'))) {
150
149
  return 0;
@@ -162,7 +161,7 @@ const ProductData = {
162
161
  * @param {*} product
163
162
  * @returns {number} backOrderDate
164
163
  */
165
- getBackOrderDate: function (product) {
164
+ getBackOrderDate: function(product) {
166
165
 
167
166
  if ((product.type === productTypes.kit || product.type === productTypes.bundle) && product.childSkus) {
168
167
 
@@ -637,7 +636,7 @@ const ProductData = {
637
636
  type: 'BUNDLE',
638
637
  availableChannels: product.properties.availableChannels
639
638
  },
640
- ...res.data.product.map(p => mapChildSKUBundle(bundles, p, product.identifier))
639
+ ...res.data.product.map(p => mapChildSKUBundle(bundles, p))
641
640
  ];
642
641
 
643
642
  return childSkus;