@nuskin/ns-shop 7.5.6-mdigi-4997.1 → 7.6.0-brw-988.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
CHANGED
|
@@ -395,7 +395,7 @@ function _assembleChildSkus(requestData, options) {
|
|
|
395
395
|
if (personalOffer !== null) {
|
|
396
396
|
personalOffer = JSON.parse(personalOffer);
|
|
397
397
|
productWithVariant = personalOffer.products.filter((sku) =>
|
|
398
|
-
sku.type
|
|
398
|
+
sku.type === 'bundle' && sku.variantSelected !== null && sku.sku === productSku
|
|
399
399
|
)
|
|
400
400
|
}
|
|
401
401
|
|
|
@@ -411,17 +411,18 @@ function _assembleChildSkus(requestData, options) {
|
|
|
411
411
|
}
|
|
412
412
|
if (personalOffer != null && selectedVariants && cs.skuId != selectedVariants[cs.productId] && (cs.type !== "BUNDLE" && cs.type !== "OPTIONAL")) return null
|
|
413
413
|
const childSku =
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
414
|
+
(personalOffer != null && selectedVariants && selectedVariants[cs.productId] && config.MySite_graphql_active)
|
|
415
|
+
? {
|
|
416
|
+
productId: cs.productId,
|
|
417
|
+
skuId: selectedVariants[cs.productId],
|
|
418
|
+
type: cs.type,
|
|
419
|
+
availableChannels: cs.availableChannels
|
|
420
|
+
} : {
|
|
421
|
+
productId: cs.productId,
|
|
422
|
+
skuId: cs.skuId,
|
|
423
|
+
type: cs.type,
|
|
424
|
+
availableChannels: cs.availableChannels
|
|
425
|
+
}
|
|
425
426
|
if (cs.inventory) {
|
|
426
427
|
childSku.skuQuantity = cs.skuQuantity;
|
|
427
428
|
childSku.backOrdered = cs.inventory.backOrdered;
|
|
@@ -4,7 +4,8 @@ import {ProductResultsEnum} from "./productResultsEnum.js";
|
|
|
4
4
|
import OrderType from "./orderType.js";
|
|
5
5
|
import {SolrProductAdaptor} from "./solrProductAdaptor.js";
|
|
6
6
|
import {SolrQueryUrlService} from "./solrQueryUrlService.js";
|
|
7
|
-
import {getCachedConfigField} from '@nuskin/configuration-sdk';
|
|
7
|
+
import {getCachedConfigField, getCachedConfiguration} from '@nuskin/configuration-sdk';
|
|
8
|
+
import {allPredictiveSearch, predictiveSearch} from "./productSearchAPIQueryService.js"
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
*
|
|
@@ -436,120 +437,134 @@ let SolrQueryService = function() {
|
|
|
436
437
|
productResultType, searchTerm, productSearchFields, language, market, searchByOrderType ? rows*5 : rows, start
|
|
437
438
|
);
|
|
438
439
|
|
|
439
|
-
|
|
440
|
-
let queryResponsePromise = $.ajax({
|
|
441
|
-
url: solrUrl,
|
|
442
|
-
type: "GET",
|
|
443
|
-
contentType: 'application/json; charset=utf-8',
|
|
444
|
-
headers: {
|
|
445
|
-
"client_id": getCachedConfigField('solrClientId'),
|
|
446
|
-
"client_secret": getCachedConfigField('solrClientSecret')
|
|
447
|
-
},
|
|
448
|
-
timeout: SolrTimeout,
|
|
449
|
-
success: function () {
|
|
450
|
-
//console.log("Search success!");
|
|
451
|
-
},
|
|
452
|
-
error: function (xmlHttpRequest, textStatus) {
|
|
453
|
-
deferred.reject(textStatus);
|
|
454
|
-
//console.log('Search failed!');
|
|
455
|
-
}
|
|
456
|
-
});
|
|
440
|
+
const {active, MySite_search_API_Base_URLs} = getCachedConfiguration('Equinox_Markets');
|
|
457
441
|
|
|
458
|
-
|
|
459
|
-
let retValue;
|
|
460
|
-
let docs, totalNumFound/*, responseHeader*/;
|
|
442
|
+
if(active && MySite_search_API_Base_URLs !== '') {
|
|
461
443
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
// responseHeader = responseData.responseHeader;
|
|
470
|
-
}
|
|
444
|
+
predictiveSearch(deferred, {
|
|
445
|
+
searchTerm,
|
|
446
|
+
rows,
|
|
447
|
+
language,
|
|
448
|
+
market,
|
|
449
|
+
page: start/rows
|
|
450
|
+
})
|
|
471
451
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
else {
|
|
493
|
-
docs = responseData.response.docs;
|
|
494
|
-
totalNumFound = responseData.response.numFound;
|
|
495
|
-
}
|
|
452
|
+
} else {
|
|
453
|
+
// Search for language nodes for the given market that match the search term.
|
|
454
|
+
let queryResponsePromise = $.ajax({
|
|
455
|
+
url: solrUrl,
|
|
456
|
+
type: "GET",
|
|
457
|
+
contentType: 'application/json; charset=utf-8',
|
|
458
|
+
headers: {
|
|
459
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
460
|
+
"client_secret": getCachedConfigField('solrClientSecret')
|
|
461
|
+
},
|
|
462
|
+
timeout: SolrTimeout,
|
|
463
|
+
success: function () {
|
|
464
|
+
//console.log("Search success!");
|
|
465
|
+
},
|
|
466
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
467
|
+
deferred.reject(textStatus);
|
|
468
|
+
//console.log('Search failed!');
|
|
469
|
+
}
|
|
470
|
+
});
|
|
496
471
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
if (docs[i]._childDocuments_) {
|
|
501
|
-
for (let m = 0; m < docs[i]._childDocuments_.length; m++) {
|
|
502
|
-
if ((docs[i]._childDocuments_[m].path_exact === "product/" + docs[i].sku + '/' + market.toUpperCase()) &&
|
|
503
|
-
!docs[i]._childDocuments_[m].excludeFromSearch) {
|
|
472
|
+
queryResponsePromise.then(function(responseData) {
|
|
473
|
+
let retValue;
|
|
474
|
+
let docs, totalNumFound/*, responseHeader*/;
|
|
504
475
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
476
|
+
if (typeof(responseData) === "string") {
|
|
477
|
+
docs = $.parseJSON(responseData).response.docs;
|
|
478
|
+
totalNumFound = $.parseJSON(responseData).response.numFound;
|
|
479
|
+
// responseHeader = $.parseJSON(responseData).responseHeader;
|
|
480
|
+
} else {
|
|
481
|
+
docs = responseData.response.docs;
|
|
482
|
+
totalNumFound = responseData.response.numFound;
|
|
483
|
+
// responseHeader = responseData.responseHeader;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (searchByOrderType) {
|
|
487
|
+
solrUrl = SolrQueryUrlService.getProductsByRoots(docs, language, market, rows, 0, orderTypes);
|
|
488
|
+
let _orderTypes = orderTypes;
|
|
489
|
+
if (solrUrl.url) {
|
|
490
|
+
let productDocuments = [];
|
|
491
|
+
queryResponsePromise = $.ajax({
|
|
492
|
+
url: solrUrl.url,
|
|
493
|
+
type: "POST",
|
|
494
|
+
contentType: 'application/json; charset=utf-8',
|
|
495
|
+
headers: {
|
|
496
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
497
|
+
"client_secret":getCachedConfigField('solrClientSecret')
|
|
498
|
+
},
|
|
499
|
+
timeout: SolrTimeout,
|
|
500
|
+
data: JSON.stringify(solrUrl.postData),
|
|
501
|
+
success: function (responseData) {
|
|
502
|
+
if (typeof(responseData) === "string") {
|
|
503
|
+
docs = $.parseJSON(responseData).response.docs;
|
|
504
|
+
totalNumFound = $.parseJSON(responseData).response.numFound;
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
docs = responseData.response.docs;
|
|
508
|
+
totalNumFound = responseData.response.numFound;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Wrap the products in an adaptor for ease of use.
|
|
512
|
+
for (let i = 0; i < docs.length; i++) {
|
|
513
|
+
//ONLY RETURN PRODUCTS THAT HAVE A MARKET
|
|
514
|
+
if (docs[i]._childDocuments_) {
|
|
515
|
+
for (let m = 0; m < docs[i]._childDocuments_.length; m++) {
|
|
516
|
+
if ((docs[i]._childDocuments_[m].path_exact === "product/" + docs[i].sku + '/' + market.toUpperCase()) &&
|
|
517
|
+
!docs[i]._childDocuments_[m].excludeFromSearch) {
|
|
518
|
+
|
|
519
|
+
if (!skuExistsInProductArray(productDocuments, docs[i].sku.toString())) {
|
|
520
|
+
let prodAdaptor = new SolrProductAdaptor(docs[i]);
|
|
521
|
+
let marketChild = prodAdaptor.getMarketChild(market);
|
|
522
|
+
let languageChild = prodAdaptor.getLanguageChild(language);
|
|
523
|
+
if (existsInArray(marketChild.getOrderType(), _orderTypes)) {
|
|
524
|
+
productDocuments.push({
|
|
525
|
+
sku: docs[i].sku,
|
|
526
|
+
fullImage: marketChild.getFullImageUrl(),
|
|
527
|
+
name: languageChild.getTitle(),
|
|
528
|
+
_root_: "product/" + docs[i].sku,
|
|
529
|
+
isExclusive: languageChild.getIsExclusive()
|
|
530
|
+
});
|
|
531
|
+
}
|
|
517
532
|
}
|
|
518
533
|
}
|
|
519
534
|
}
|
|
520
535
|
}
|
|
521
536
|
}
|
|
522
|
-
}
|
|
523
537
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
538
|
+
let retValue = {
|
|
539
|
+
products: productDocuments,
|
|
540
|
+
totalNumFound: totalNumFound
|
|
541
|
+
};
|
|
528
542
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
543
|
+
deferred.resolve(retValue);
|
|
544
|
+
},
|
|
545
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
546
|
+
deferred.reject(textStatus);
|
|
547
|
+
//console.log('Search failed!');
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
} else {
|
|
551
|
+
retValue = {
|
|
552
|
+
products: docs,
|
|
553
|
+
totalNumFound: totalNumFound
|
|
554
|
+
};
|
|
555
|
+
deferred.resolve(retValue);
|
|
556
|
+
}
|
|
536
557
|
} else {
|
|
537
558
|
retValue = {
|
|
538
559
|
products: docs,
|
|
539
560
|
totalNumFound: totalNumFound
|
|
540
561
|
};
|
|
562
|
+
|
|
541
563
|
deferred.resolve(retValue);
|
|
542
564
|
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
totalNumFound: totalNumFound
|
|
547
|
-
};
|
|
548
|
-
|
|
549
|
-
deferred.resolve(retValue);
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
|
|
553
568
|
return deferred;
|
|
554
569
|
}
|
|
555
570
|
|
|
@@ -573,113 +588,127 @@ let SolrQueryService = function() {
|
|
|
573
588
|
productResultType, searchTerm, productSearchFields, language, market, rows, start
|
|
574
589
|
);
|
|
575
590
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
|
|
591
|
+
const {active, MySite_search_API_Base_URLs} = getCachedConfiguration('Equinox_Markets');
|
|
592
|
+
|
|
593
|
+
if(active && MySite_search_API_Base_URLs !== '') {
|
|
594
|
+
|
|
595
|
+
allPredictiveSearch(deferred, {
|
|
596
|
+
searchTerm,
|
|
597
|
+
language,
|
|
598
|
+
market
|
|
599
|
+
})
|
|
600
|
+
|
|
601
|
+
} else {
|
|
602
|
+
|
|
603
|
+
// Search for language nodes for the given market that match the search term.
|
|
604
|
+
let queryResponsePromise = $.ajax({
|
|
605
|
+
url: solrUrl,
|
|
606
|
+
type: "GET",
|
|
607
|
+
contentType: 'application/json; charset=utf-8',
|
|
608
|
+
headers: {
|
|
609
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
610
|
+
"client_secret": getCachedConfigField('solrClientSecret')
|
|
611
|
+
},
|
|
612
|
+
timeout: SolrTimeout,
|
|
613
|
+
success: function () {
|
|
587
614
|
//console.log("Search success!");
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
615
|
+
},
|
|
616
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
617
|
+
deferred.reject(textStatus);
|
|
591
618
|
//console.log('Search failed!');
|
|
592
|
-
|
|
593
|
-
|
|
619
|
+
}
|
|
620
|
+
});
|
|
594
621
|
|
|
595
|
-
|
|
596
|
-
|
|
622
|
+
queryResponsePromise.then(function(responseData){
|
|
623
|
+
let matchingRootProducts, totalNumFound, responseHeader;
|
|
597
624
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
625
|
+
if (typeof(responseData) === "string") {
|
|
626
|
+
matchingRootProducts = $.parseJSON(responseData).response.docs;
|
|
627
|
+
totalNumFound = $.parseJSON(responseData).response.numFound;
|
|
628
|
+
responseHeader = $.parseJSON(responseData).responseHeader;
|
|
629
|
+
} else {
|
|
630
|
+
matchingRootProducts = responseData.response.docs;
|
|
631
|
+
totalNumFound = responseData.response.numFound;
|
|
632
|
+
responseHeader = responseData.responseHeader;
|
|
633
|
+
}
|
|
607
634
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
635
|
+
// If the zkConnected header is true, we count on the data returned from the query being accurate.
|
|
636
|
+
// If it's false, we will re-try the Solr query so that we are sure we have the most up-to-date information
|
|
637
|
+
// (We only try again once, which is what sets the retrySolrRequest variable)
|
|
638
|
+
if (responseHeader.zkConnected || !retrySolrRequest) {
|
|
612
639
|
// eslint-disable-next-line
|
|
613
640
|
// Example solrUrl: http://dev-gateway-mulesoft-21:8080/mec/solr/oak/select?fl=*,[child%20parentFilter=path_exact:product/????????%20childFilter=path_exact:product/????????/en],[child%20parentFilter=path_exact:product/????????%20childFilter=path_exact:product/????????/US]&q=path_exact:product/01003611&rows=5&wt=json
|
|
614
641
|
// Always start at 0 so we get all the rows we are asking for.
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
642
|
+
solrUrl = SolrQueryUrlService.getProductsByRoots(matchingRootProducts, language, market, rows, 0, orderTypes);
|
|
643
|
+
|
|
644
|
+
if (solrUrl.url) {
|
|
645
|
+
let productDocuments = [];
|
|
646
|
+
|
|
647
|
+
// Return the complete records for the given matches
|
|
648
|
+
queryResponsePromise = $.ajax({
|
|
649
|
+
url: solrUrl.url,
|
|
650
|
+
type: "POST",
|
|
651
|
+
contentType: 'application/json; charset=utf-8',
|
|
652
|
+
headers: {
|
|
653
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
654
|
+
"client_secret": getCachedConfigField('solrClientSecret')
|
|
655
|
+
},
|
|
656
|
+
data: JSON.stringify(solrUrl.postData),
|
|
657
|
+
timeout: SolrTimeout,
|
|
658
|
+
success: function (responseData) {
|
|
659
|
+
let docs;
|
|
660
|
+
|
|
661
|
+
if (typeof(responseData) === "string") {
|
|
662
|
+
docs = $.parseJSON(responseData).response.docs;
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
docs = responseData.response.docs;
|
|
666
|
+
}
|
|
640
667
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
668
|
+
for (let i = 0; i < matchingRootProducts.length; i++) {
|
|
669
|
+
matchingRootProducts[i].path_exact = matchingRootProducts[i]._root_[0];
|
|
670
|
+
}
|
|
644
671
|
|
|
645
|
-
|
|
646
|
-
|
|
672
|
+
// Wrap the products in an adaptor for ease of use.
|
|
673
|
+
for (let i = 0; i < docs.length; i++) {
|
|
647
674
|
//ONLY RETURN PRODUCTS THAT HAVE A MARKET
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
675
|
+
if (docs[i]._childDocuments_) {
|
|
676
|
+
for (let m = 0; m < docs[i]._childDocuments_.length; m++) {
|
|
677
|
+
if ((docs[i]._childDocuments_[m].path_exact === "product/" + docs[i].sku + '/' + market.toUpperCase()) &&
|
|
651
678
|
!docs[i]._childDocuments_[m].excludeFromSearch) {
|
|
652
679
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
680
|
+
if (!skuExistsInSolrProductAdaptorArray(productDocuments, docs[i].sku.toString())) {
|
|
681
|
+
const match = matchingRootProducts.find(root => root.path_exact === docs[i].path_exact) || null;
|
|
682
|
+
const score = match ? match.score : 0;
|
|
683
|
+
productDocuments.push(new SolrProductAdaptor(docs[i], score));
|
|
684
|
+
}
|
|
657
685
|
}
|
|
658
686
|
}
|
|
659
687
|
}
|
|
660
688
|
}
|
|
661
|
-
}
|
|
662
689
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
690
|
+
let retValue = {
|
|
691
|
+
products: productDocuments,
|
|
692
|
+
totalNumFound: totalNumFound
|
|
693
|
+
};
|
|
667
694
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
695
|
+
deferred.resolve(retValue);
|
|
696
|
+
},
|
|
697
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
698
|
+
deferred.reject(textStatus);
|
|
672
699
|
//console.log('Search failed!');
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
deferred.resolve(undefined);
|
|
705
|
+
}
|
|
706
|
+
} else {
|
|
707
|
+
getProductsBySearchFields(productResultType, searchTerm, productSearchFields, language, market, rows, start, orderTypes, deferred)
|
|
678
708
|
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
});
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
}
|
|
683
712
|
|
|
684
713
|
return deferred;
|
|
685
714
|
}
|
|
@@ -0,0 +1,521 @@
|
|
|
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
|
+
// const {$} = require('@nuskin/nuskinjquery');
|
|
7
|
+
// const { getCachedConfiguration } = require('@nuskin/configuration-sdk');
|
|
8
|
+
// const { SolrProductAdaptor } = require('./solrProductAdaptor');
|
|
9
|
+
// const { CustomerTypes } = require('@nuskin/ns-product-lib');
|
|
10
|
+
|
|
11
|
+
let baseScore = 5;
|
|
12
|
+
const searchQuery = `
|
|
13
|
+
query ProductSearch(
|
|
14
|
+
$market: String!
|
|
15
|
+
$language: String!
|
|
16
|
+
$searchTerm: String
|
|
17
|
+
$sizeOpt: Int
|
|
18
|
+
$pageOpt: Int
|
|
19
|
+
) {
|
|
20
|
+
productSearch(
|
|
21
|
+
sizeOpt: $sizeOpt
|
|
22
|
+
language: $language
|
|
23
|
+
market: $market
|
|
24
|
+
searchTerm: $searchTerm
|
|
25
|
+
pageOpt: $pageOpt
|
|
26
|
+
) {
|
|
27
|
+
ProductContent {
|
|
28
|
+
products {
|
|
29
|
+
error {
|
|
30
|
+
errors
|
|
31
|
+
}
|
|
32
|
+
title
|
|
33
|
+
productImages {
|
|
34
|
+
url
|
|
35
|
+
}
|
|
36
|
+
variants {
|
|
37
|
+
title
|
|
38
|
+
sku
|
|
39
|
+
productImages {
|
|
40
|
+
url
|
|
41
|
+
alt
|
|
42
|
+
thumbnail
|
|
43
|
+
}
|
|
44
|
+
isExclusive
|
|
45
|
+
availableChannels
|
|
46
|
+
customerTypes
|
|
47
|
+
description
|
|
48
|
+
searchKeywords
|
|
49
|
+
}
|
|
50
|
+
bundle {
|
|
51
|
+
purchaseTypes {
|
|
52
|
+
buyOnce
|
|
53
|
+
subscription
|
|
54
|
+
}
|
|
55
|
+
customerTypes
|
|
56
|
+
}
|
|
57
|
+
id
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
pageableInfo {
|
|
61
|
+
page
|
|
62
|
+
size
|
|
63
|
+
count
|
|
64
|
+
totalCount
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}`;
|
|
68
|
+
const predictiveQuery = `
|
|
69
|
+
query PredictiveSearch($language: String, $market: String, $page: Int, $searchTerm: String, $size: Int) {
|
|
70
|
+
predictiveSearch(
|
|
71
|
+
language: $language
|
|
72
|
+
market: $market
|
|
73
|
+
page: $page
|
|
74
|
+
searchTerm: $searchTerm
|
|
75
|
+
size: $size
|
|
76
|
+
) {
|
|
77
|
+
didYouMean
|
|
78
|
+
pagination {
|
|
79
|
+
count
|
|
80
|
+
page
|
|
81
|
+
size
|
|
82
|
+
totalCount
|
|
83
|
+
}
|
|
84
|
+
products {
|
|
85
|
+
id
|
|
86
|
+
isExclusive
|
|
87
|
+
sku
|
|
88
|
+
slug
|
|
89
|
+
title
|
|
90
|
+
price {
|
|
91
|
+
retail
|
|
92
|
+
retailSales
|
|
93
|
+
wholesale
|
|
94
|
+
wholesaleSales
|
|
95
|
+
}
|
|
96
|
+
productImages {
|
|
97
|
+
url
|
|
98
|
+
thumbnail
|
|
99
|
+
alt
|
|
100
|
+
}
|
|
101
|
+
status {
|
|
102
|
+
status
|
|
103
|
+
inventory
|
|
104
|
+
isBackordered
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}`;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checks if the input string follows a specific SKU format.
|
|
112
|
+
* @param {string} str - The input string to be checked.
|
|
113
|
+
* @returns {boolean} Returns true if the input string is a valid SKU format, otherwise false.
|
|
114
|
+
*/
|
|
115
|
+
function isSkuFormat(str) {
|
|
116
|
+
return typeof str === 'string' && str.length === 8 && /^[a-zA-Z0-9]+$/.test(str);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Sends a query to the product-search graphql
|
|
121
|
+
* @returns {Promise} A promise that resolves with the query response.
|
|
122
|
+
*/
|
|
123
|
+
function sendQuery(query, variables, page) {
|
|
124
|
+
if (page) {
|
|
125
|
+
variables.pageOpt = page;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const { MySite_search_API_Base_URLs } = getCachedConfiguration('Equinox_Markets');
|
|
129
|
+
|
|
130
|
+
const data = JSON.stringify({
|
|
131
|
+
query: query,
|
|
132
|
+
variables: variables
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return $.ajax({
|
|
136
|
+
url: MySite_search_API_Base_URLs,
|
|
137
|
+
type: "POST",
|
|
138
|
+
contentType: 'application/json; charset=utf-8',
|
|
139
|
+
data: data
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Extracts relevant information from the product search response.
|
|
145
|
+
* @param {Object} response - The response from the product-search graphql.
|
|
146
|
+
* @returns {Object} An object containing products and total number found.
|
|
147
|
+
*/
|
|
148
|
+
function processSearchResponse(response, options) {
|
|
149
|
+
let retValue = {
|
|
150
|
+
products: [],
|
|
151
|
+
totalNumFound: 0
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const result = response.data.productSearch || {};
|
|
155
|
+
|
|
156
|
+
if (result.ProductContent && result.ProductContent.products && result.ProductContent.products.length > 0) {
|
|
157
|
+
let products = result.ProductContent.products;
|
|
158
|
+
products = processGroupByParent(products, options);
|
|
159
|
+
|
|
160
|
+
retValue = {
|
|
161
|
+
products,
|
|
162
|
+
totalNumFound: result.pageableInfo.totalCount
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return retValue;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Extracts relevant information from the predictive search response.
|
|
171
|
+
* @param {Object} response - The response from the product-search graphql.
|
|
172
|
+
* @returns {Object} An object containing products and total number found.
|
|
173
|
+
*/
|
|
174
|
+
function processPredictiveResponse(response, options) {
|
|
175
|
+
let retValue = {
|
|
176
|
+
products: [],
|
|
177
|
+
totalNumFound: 0
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const result = response.data.predictiveSearch || {};
|
|
181
|
+
|
|
182
|
+
if (result.products && result.products.length > 0) {
|
|
183
|
+
let products = result.products;
|
|
184
|
+
const unfilteredProductCount = products.length;
|
|
185
|
+
products = processGroupByVariant(products, options);
|
|
186
|
+
|
|
187
|
+
retValue = {
|
|
188
|
+
products,
|
|
189
|
+
totalNumFound: unfilteredProductCount === result.pagination.totalCount ? products.length : result.pagination.totalCount
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return retValue;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Processes a list of products to be grouped by parent, generating a mapped product structure.
|
|
198
|
+
*
|
|
199
|
+
* @param {Array} products - The list of products to process.
|
|
200
|
+
* @returns {Array} An array of mapped products with child documents for each variant.
|
|
201
|
+
*/
|
|
202
|
+
function processGroupByParent(products, options) {
|
|
203
|
+
let mappedProducts = [];
|
|
204
|
+
|
|
205
|
+
//clean up null data (a lot exists in test environment)
|
|
206
|
+
products = products.filter((product) => {
|
|
207
|
+
if(product.error) {
|
|
208
|
+
console.log('Removed Products with error' , product.error)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return !product.error
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
products.forEach((parentProduct) => {
|
|
215
|
+
let mappedParentProduct = parentProduct;
|
|
216
|
+
|
|
217
|
+
if (!isSkuFormat(parentProduct.id) && parentProduct.variants && parentProduct.variants.length > 0) {
|
|
218
|
+
mappedParentProduct = parentProduct.variants[0];
|
|
219
|
+
} else {
|
|
220
|
+
mappedParentProduct.sku = parentProduct.id;
|
|
221
|
+
mappedParentProduct.variants = [];
|
|
222
|
+
mappedParentProduct.variants.push({ ...mappedParentProduct, sku: parentProduct.id });
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
let indexDocuments = parentProduct.variants.map((variant) => {
|
|
226
|
+
|
|
227
|
+
let orderTypes = mapOrderTypes(variant.availableChannels, variant.bundle ? variant.bundle.purchaseTypes : undefined);
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
path_exact: `product/${variant.sku}/${options.language}`,
|
|
231
|
+
sku: [`${variant.sku}`],
|
|
232
|
+
markets: [`${options.market}`],
|
|
233
|
+
variantType: [""],
|
|
234
|
+
name: [`${variant.title}`],
|
|
235
|
+
shortDescription: variant.description,
|
|
236
|
+
longDescription: variant.description,
|
|
237
|
+
searchTerms: variant.searchKeywords,
|
|
238
|
+
isExclusive: mappedParentProduct.isExclusive || "false",
|
|
239
|
+
custType: mapCustomerTypes(variant.bundle ? variant.bundle.customerTypes : variant.customerTypes),
|
|
240
|
+
statusCode: ["10"],
|
|
241
|
+
orderType: Object.keys(orderTypes).filter(key => orderTypes[key]),
|
|
242
|
+
_root_: [`product/${mappedParentProduct.sku}`]
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
let mySiteIndexDocuments = parentProduct.variants.map((variant) => {
|
|
247
|
+
|
|
248
|
+
let orderTypes = mapOrderTypes(variant.availableChannels, variant.bundle ? variant.bundle.purchaseTypes : undefined);
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
path_exact: `product/${variant.sku}/${options.market.toUpperCase()}`,
|
|
252
|
+
sku: [`${variant.sku}`],
|
|
253
|
+
searchTerms: variant.searchKeywords,
|
|
254
|
+
orderType: Object.keys(orderTypes).filter(key => orderTypes[key]),
|
|
255
|
+
custType: mapCustomerTypes(variant.bundle ? variant.bundle.customerTypes : variant.customerTypes),
|
|
256
|
+
statusCode: ["10"],
|
|
257
|
+
webEnabled: ["true"],
|
|
258
|
+
_root_: [`product/${mappedParentProduct.sku}`]
|
|
259
|
+
};
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
indexDocuments = indexDocuments.concat(mySiteIndexDocuments);
|
|
263
|
+
|
|
264
|
+
if (indexDocuments.length > 0) {
|
|
265
|
+
mappedProducts.push({
|
|
266
|
+
path_exact: `product/${mappedParentProduct.sku}`,
|
|
267
|
+
languages: [`${options.language.toLowerCase()}`],
|
|
268
|
+
markets: [`${options.market.toLowerCase()}`],
|
|
269
|
+
sku: [`${mappedParentProduct.sku}`],
|
|
270
|
+
_childDocuments_: indexDocuments
|
|
271
|
+
});
|
|
272
|
+
} else {
|
|
273
|
+
console.log('Invalid Product', mappedParentProduct);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
console.log('Products' , mappedProducts)
|
|
278
|
+
|
|
279
|
+
return mappedProducts.map((product) => {
|
|
280
|
+
baseScore -= 0.01;
|
|
281
|
+
return new SolrProductAdaptor(product, baseScore)
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Processes a list of products to be grouped by variant, generating a mapped product structure.
|
|
287
|
+
*
|
|
288
|
+
* @param {Array} products - The list of products to process.
|
|
289
|
+
* @returns {Array} An array of mapped products with a flattened structure.
|
|
290
|
+
*/
|
|
291
|
+
function processGroupByVariant(products, options) {
|
|
292
|
+
let sellableProducts = products.filter((v) => {
|
|
293
|
+
return v.status && v.status.status && (v.status.status !== 'inactive' && v.status.status !== 'discontinued');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
sellableProducts = sellableProducts.filter((v) => v !== undefined).map((product) => {
|
|
297
|
+
return {
|
|
298
|
+
sku: [product.sku],
|
|
299
|
+
fullImage: (product.productImages && product.productImages.length > 0) ? product.productImages[0].thumbnail ? product.productImages[0].thumbnail : product.productImages[0].url : '',
|
|
300
|
+
name: product.title || '',
|
|
301
|
+
_root_: `product/${product.sku}`,
|
|
302
|
+
isExclusive: product.isExclusive || "false",
|
|
303
|
+
price: product.price,
|
|
304
|
+
status: product.status
|
|
305
|
+
};
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
let exactSkuResult = sellableProducts.filter((product) => product.sku[0].toLowerCase() === options.searchTerm.toLowerCase());
|
|
309
|
+
|
|
310
|
+
if (isSkuFormat(options.searchTerm) && exactSkuResult.length > 0) {
|
|
311
|
+
sellableProducts = exactSkuResult
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return sellableProducts;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* map EQ customer types to supported product card customer types
|
|
320
|
+
* @param {Array<string>} eqCustomerTypes
|
|
321
|
+
* @returns{string} customer types
|
|
322
|
+
*/
|
|
323
|
+
function mapCustomerTypes(eqCustomerTypes) {
|
|
324
|
+
if (!eqCustomerTypes) {
|
|
325
|
+
return "";
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const custTypes = eqCustomerTypes.map(str => str.toLowerCase());
|
|
329
|
+
|
|
330
|
+
let newCustType = [];
|
|
331
|
+
if (custTypes.includes(CustomerTypes.BrandAffiliate)) {
|
|
332
|
+
newCustType.push(CustomerTypes.properties.BRAND_AFFILIATE.code);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (custTypes.includes(CustomerTypes.Retail)) {
|
|
336
|
+
newCustType.push(CustomerTypes.properties.RETAIL.code);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (custTypes.includes(CustomerTypes.Preferred) || custTypes.includes(CustomerTypes.PreferredCustomer)) {
|
|
340
|
+
newCustType.push(CustomerTypes.properties.PREFERRED.code);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return newCustType.toString().split(",")
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Map Order Types
|
|
348
|
+
* @param {Array<string>} availableChannels
|
|
349
|
+
* @param {object} purchaseTypes
|
|
350
|
+
* @returns {object} orderTypes
|
|
351
|
+
*/
|
|
352
|
+
function mapOrderTypes(availableChannels, purchaseTypes) {
|
|
353
|
+
|
|
354
|
+
let orderTypes = {
|
|
355
|
+
"adr": false,
|
|
356
|
+
"order": false,
|
|
357
|
+
"zpfc": false,
|
|
358
|
+
"zadp": false,
|
|
359
|
+
"ars": false,
|
|
360
|
+
"kiosk": false,
|
|
361
|
+
"mobile": false,
|
|
362
|
+
"preferred customer": false,
|
|
363
|
+
"retail": false,
|
|
364
|
+
"web": false,
|
|
365
|
+
"web display": false
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
if (availableChannels) {
|
|
369
|
+
let availableChannelsArr = Array.isArray(availableChannels) ? availableChannels : availableChannels.split(',');
|
|
370
|
+
|
|
371
|
+
availableChannelsArr.forEach(channel => {
|
|
372
|
+
if (channel == 'arsPhone')
|
|
373
|
+
orderTypes.ars = true
|
|
374
|
+
if (channel == 'web') {
|
|
375
|
+
orderTypes.order = true
|
|
376
|
+
orderTypes.web = true
|
|
377
|
+
}
|
|
378
|
+
if (channel == 'kiosk')
|
|
379
|
+
orderTypes.kiosk = true
|
|
380
|
+
if (channel == 'mobile')
|
|
381
|
+
orderTypes.mobile = true
|
|
382
|
+
if (channel == 'subscription')
|
|
383
|
+
orderTypes.adr = true
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (purchaseTypes && purchaseTypes.buyOnce) {
|
|
388
|
+
orderTypes.web = true
|
|
389
|
+
orderTypes.order = true
|
|
390
|
+
}
|
|
391
|
+
if (purchaseTypes && purchaseTypes.subscription) {
|
|
392
|
+
orderTypes.adr = true
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return orderTypes;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Performs a product search to the product-search graphql
|
|
401
|
+
* @param {Promise} deferred - A promise object that resolves when the search is complete.
|
|
402
|
+
* @param {Object} options - The search options including searchTerm, rows, language, market.
|
|
403
|
+
*/
|
|
404
|
+
function productSearch(deferred, options) {
|
|
405
|
+
|
|
406
|
+
let allProducts = [];
|
|
407
|
+
let currentPage = 1;
|
|
408
|
+
const variables = {
|
|
409
|
+
"language": options.language,
|
|
410
|
+
"market": options.market,
|
|
411
|
+
"sizeOpt": options.rows,
|
|
412
|
+
"pageOpt": currentPage,
|
|
413
|
+
"searchTerm": options.searchTerm
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
function fetchNextPage() {
|
|
417
|
+
sendQuery(searchQuery, variables, currentPage)
|
|
418
|
+
.then((qresp) => processSearchResponse(qresp, options))
|
|
419
|
+
.then((result) => {
|
|
420
|
+
allProducts = allProducts.concat(result.products);
|
|
421
|
+
if ((currentPage * options.rows) < result.totalNumFound) {
|
|
422
|
+
currentPage++;
|
|
423
|
+
fetchNextPage();
|
|
424
|
+
} else {
|
|
425
|
+
baseScore = 5;
|
|
426
|
+
deferred.resolve({
|
|
427
|
+
products: allProducts,
|
|
428
|
+
totalNumFound: result.totalNumFound
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
})
|
|
432
|
+
.catch((error) => {
|
|
433
|
+
console.error(error);
|
|
434
|
+
deferred.reject(error);
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
fetchNextPage();
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Performs a product search to the product-search graphql
|
|
443
|
+
* @param {Promise} deferred - A promise object that resolves when the search is complete.
|
|
444
|
+
* @param {Object} options - The search options including searchTerm, rows, language, market.
|
|
445
|
+
*/
|
|
446
|
+
function predictiveSearch(deferred, options, page) {
|
|
447
|
+
const variables = {
|
|
448
|
+
"language": options.language,
|
|
449
|
+
"market": options.market,
|
|
450
|
+
"searchTerm": options.searchTerm,
|
|
451
|
+
"page": page ? page : options.page ? options.page : 1,
|
|
452
|
+
"size": options.rows || 6
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
sendQuery(predictiveQuery, variables)
|
|
456
|
+
.then((qresult) => processPredictiveResponse(qresult, options))
|
|
457
|
+
.then((result) => {
|
|
458
|
+
deferred.resolve({
|
|
459
|
+
products: result.products,
|
|
460
|
+
totalNumFound: result.totalNumFound
|
|
461
|
+
});
|
|
462
|
+
})
|
|
463
|
+
.catch((error) => {
|
|
464
|
+
console.error(error);
|
|
465
|
+
deferred.reject(error);
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Performs multiple predictive searches to the product-search graphql to retrieve all results for the term
|
|
471
|
+
* @param {Promise} deferred - A promise object that resolves when the search is complete.
|
|
472
|
+
* @param {Object} options - The search options including searchTerm, rows, language, market.
|
|
473
|
+
*/
|
|
474
|
+
function allPredictiveSearch(deferred, options) {
|
|
475
|
+
|
|
476
|
+
let allProducts = [];
|
|
477
|
+
let currentPage = 1;
|
|
478
|
+
let variables = {
|
|
479
|
+
"language": options.language,
|
|
480
|
+
"market": options.market,
|
|
481
|
+
"searchTerm": options.searchTerm,
|
|
482
|
+
"page": currentPage,
|
|
483
|
+
"size": 50
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
function fetchNextPage() {
|
|
487
|
+
sendQuery(predictiveQuery, variables)
|
|
488
|
+
.then((qresp) => processPredictiveResponse(qresp, options))
|
|
489
|
+
.then((result) => {
|
|
490
|
+
result.products.map((product) => {
|
|
491
|
+
baseScore -= 0.01;
|
|
492
|
+
product.searchScore = baseScore
|
|
493
|
+
});
|
|
494
|
+
allProducts = allProducts.concat(result.products);
|
|
495
|
+
if ((currentPage * 6) < result.totalNumFound) {
|
|
496
|
+
currentPage++;
|
|
497
|
+
variables.page = currentPage
|
|
498
|
+
fetchNextPage();
|
|
499
|
+
} else {
|
|
500
|
+
baseScore = 5;
|
|
501
|
+
deferred.resolve({
|
|
502
|
+
products: allProducts,
|
|
503
|
+
totalNumFound: result.totalNumFound
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
})
|
|
507
|
+
.catch((error) => {
|
|
508
|
+
console.error(error);
|
|
509
|
+
deferred.reject(error);
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
fetchNextPage();
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export {
|
|
517
|
+
allPredictiveSearch,
|
|
518
|
+
predictiveSearch,
|
|
519
|
+
productSearch,
|
|
520
|
+
isSkuFormat
|
|
521
|
+
};
|
|
@@ -44,7 +44,7 @@ let productSearchService = function() {
|
|
|
44
44
|
productFields.push(ProductSearchFieldsEnum.USAGE);
|
|
45
45
|
productFields.push(ProductSearchFieldsEnum.KEY_INGREDIENTS);
|
|
46
46
|
}
|
|
47
|
-
if (typeof(limit) === "undefined"|| limit === null)
|
|
47
|
+
if (typeof(limit) === "undefined" || limit === null)
|
|
48
48
|
limit = 6;
|
|
49
49
|
if (typeof(market) === "undefined" || market === null) {
|
|
50
50
|
market = util.countryCode;
|
|
@@ -255,46 +255,60 @@ let productSearchService = function() {
|
|
|
255
255
|
let skuArray = [];
|
|
256
256
|
|
|
257
257
|
for (let i = 0; i < products.length; i++) {
|
|
258
|
-
|
|
258
|
+
if (products[i].sku && products[i].sku.length > 0) {
|
|
259
|
+
skuArray.push(products[i].sku[0]);
|
|
260
|
+
} else {
|
|
261
|
+
skuArray.push(products[i].getSku());
|
|
262
|
+
}
|
|
259
263
|
}
|
|
260
264
|
|
|
261
265
|
if (skuArray.length > 0) {
|
|
262
266
|
let productResults = [];
|
|
263
267
|
let marketChild;
|
|
268
|
+
const addProductData = (productData) => {
|
|
269
|
+
if (productData.sku && Array.isArray(productData.sku)) {
|
|
270
|
+
productData.sku = productData.sku[0]
|
|
271
|
+
}
|
|
272
|
+
let addProduct = new Product(productData);
|
|
273
|
+
|
|
274
|
+
const siteUrl = UrlService.getSiteUrl();
|
|
275
|
+
const isEdge = BrowserDetection.isEdge();
|
|
276
|
+
const isFirefox = BrowserDetection.isFirefox();
|
|
277
|
+
|
|
278
|
+
// set the base url for images, etc
|
|
279
|
+
addProduct.setBaseUrl(siteUrl);
|
|
280
|
+
|
|
281
|
+
// fix image paths for non-edge/firefox
|
|
282
|
+
if (!isEdge && !isFirefox) {
|
|
283
|
+
if (addProduct.fullImage && !addProduct.fullImage.includes("media.nuskin.com/transform")) {
|
|
284
|
+
addProduct.fullImage = addProduct.fullImage
|
|
285
|
+
? `${addProduct.fullImage.split("?")[0]}?format=pjpg`
|
|
286
|
+
: undefined;
|
|
287
|
+
addProduct.thumbnail = addProduct.thumbnail
|
|
288
|
+
? `${addProduct.thumbnail.split("?")[0]}?format=pjpg`
|
|
289
|
+
: undefined;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// set price type
|
|
294
|
+
const priceType = getCachedConfigField('showWholeSalePricing') && !AccountManager.isLoggedIn()
|
|
295
|
+
? PriceType.WWHL
|
|
296
|
+
: PriceType.RTL;
|
|
297
|
+
addProduct.setPriceAndPvFromType(priceType);
|
|
298
|
+
productResults.push(addProduct);
|
|
299
|
+
}
|
|
264
300
|
for (let i = 0; i < products.length; i++) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const siteUrl = UrlService.getSiteUrl();
|
|
273
|
-
const isEdge = BrowserDetection.isEdge();
|
|
274
|
-
const isFirefox = BrowserDetection.isFirefox();
|
|
275
|
-
|
|
276
|
-
// set the base url for images, etc
|
|
277
|
-
addProduct.setBaseUrl(siteUrl);
|
|
278
|
-
|
|
279
|
-
// fix image paths for non-edge/firefox
|
|
280
|
-
if (!isEdge && !isFirefox) {
|
|
281
|
-
if (addProduct.fullImage && !addProduct.fullImage.includes("media.nuskin.com/transform")) {
|
|
282
|
-
addProduct.fullImage = addProduct.fullImage
|
|
283
|
-
? `${addProduct.fullImage.split("?")[0]}?format=pjpg`
|
|
284
|
-
: undefined;
|
|
285
|
-
addProduct.thumbnail = addProduct.thumbnail
|
|
286
|
-
? `${addProduct.thumbnail.split("?")[0]}?format=pjpg`
|
|
287
|
-
: undefined;
|
|
288
|
-
}
|
|
301
|
+
if (products[i].getMarketChild) {
|
|
302
|
+
marketChild = products[i].getMarketChild(market);
|
|
303
|
+
if (searchedProductIsBase(products[i], productResultTypes) || (marketChild.getPurchasable() &&
|
|
304
|
+
existsInArray(marketChild.getOrderType(), orderTypes))) {
|
|
305
|
+
let productData = createDataFromSolrSearch(products[i], market, language);
|
|
306
|
+
if (productData) {
|
|
307
|
+
addProductData(productData)
|
|
289
308
|
}
|
|
290
|
-
|
|
291
|
-
// set price type
|
|
292
|
-
const priceType = getCachedConfigField('showWholeSalePricing') && !AccountManager.isLoggedIn()
|
|
293
|
-
? PriceType.WWHL
|
|
294
|
-
: PriceType.RTL;
|
|
295
|
-
addProduct.setPriceAndPvFromType(priceType);
|
|
296
|
-
productResults.push(addProduct);
|
|
297
309
|
}
|
|
310
|
+
} else {
|
|
311
|
+
addProductData(products[i])
|
|
298
312
|
}
|
|
299
313
|
}
|
|
300
314
|
productResults = sortProducts(productResults, sortOrder, productFieldAsText(sortField));
|
|
@@ -636,6 +650,28 @@ let productSearchService = function() {
|
|
|
636
650
|
}
|
|
637
651
|
}
|
|
638
652
|
|
|
653
|
+
if (basicProduct.price) {
|
|
654
|
+
productData.priceMap = {
|
|
655
|
+
RTL: basicProduct.price.retail,
|
|
656
|
+
WRTL: basicProduct.price.retail,
|
|
657
|
+
WHL: basicProduct.price.wholesale,
|
|
658
|
+
WWHL: basicProduct.price.wholesale
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
if (basicProduct.status) {
|
|
663
|
+
switch (basicProduct.status) {
|
|
664
|
+
case "discontinued":
|
|
665
|
+
case "inactive":
|
|
666
|
+
case "bundleOnly":
|
|
667
|
+
productData.status = "NOT_RELEASED_FOR_SALE"
|
|
668
|
+
break;
|
|
669
|
+
default:
|
|
670
|
+
productData.status = "RELEASED_FOR_SALE"
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
639
675
|
return new Product(productData);
|
|
640
676
|
}
|
|
641
677
|
|