@nuskin/ns-shop 7.0.1 → 7.1.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
|
@@ -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 {productSearchAPI} from "./productSearchAPIQueryService.js"
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
*
|
|
@@ -436,119 +437,136 @@ 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
|
-
|
|
470
|
-
}
|
|
444
|
+
productSearchAPI(deferred, {
|
|
445
|
+
searchTerm,
|
|
446
|
+
rows,
|
|
447
|
+
language,
|
|
448
|
+
market,
|
|
449
|
+
groupByVariant: true,
|
|
450
|
+
page: 1
|
|
451
|
+
})
|
|
471
452
|
|
|
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
|
-
}
|
|
453
|
+
} else {
|
|
454
|
+
// Search for language nodes for the given market that match the search term.
|
|
455
|
+
let queryResponsePromise = $.ajax({
|
|
456
|
+
url: solrUrl,
|
|
457
|
+
type: "GET",
|
|
458
|
+
contentType: 'application/json; charset=utf-8',
|
|
459
|
+
headers: {
|
|
460
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
461
|
+
"client_secret": getCachedConfigField('solrClientSecret')
|
|
462
|
+
},
|
|
463
|
+
timeout: SolrTimeout,
|
|
464
|
+
success: function () {
|
|
465
|
+
//console.log("Search success!");
|
|
466
|
+
},
|
|
467
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
468
|
+
deferred.reject(textStatus);
|
|
469
|
+
//console.log('Search failed!');
|
|
470
|
+
}
|
|
471
|
+
});
|
|
496
472
|
|
|
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) {
|
|
473
|
+
queryResponsePromise.then(function(responseData) {
|
|
474
|
+
let retValue;
|
|
475
|
+
let docs, totalNumFound/*, responseHeader*/;
|
|
504
476
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
477
|
+
if (typeof(responseData) === "string") {
|
|
478
|
+
docs = $.parseJSON(responseData).response.docs;
|
|
479
|
+
totalNumFound = $.parseJSON(responseData).response.numFound;
|
|
480
|
+
// responseHeader = $.parseJSON(responseData).responseHeader;
|
|
481
|
+
} else {
|
|
482
|
+
docs = responseData.response.docs;
|
|
483
|
+
totalNumFound = responseData.response.numFound;
|
|
484
|
+
// responseHeader = responseData.responseHeader;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (searchByOrderType) {
|
|
488
|
+
solrUrl = SolrQueryUrlService.getProductsByRoots(docs, language, market, rows, 0, orderTypes);
|
|
489
|
+
let _orderTypes = orderTypes;
|
|
490
|
+
if (solrUrl.url) {
|
|
491
|
+
let productDocuments = [];
|
|
492
|
+
queryResponsePromise = $.ajax({
|
|
493
|
+
url: solrUrl.url,
|
|
494
|
+
type: "POST",
|
|
495
|
+
contentType: 'application/json; charset=utf-8',
|
|
496
|
+
headers: {
|
|
497
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
498
|
+
"client_secret":getCachedConfigField('solrClientSecret')
|
|
499
|
+
},
|
|
500
|
+
timeout: SolrTimeout,
|
|
501
|
+
data: JSON.stringify(solrUrl.postData),
|
|
502
|
+
success: function (responseData) {
|
|
503
|
+
if (typeof(responseData) === "string") {
|
|
504
|
+
docs = $.parseJSON(responseData).response.docs;
|
|
505
|
+
totalNumFound = $.parseJSON(responseData).response.numFound;
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
docs = responseData.response.docs;
|
|
509
|
+
totalNumFound = responseData.response.numFound;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Wrap the products in an adaptor for ease of use.
|
|
513
|
+
for (let i = 0; i < docs.length; i++) {
|
|
514
|
+
//ONLY RETURN PRODUCTS THAT HAVE A MARKET
|
|
515
|
+
if (docs[i]._childDocuments_) {
|
|
516
|
+
for (let m = 0; m < docs[i]._childDocuments_.length; m++) {
|
|
517
|
+
if ((docs[i]._childDocuments_[m].path_exact === "product/" + docs[i].sku + '/' + market.toUpperCase()) &&
|
|
518
|
+
!docs[i]._childDocuments_[m].excludeFromSearch) {
|
|
519
|
+
|
|
520
|
+
if (!skuExistsInProductArray(productDocuments, docs[i].sku.toString())) {
|
|
521
|
+
let prodAdaptor = new SolrProductAdaptor(docs[i]);
|
|
522
|
+
let marketChild = prodAdaptor.getMarketChild(market);
|
|
523
|
+
let languageChild = prodAdaptor.getLanguageChild(language);
|
|
524
|
+
if (existsInArray(marketChild.getOrderType(), _orderTypes)) {
|
|
525
|
+
productDocuments.push({
|
|
526
|
+
sku: docs[i].sku,
|
|
527
|
+
fullImage: marketChild.getFullImageUrl(),
|
|
528
|
+
name: languageChild.getTitle(),
|
|
529
|
+
_root_: "product/" + docs[i].sku,
|
|
530
|
+
isExclusive: languageChild.getIsExclusive()
|
|
531
|
+
});
|
|
532
|
+
}
|
|
517
533
|
}
|
|
518
534
|
}
|
|
519
535
|
}
|
|
520
536
|
}
|
|
521
537
|
}
|
|
522
|
-
}
|
|
523
538
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
539
|
+
let retValue = {
|
|
540
|
+
products: productDocuments,
|
|
541
|
+
totalNumFound: totalNumFound
|
|
542
|
+
};
|
|
528
543
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
544
|
+
deferred.resolve(retValue);
|
|
545
|
+
},
|
|
546
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
547
|
+
deferred.reject(textStatus);
|
|
548
|
+
//console.log('Search failed!');
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
} else {
|
|
552
|
+
retValue = {
|
|
553
|
+
products: docs,
|
|
554
|
+
totalNumFound: totalNumFound
|
|
555
|
+
};
|
|
556
|
+
deferred.resolve(retValue);
|
|
557
|
+
}
|
|
536
558
|
} else {
|
|
537
559
|
retValue = {
|
|
538
560
|
products: docs,
|
|
539
561
|
totalNumFound: totalNumFound
|
|
540
562
|
};
|
|
563
|
+
|
|
541
564
|
deferred.resolve(retValue);
|
|
542
565
|
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
};
|
|
548
|
-
|
|
549
|
-
deferred.resolve(retValue);
|
|
550
|
-
}
|
|
551
|
-
});
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
|
|
552
570
|
|
|
553
571
|
return deferred;
|
|
554
572
|
}
|
|
@@ -573,113 +591,132 @@ let SolrQueryService = function() {
|
|
|
573
591
|
productResultType, searchTerm, productSearchFields, language, market, rows, start
|
|
574
592
|
);
|
|
575
593
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
594
|
+
const {active, MySite_search_API_Base_URLs} = getCachedConfiguration('Equinox_Markets');
|
|
595
|
+
|
|
596
|
+
if(active && MySite_search_API_Base_URLs !== '') {
|
|
597
|
+
|
|
598
|
+
productSearchAPI(deferred, {
|
|
599
|
+
searchTerm,
|
|
600
|
+
rows: 50,
|
|
601
|
+
language,
|
|
602
|
+
market,
|
|
603
|
+
page: 1
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
} else {
|
|
607
|
+
|
|
608
|
+
// Search for language nodes for the given market that match the search term.
|
|
609
|
+
let queryResponsePromise = $.ajax({
|
|
610
|
+
url: solrUrl,
|
|
611
|
+
type: "GET",
|
|
612
|
+
contentType: 'application/json; charset=utf-8',
|
|
613
|
+
headers: {
|
|
614
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
615
|
+
"client_secret": getCachedConfigField('solrClientSecret')
|
|
616
|
+
},
|
|
617
|
+
timeout: SolrTimeout,
|
|
618
|
+
success: function () {
|
|
587
619
|
//console.log("Search success!");
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
620
|
+
},
|
|
621
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
622
|
+
deferred.reject(textStatus);
|
|
591
623
|
//console.log('Search failed!');
|
|
592
|
-
|
|
593
|
-
|
|
624
|
+
}
|
|
625
|
+
});
|
|
594
626
|
|
|
595
|
-
|
|
596
|
-
|
|
627
|
+
queryResponsePromise.then(function(responseData){
|
|
628
|
+
let matchingRootProducts, totalNumFound, responseHeader;
|
|
597
629
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
630
|
+
if (typeof(responseData) === "string") {
|
|
631
|
+
matchingRootProducts = $.parseJSON(responseData).response.docs;
|
|
632
|
+
totalNumFound = $.parseJSON(responseData).response.numFound;
|
|
633
|
+
responseHeader = $.parseJSON(responseData).responseHeader;
|
|
634
|
+
} else {
|
|
635
|
+
matchingRootProducts = responseData.response.docs;
|
|
636
|
+
totalNumFound = responseData.response.numFound;
|
|
637
|
+
responseHeader = responseData.responseHeader;
|
|
638
|
+
}
|
|
607
639
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
640
|
+
// If the zkConnected header is true, we count on the data returned from the query being accurate.
|
|
641
|
+
// If it's false, we will re-try the Solr query so that we are sure we have the most up-to-date information
|
|
642
|
+
// (We only try again once, which is what sets the retrySolrRequest variable)
|
|
643
|
+
if (responseHeader.zkConnected || !retrySolrRequest) {
|
|
612
644
|
// eslint-disable-next-line
|
|
613
645
|
// 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
646
|
// 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
|
-
|
|
647
|
+
solrUrl = SolrQueryUrlService.getProductsByRoots(matchingRootProducts, language, market, rows, 0, orderTypes);
|
|
648
|
+
|
|
649
|
+
if (solrUrl.url) {
|
|
650
|
+
let productDocuments = [];
|
|
651
|
+
|
|
652
|
+
// Return the complete records for the given matches
|
|
653
|
+
queryResponsePromise = $.ajax({
|
|
654
|
+
url: solrUrl.url,
|
|
655
|
+
type: "POST",
|
|
656
|
+
contentType: 'application/json; charset=utf-8',
|
|
657
|
+
headers: {
|
|
658
|
+
"client_id": getCachedConfigField('solrClientId'),
|
|
659
|
+
"client_secret": getCachedConfigField('solrClientSecret')
|
|
660
|
+
},
|
|
661
|
+
data: JSON.stringify(solrUrl.postData),
|
|
662
|
+
timeout: SolrTimeout,
|
|
663
|
+
success: function (responseData) {
|
|
664
|
+
let docs;
|
|
665
|
+
|
|
666
|
+
if (typeof(responseData) === "string") {
|
|
667
|
+
docs = $.parseJSON(responseData).response.docs;
|
|
668
|
+
}
|
|
669
|
+
else {
|
|
670
|
+
docs = responseData.response.docs;
|
|
671
|
+
}
|
|
640
672
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
673
|
+
for (let i = 0; i < matchingRootProducts.length; i++) {
|
|
674
|
+
matchingRootProducts[i].path_exact = matchingRootProducts[i]._root_[0];
|
|
675
|
+
}
|
|
644
676
|
|
|
645
|
-
|
|
646
|
-
|
|
677
|
+
// Wrap the products in an adaptor for ease of use.
|
|
678
|
+
for (let i = 0; i < docs.length; i++) {
|
|
647
679
|
//ONLY RETURN PRODUCTS THAT HAVE A MARKET
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
680
|
+
if (docs[i]._childDocuments_) {
|
|
681
|
+
for (let m = 0; m < docs[i]._childDocuments_.length; m++) {
|
|
682
|
+
if ((docs[i]._childDocuments_[m].path_exact === "product/" + docs[i].sku + '/' + market.toUpperCase()) &&
|
|
651
683
|
!docs[i]._childDocuments_[m].excludeFromSearch) {
|
|
652
684
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
685
|
+
if (!skuExistsInSolrProductAdaptorArray(productDocuments, docs[i].sku.toString())) {
|
|
686
|
+
const match = matchingRootProducts.find(root => root.path_exact === docs[i].path_exact) || null;
|
|
687
|
+
const score = match ? match.score : 0;
|
|
688
|
+
productDocuments.push(new SolrProductAdaptor(docs[i], score));
|
|
689
|
+
}
|
|
657
690
|
}
|
|
658
691
|
}
|
|
659
692
|
}
|
|
660
693
|
}
|
|
661
|
-
}
|
|
662
694
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
695
|
+
let retValue = {
|
|
696
|
+
products: productDocuments,
|
|
697
|
+
totalNumFound: totalNumFound
|
|
698
|
+
};
|
|
667
699
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
700
|
+
deferred.resolve(retValue);
|
|
701
|
+
},
|
|
702
|
+
error: function (xmlHttpRequest, textStatus) {
|
|
703
|
+
deferred.reject(textStatus);
|
|
672
704
|
//console.log('Search failed!');
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
deferred.resolve(undefined);
|
|
710
|
+
}
|
|
711
|
+
} else {
|
|
712
|
+
getProductsBySearchFields(productResultType, searchTerm, productSearchFields, language, market, rows, start, orderTypes, deferred)
|
|
678
713
|
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
|
|
683
720
|
|
|
684
721
|
return deferred;
|
|
685
722
|
}
|
|
@@ -0,0 +1,389 @@
|
|
|
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
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {ProductSearchFieldsEnum, ProductSortOrderEnum, ProductSortTypeEnum} from "./productSearchFieldsEnum.js";
|
|
2
2
|
import {ProductResultsEnum} from "./productResultsEnum.js";
|
|
3
3
|
import {util, BrowserDetection, UrlService} from '@nuskin/ns-util';
|
|
4
|
-
import {getCachedConfigField} from "@nuskin/configuration-sdk";
|
|
4
|
+
import {getCachedConfigField, getCachedConfiguration} from "@nuskin/configuration-sdk";
|
|
5
5
|
import {AccountManager} from '@nuskin/ns-account';
|
|
6
6
|
import SolrQueryService from "./SolrQueryService.js";
|
|
7
7
|
import SynonymService from "./synonymService";
|
|
@@ -600,6 +600,8 @@ let productSearchService = function() {
|
|
|
600
600
|
const createProductFromBasicProduct = function(basicProduct) {
|
|
601
601
|
let siteUrl = UrlService.getSiteUrl();
|
|
602
602
|
let productData = {};
|
|
603
|
+
const {active, MySite_search_API_Base_URLs} = getCachedConfiguration('Equinox_Markets');
|
|
604
|
+
|
|
603
605
|
if (basicProduct.sku) {
|
|
604
606
|
if (typeof(basicProduct.sku) === 'object') {
|
|
605
607
|
productData.sku = basicProduct.sku[0];
|
|
@@ -608,6 +610,11 @@ let productSearchService = function() {
|
|
|
608
610
|
}
|
|
609
611
|
// eslint-disable-next-line
|
|
610
612
|
productData.thumbnail = siteUrl + "/content/products/" + productData.sku.substring(0,2) +"/" + productData.sku.substring(2,4) + "/" + productData.sku.substring(4,6) +"/" + productData.sku +"/_jcr_content/fullImage.img.160.160.png"
|
|
613
|
+
|
|
614
|
+
//use equinox image when using product-search-api and market is active
|
|
615
|
+
if(MySite_search_API_Base_URLs !== '' && active) {
|
|
616
|
+
productData.thumbnail = basicProduct.fullImage
|
|
617
|
+
}
|
|
611
618
|
}
|
|
612
619
|
if (basicProduct.name) {
|
|
613
620
|
if (typeof(basicProduct.name) === 'object') {
|