@nuskin/cs-product-lib 1.7.3-bundleonly-members.1 → 1.8.0-bundleonly-members.1
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 +1 -1
- package/src/csProduct.js +65 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuskin/cs-product-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0-bundleonly-members.1",
|
|
4
4
|
"description": "Library for pulling and parsing product content (and applying business logic) retrieved from Contentstack",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
package/src/csProduct.js
CHANGED
|
@@ -42,6 +42,9 @@ const validateConfig = (props) => {
|
|
|
42
42
|
/* istanbul ignore next */
|
|
43
43
|
const csProduct = (props) => {
|
|
44
44
|
const DEV_ENVIRONMENT = 'public-dev'
|
|
45
|
+
// CS-native sellable gate for the bypassProductStatus path -- mirrors
|
|
46
|
+
// content-validator ValidationSteps (csStatus === 'sellable' || 'bundleOnly').
|
|
47
|
+
const CS_SELLABLE_STATUSES = ['sellable', 'bundleOnly']
|
|
45
48
|
const VARIANTS = 'variants'
|
|
46
49
|
const VARIANT = 'variant'
|
|
47
50
|
const KEY_INGREDIENTS = 'ingredients.key_ingredients'
|
|
@@ -108,7 +111,7 @@ const csProduct = (props) => {
|
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
const removeInvalidVariants = async (products = [], locale, translations, keepBundleOnly = false) => {
|
|
114
|
+
const removeInvalidVariants = async (products = [], locale, translations, keepBundleOnly = false, bypassProductStatus = false) => {
|
|
112
115
|
const validSkus = []
|
|
113
116
|
for (const product of products) {
|
|
114
117
|
for (const variant of product?.variants || []) {
|
|
@@ -125,13 +128,35 @@ const csProduct = (props) => {
|
|
|
125
128
|
let status = {}
|
|
126
129
|
let marketData = {}
|
|
127
130
|
if (validSkus?.length > 0) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
if (bypassProductStatus) {
|
|
132
|
+
// Equinox markets: derive status from the CS entry instead of
|
|
133
|
+
// calling product-status. Live availability/quantity is
|
|
134
|
+
// intentionally not available on this path. Temporary until
|
|
135
|
+
// cs-product-graphql is retired.
|
|
136
|
+
status = {}
|
|
137
|
+
for (const product of products) {
|
|
138
|
+
for (const variant of product?.variants || []) {
|
|
139
|
+
const best = helpers?.getBestSkuData(variant)
|
|
140
|
+
if (best?.sku) {
|
|
141
|
+
const csStatus = helpers.mapCsStatus(variant)
|
|
142
|
+
status[best.sku] = {
|
|
143
|
+
status: { retail: csStatus.retail, wholesale: csStatus.wholesale },
|
|
144
|
+
csStatus: csStatus.status,
|
|
145
|
+
isBackordered: false,
|
|
146
|
+
backorderedAvailableDate: null
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
status = await getProductStatus(
|
|
153
|
+
validSkus,
|
|
154
|
+
locale,
|
|
155
|
+
homeUrl,
|
|
156
|
+
awsBase,
|
|
157
|
+
clientId
|
|
158
|
+
)
|
|
159
|
+
}
|
|
135
160
|
const localeSplit = locale.split('_')
|
|
136
161
|
let market =
|
|
137
162
|
localeSplit?.length > 1 ? localeSplit[1].toUpperCase() : 'XX'
|
|
@@ -156,7 +181,12 @@ const csProduct = (props) => {
|
|
|
156
181
|
const varStatus = status[bestSkuData.sku]
|
|
157
182
|
const isBundleOnly =
|
|
158
183
|
bestSkuData?.status_selections?.status === 'bundleOnly'
|
|
159
|
-
|
|
184
|
+
const passesBypassGate =
|
|
185
|
+
bypassProductStatus &&
|
|
186
|
+
CS_SELLABLE_STATUSES.includes(varStatus?.csStatus)
|
|
187
|
+
const passesStatusGate =
|
|
188
|
+
!bypassProductStatus && varStatus && varStatus.status.retail
|
|
189
|
+
if (passesStatusGate || passesBypassGate || (keepBundleOnly && isBundleOnly)) {
|
|
160
190
|
variant.sap_data.sku_data = [bestSkuData]
|
|
161
191
|
validVariants.push({
|
|
162
192
|
...variant,
|
|
@@ -256,7 +286,7 @@ const csProduct = (props) => {
|
|
|
256
286
|
})
|
|
257
287
|
}
|
|
258
288
|
|
|
259
|
-
const convertKitToRequiredProducts = async (skuKit, locale) => {
|
|
289
|
+
const convertKitToRequiredProducts = async (skuKit, locale, bypassProductStatus = false) => {
|
|
260
290
|
let productBundle = {}
|
|
261
291
|
const variantSkus = []
|
|
262
292
|
for (let kitItem of skuKit[0].variants) {
|
|
@@ -264,8 +294,9 @@ const csProduct = (props) => {
|
|
|
264
294
|
variantSkus.push((skuData || {}).sku)
|
|
265
295
|
kitItem.sku = (skuData || {}).sku
|
|
266
296
|
}
|
|
267
|
-
const products = await getProductsBySku(variantSkus, locale, true)
|
|
297
|
+
const products = await getProductsBySku(variantSkus, locale, true, bypassProductStatus)
|
|
268
298
|
const requiredProducts = []
|
|
299
|
+
const seenSkuQuantities = new Set()
|
|
269
300
|
for (let i = 0; i < products?.length; i++) {
|
|
270
301
|
for (const variantSku of variantSkus) {
|
|
271
302
|
const productSelect = JSON.parse(JSON.stringify(products[i]))
|
|
@@ -276,10 +307,15 @@ const csProduct = (props) => {
|
|
|
276
307
|
}
|
|
277
308
|
}
|
|
278
309
|
if (!isNullOrEmpty(productSelect?.variants)) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
310
|
+
const quantity = skuKit[0].variants.find(v=>v.sku === variantSku).quantity
|
|
311
|
+
const dedupKey = `${variantSku}:${quantity}`
|
|
312
|
+
if (!seenSkuQuantities.has(dedupKey)) {
|
|
313
|
+
seenSkuQuantities.add(dedupKey)
|
|
314
|
+
requiredProducts.push({
|
|
315
|
+
product: [productSelect],
|
|
316
|
+
quantity
|
|
317
|
+
})
|
|
318
|
+
}
|
|
283
319
|
}
|
|
284
320
|
}
|
|
285
321
|
}
|
|
@@ -316,14 +352,15 @@ const csProduct = (props) => {
|
|
|
316
352
|
return [productBundle]
|
|
317
353
|
}
|
|
318
354
|
|
|
319
|
-
const formatKit = async (products, locale, translations) => {
|
|
355
|
+
const formatKit = async (products, locale, translations, bypassProductStatus = false) => {
|
|
320
356
|
for (let p = 0; p < products.length; p++) {
|
|
321
357
|
let noFormat = false
|
|
322
358
|
if (products[p]?.sku_kit?.length > 0) {
|
|
323
359
|
products[p].type = 'kit'
|
|
324
360
|
products[p].product_bundle = await convertKitToRequiredProducts(
|
|
325
361
|
products[p].sku_kit,
|
|
326
|
-
locale
|
|
362
|
+
locale,
|
|
363
|
+
bypassProductStatus
|
|
327
364
|
)
|
|
328
365
|
noFormat = true
|
|
329
366
|
}
|
|
@@ -439,8 +476,8 @@ const csProduct = (props) => {
|
|
|
439
476
|
* @deprecated use getProductsByUID instead
|
|
440
477
|
* @returns
|
|
441
478
|
*/
|
|
442
|
-
const getBundle = async (id, locale) => {
|
|
443
|
-
const bundles = await getBundles(id, locale)
|
|
479
|
+
const getBundle = async (id, locale, bypassProductStatus = false) => {
|
|
480
|
+
const bundles = await getBundles(id, locale, bypassProductStatus)
|
|
444
481
|
return bundles && bundles[0] ? bundles[0] : null
|
|
445
482
|
}
|
|
446
483
|
|
|
@@ -464,7 +501,7 @@ const csProduct = (props) => {
|
|
|
464
501
|
* @deprecated use getProductsByUID instead
|
|
465
502
|
* @returns
|
|
466
503
|
*/
|
|
467
|
-
const getBundles = async (ids, locale) => {
|
|
504
|
+
const getBundles = async (ids, locale, bypassProductStatus = false) => {
|
|
468
505
|
locale = badLocaleMap(locale)
|
|
469
506
|
if (!Array.isArray(ids)) {
|
|
470
507
|
ids = [ids]
|
|
@@ -480,9 +517,11 @@ const csProduct = (props) => {
|
|
|
480
517
|
const products = await queryProducts(query, locale)
|
|
481
518
|
if (Array.isArray(products) && products.length > 0) {
|
|
482
519
|
const translations = await getTranslations(locale)
|
|
483
|
-
await formatKit(products, locale, translations)
|
|
484
|
-
await removeInvalidVariants(products, locale, translations)
|
|
485
|
-
const status =
|
|
520
|
+
await formatKit(products, locale, translations, bypassProductStatus)
|
|
521
|
+
await removeInvalidVariants(products, locale, translations, false, bypassProductStatus)
|
|
522
|
+
const status = bypassProductStatus
|
|
523
|
+
? {}
|
|
524
|
+
: await getProductStatus(getAllBundleIds(products), helpers?.reorderLocale(locale), homeUrl, awsBase, clientId)
|
|
486
525
|
return formatProductWithSchema(products, status)
|
|
487
526
|
}
|
|
488
527
|
const errorResponse = products.response || {}
|
|
@@ -490,7 +529,7 @@ const csProduct = (props) => {
|
|
|
490
529
|
return [{error: {message: products.message, name: products.name, status: errorResponse.status, errors: [`${responseData.error_code}: ${responseData.error_message}`]}}]
|
|
491
530
|
}
|
|
492
531
|
|
|
493
|
-
const getProductsBySku = async (skus, locale, keepBundleOnly = false) => {
|
|
532
|
+
const getProductsBySku = async (skus, locale, keepBundleOnly = false, bypassProductStatus = false) => {
|
|
494
533
|
locale = badLocaleMap(locale)
|
|
495
534
|
if (!Array.isArray(skus)) {
|
|
496
535
|
skus = [skus]
|
|
@@ -516,8 +555,8 @@ const csProduct = (props) => {
|
|
|
516
555
|
return bundleProducts
|
|
517
556
|
}
|
|
518
557
|
const translations = await getTranslations(locale)
|
|
519
|
-
await formatKit(products, locale, translations)
|
|
520
|
-
await removeInvalidVariants(products, locale, translations, keepBundleOnly)
|
|
558
|
+
await formatKit(products, locale, translations, bypassProductStatus)
|
|
559
|
+
await removeInvalidVariants(products, locale, translations, keepBundleOnly, bypassProductStatus)
|
|
521
560
|
const formattedProducts = formatProductWithSchema(products)
|
|
522
561
|
for (const product of formattedProducts) {
|
|
523
562
|
product.skus = skus
|