@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 +6 -4
- package/src/cart/cart.js +12 -1
- package/src/cart/cartService.js +35 -5
- package/src/cart/csProductHelper.js +274 -0
- package/src/cart/equinoxCartService.js +25 -14
- package/src/cart/productService.js +54 -46
- package/src/order/orderAdapter.js +17 -7
- package/src/payment/externalPaymentService.js +7 -1
- package/src/product/SolrQueryService.js +181 -218
- package/src/product/productSearchService.js +1 -8
- package/src/salesEventService.js +60 -72
- package/src/shipping/pickupUtil.js +96 -2
- package/src/product/productSearchAPIQueryService.js +0 -389
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
import $ from '@nuskin/nuskinjquery';
|
|
2
|
-
import { getCachedConfiguration } from '@nuskin/configuration-sdk';
|
|
3
|
-
import { SolrProductAdaptor } from './solrProductAdaptor';
|
|
4
|
-
import { CustomerTypes } from '@nuskin/ns-product-lib';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Checks if the input string follows a specific SKU format.
|
|
8
|
-
* @param {string} str - The input string to be checked.
|
|
9
|
-
* @returns {boolean} Returns true if the input string is a valid SKU format, otherwise false.
|
|
10
|
-
*/
|
|
11
|
-
function isSkuFormat(str) {
|
|
12
|
-
return typeof str === 'string' && str.length === 8 && /^[a-zA-Z0-9]+$/.test(str);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Performs a search in the Equinox catalog based on the provided options.
|
|
17
|
-
* @param {Promise} deferred - A promise object that resolves when the search is complete.
|
|
18
|
-
* @param {Object} options - The search options including searchTerm, rows, language, market.
|
|
19
|
-
*/
|
|
20
|
-
function productSearchAPI(deferred, options) {
|
|
21
|
-
|
|
22
|
-
let allProducts = [];
|
|
23
|
-
let currentPage = 1;
|
|
24
|
-
let baseScore = 5;
|
|
25
|
-
const { MySite_search_API_Base_URLs } = getCachedConfiguration('Equinox_Markets');
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Sends a query to the Equinox catalog API.
|
|
29
|
-
* @returns {Promise} A promise that resolves with the query response.
|
|
30
|
-
*/
|
|
31
|
-
function sendQuery(page) {
|
|
32
|
-
|
|
33
|
-
const query = `
|
|
34
|
-
query ProductSearch(
|
|
35
|
-
$sizeOpt: Int
|
|
36
|
-
$language: String!
|
|
37
|
-
$market: String!
|
|
38
|
-
$storeId: String
|
|
39
|
-
$searchTerm: String
|
|
40
|
-
$filterOpt: String
|
|
41
|
-
$sortOpt: String
|
|
42
|
-
$pageOpt: Int
|
|
43
|
-
) {
|
|
44
|
-
productSearch(
|
|
45
|
-
sizeOpt: $sizeOpt
|
|
46
|
-
language: $language
|
|
47
|
-
market: $market
|
|
48
|
-
store_Id: $storeId
|
|
49
|
-
searchTerm: $searchTerm
|
|
50
|
-
filterOpt: $filterOpt
|
|
51
|
-
sortOpt: $sortOpt
|
|
52
|
-
pageOpt: $pageOpt
|
|
53
|
-
) {
|
|
54
|
-
ProductContent {
|
|
55
|
-
products {
|
|
56
|
-
error {
|
|
57
|
-
errors
|
|
58
|
-
}
|
|
59
|
-
title
|
|
60
|
-
productImages {
|
|
61
|
-
url
|
|
62
|
-
}
|
|
63
|
-
variants {
|
|
64
|
-
title
|
|
65
|
-
sku
|
|
66
|
-
productImages {
|
|
67
|
-
url
|
|
68
|
-
alt
|
|
69
|
-
thumbnail
|
|
70
|
-
}
|
|
71
|
-
isExclusive
|
|
72
|
-
availableChannels
|
|
73
|
-
customerTypes
|
|
74
|
-
description
|
|
75
|
-
searchKeywords
|
|
76
|
-
}
|
|
77
|
-
bundle {
|
|
78
|
-
purchaseTypes {
|
|
79
|
-
buyOnce
|
|
80
|
-
subscription
|
|
81
|
-
}
|
|
82
|
-
customerTypes
|
|
83
|
-
}
|
|
84
|
-
id
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
pageableInfo {
|
|
88
|
-
Page
|
|
89
|
-
Size
|
|
90
|
-
Count
|
|
91
|
-
TotalCount
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
`;
|
|
96
|
-
|
|
97
|
-
const variables = {
|
|
98
|
-
"language": options.language,
|
|
99
|
-
"market": options.market,
|
|
100
|
-
"sizeOpt": options.rows,
|
|
101
|
-
"pageOpt": page,
|
|
102
|
-
"searchTerm": options.searchTerm,
|
|
103
|
-
"filterOpt": null,
|
|
104
|
-
"sortOpt": null
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const data = JSON.stringify({
|
|
108
|
-
query: query,
|
|
109
|
-
variables: variables
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return $.ajax({
|
|
113
|
-
url: MySite_search_API_Base_URLs,
|
|
114
|
-
type: "POST",
|
|
115
|
-
contentType: 'application/json; charset=utf-8',
|
|
116
|
-
data: data
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Extracts relevant information from the product response.
|
|
122
|
-
* @param {Object} response - The response from the Equinox catalog API.
|
|
123
|
-
* @returns {Object} An object containing products and total number found.
|
|
124
|
-
*/
|
|
125
|
-
function processResponse(response) {
|
|
126
|
-
let retValue = {
|
|
127
|
-
products: [],
|
|
128
|
-
totalNumFound: 0
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const result = response.data.productSearch || {};
|
|
132
|
-
|
|
133
|
-
if (result.ProductContent && result.ProductContent.products && result.ProductContent.products.length > 0) {
|
|
134
|
-
let products = result.ProductContent.products;
|
|
135
|
-
|
|
136
|
-
if (options.groupByVariant) {
|
|
137
|
-
products = processGroupByVariant(products);
|
|
138
|
-
} else {
|
|
139
|
-
products = processGroupByParent(products);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
retValue = {
|
|
143
|
-
products,
|
|
144
|
-
totalNumFound: result.pageableInfo.TotalCount
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return retValue;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Processes a list of products to be grouped by parent, generating a mapped product structure.
|
|
153
|
-
*
|
|
154
|
-
* @param {Array} products - The list of products to process.
|
|
155
|
-
* @returns {Array} An array of mapped products with child documents for each variant.
|
|
156
|
-
*/
|
|
157
|
-
function processGroupByParent(products) {
|
|
158
|
-
let mappedProducts = [];
|
|
159
|
-
|
|
160
|
-
//clean up null data (a lot exists in test environment)
|
|
161
|
-
products = products.filter((product) => {
|
|
162
|
-
if(product.error) {
|
|
163
|
-
console.log('Removed Products with error' , product.error)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return !product.error
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
products.forEach((parentProduct) => {
|
|
170
|
-
let mappedParentProduct = parentProduct;
|
|
171
|
-
|
|
172
|
-
if (!isSkuFormat(parentProduct.id) && parentProduct.variants && parentProduct.variants.length > 0) {
|
|
173
|
-
mappedParentProduct = parentProduct.variants[0];
|
|
174
|
-
} else {
|
|
175
|
-
mappedParentProduct.sku = parentProduct.id;
|
|
176
|
-
mappedParentProduct.variants = [];
|
|
177
|
-
mappedParentProduct.variants.push({ ...mappedParentProduct, sku: parentProduct.id });
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
let indexDocuments = parentProduct.variants.map((variant) => {
|
|
181
|
-
|
|
182
|
-
let orderTypes = mapOrderTypes(variant.availableChannels, variant.bundle ? variant.bundle.purchaseTypes : undefined);
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
path_exact: `product/${variant.sku}/${options.language}`,
|
|
186
|
-
sku: [`${variant.sku}`],
|
|
187
|
-
markets: [`${options.market}`],
|
|
188
|
-
variantType: [""],
|
|
189
|
-
name: [`${variant.title}`],
|
|
190
|
-
shortDescription: variant.description,
|
|
191
|
-
longDescription: variant.description,
|
|
192
|
-
searchTerms: variant.searchKeywords,
|
|
193
|
-
isExclusive: mappedParentProduct.isExclusive || "false",
|
|
194
|
-
custType: mapCustomerTypes(variant.bundle ? variant.bundle.customerTypes : variant.customerTypes),
|
|
195
|
-
statusCode: ["10"],
|
|
196
|
-
orderType: Object.keys(orderTypes).filter(key => orderTypes[key]),
|
|
197
|
-
_root_: [`product/${mappedParentProduct.sku}`]
|
|
198
|
-
};
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
let mySiteIndexDocuments = parentProduct.variants.map((variant) => {
|
|
202
|
-
|
|
203
|
-
let orderTypes = mapOrderTypes(variant.availableChannels, variant.bundle ? variant.bundle.purchaseTypes : undefined);
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
path_exact: `product/${variant.sku}/${options.market.toUpperCase()}`,
|
|
207
|
-
sku: [`${variant.sku}`],
|
|
208
|
-
searchTerms: variant.searchKeywords,
|
|
209
|
-
orderType: Object.keys(orderTypes).filter(key => orderTypes[key]),
|
|
210
|
-
custType: mapCustomerTypes(variant.bundle ? variant.bundle.customerTypes : variant.customerTypes),
|
|
211
|
-
statusCode: ["10"],
|
|
212
|
-
webEnabled: ["true"],
|
|
213
|
-
_root_: [`product/${mappedParentProduct.sku}`]
|
|
214
|
-
};
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
indexDocuments = indexDocuments.concat(mySiteIndexDocuments);
|
|
218
|
-
|
|
219
|
-
if (indexDocuments.length > 0) {
|
|
220
|
-
mappedProducts.push({
|
|
221
|
-
path_exact: `product/${mappedParentProduct.sku}`,
|
|
222
|
-
languages: [`${options.language.toLowerCase()}`],
|
|
223
|
-
markets: [`${options.market.toLowerCase()}`],
|
|
224
|
-
sku: [`${mappedParentProduct.sku}`],
|
|
225
|
-
_childDocuments_: indexDocuments
|
|
226
|
-
});
|
|
227
|
-
} else {
|
|
228
|
-
console.log('Invalid Product', mappedParentProduct);
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
console.log('Products' , mappedProducts)
|
|
233
|
-
|
|
234
|
-
return mappedProducts.map((product) => {
|
|
235
|
-
baseScore -= 0.01;
|
|
236
|
-
return new SolrProductAdaptor(product, baseScore)
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Processes a list of products to be grouped by variant, generating a mapped product structure.
|
|
242
|
-
*
|
|
243
|
-
* @param {Array} products - The list of products to process.
|
|
244
|
-
* @returns {Array} An array of mapped products with a flattened structure.
|
|
245
|
-
*/
|
|
246
|
-
function processGroupByVariant(products) {
|
|
247
|
-
|
|
248
|
-
//clean up null data (a lot exists in test environment)
|
|
249
|
-
products = products.filter((product) => {
|
|
250
|
-
if(product.error) {
|
|
251
|
-
console.log('Removed Products with error' , product.error)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return !product.error
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
let groupedProducts = products.map((v) => {
|
|
258
|
-
return v.variants && v.variants.length > 0 ? v.variants : [{ ...v, sku: v.id }];
|
|
259
|
-
}).flat();
|
|
260
|
-
|
|
261
|
-
groupedProducts = groupedProducts.filter((v) => v !== undefined).map((product) => {
|
|
262
|
-
return {
|
|
263
|
-
sku: [product.sku],
|
|
264
|
-
fullImage: (product.productImages && product.productImages.length > 0) ? product.productImages[0].url : '',
|
|
265
|
-
name: product.title || '',
|
|
266
|
-
_root_: `product/${product.sku}`,
|
|
267
|
-
isExclusive: product.isExclusive || "false"
|
|
268
|
-
};
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
let exactSkuResult = groupedProducts.filter((product) => product.sku[0].toLowerCase() === options.searchTerm.toLowerCase());
|
|
272
|
-
|
|
273
|
-
if (isSkuFormat(options.searchTerm) && exactSkuResult.length > 0) {
|
|
274
|
-
groupedProducts = exactSkuResult
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return groupedProducts;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* map EQ customer types to supported product card customer types
|
|
283
|
-
* @param {Array<string>} eqCustomerTypes
|
|
284
|
-
* @returns{string} customer types
|
|
285
|
-
*/
|
|
286
|
-
function mapCustomerTypes(eqCustomerTypes) {
|
|
287
|
-
if (!eqCustomerTypes) {
|
|
288
|
-
return "";
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const custTypes = eqCustomerTypes.map(str => str.toLowerCase());
|
|
292
|
-
|
|
293
|
-
let newCustType = [];
|
|
294
|
-
if (custTypes.includes(CustomerTypes.BrandAffiliate)) {
|
|
295
|
-
newCustType.push(CustomerTypes.properties.BRAND_AFFILIATE.code);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (custTypes.includes(CustomerTypes.Retail)) {
|
|
299
|
-
newCustType.push(CustomerTypes.properties.RETAIL.code);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
if (custTypes.includes(CustomerTypes.Preferred) || custTypes.includes(CustomerTypes.PreferredCustomer)) {
|
|
303
|
-
newCustType.push(CustomerTypes.properties.PREFERRED.code);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
return newCustType.toString().split(",")
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Map Order Types
|
|
311
|
-
* @param {Array<string>} availableChannels
|
|
312
|
-
* @param {object} purchaseTypes
|
|
313
|
-
* @returns {object} orderTypes
|
|
314
|
-
*/
|
|
315
|
-
function mapOrderTypes(availableChannels, purchaseTypes) {
|
|
316
|
-
|
|
317
|
-
let orderTypes = {
|
|
318
|
-
"adr": false,
|
|
319
|
-
"order": false,
|
|
320
|
-
"zpfc": false,
|
|
321
|
-
"zadp": false,
|
|
322
|
-
"ars": false,
|
|
323
|
-
"kiosk": false,
|
|
324
|
-
"mobile": false,
|
|
325
|
-
"preferred customer": false,
|
|
326
|
-
"retail": false,
|
|
327
|
-
"web": false,
|
|
328
|
-
"web display": false
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
if (availableChannels) {
|
|
332
|
-
let availableChannelsArr = Array.isArray(availableChannels) ? availableChannels : availableChannels.split(',');
|
|
333
|
-
|
|
334
|
-
availableChannelsArr.forEach(channel => {
|
|
335
|
-
if (channel == 'arsPhone')
|
|
336
|
-
orderTypes.ars = true
|
|
337
|
-
if (channel == 'web') {
|
|
338
|
-
orderTypes.order = true
|
|
339
|
-
orderTypes.web = true
|
|
340
|
-
}
|
|
341
|
-
if (channel == 'kiosk')
|
|
342
|
-
orderTypes.kiosk = true
|
|
343
|
-
if (channel == 'mobile')
|
|
344
|
-
orderTypes.mobile = true
|
|
345
|
-
if (channel == 'subscription')
|
|
346
|
-
orderTypes.adr = true
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
if (purchaseTypes && purchaseTypes.buyOnce) {
|
|
351
|
-
orderTypes.web = true
|
|
352
|
-
orderTypes.order = true
|
|
353
|
-
}
|
|
354
|
-
if (purchaseTypes && purchaseTypes.subscription) {
|
|
355
|
-
orderTypes.adr = true
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return orderTypes;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
function fetchNextPage() {
|
|
363
|
-
sendQuery(currentPage)
|
|
364
|
-
.then(processResponse)
|
|
365
|
-
.then((result) => {
|
|
366
|
-
allProducts = allProducts.concat(result.products);
|
|
367
|
-
if ((currentPage * options.rows) < result.totalNumFound && !options.groupByVariant) {
|
|
368
|
-
currentPage++;
|
|
369
|
-
fetchNextPage();
|
|
370
|
-
} else {
|
|
371
|
-
deferred.resolve({
|
|
372
|
-
products: allProducts,
|
|
373
|
-
totalNumFound: result.totalNumFound
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
})
|
|
377
|
-
.catch((error) => {
|
|
378
|
-
console.error(error);
|
|
379
|
-
deferred.reject(error);
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
fetchNextPage();
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
export {
|
|
387
|
-
productSearchAPI,
|
|
388
|
-
isSkuFormat
|
|
389
|
-
};
|