@nuskin/ns-shop 7.2.1-mdigi-2049.2 → 7.3.0-mdigi-897.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
|
@@ -137,7 +137,7 @@ const populateItem = (order, salesOrder, shipImmediate, includeSapItems) => {
|
|
|
137
137
|
};
|
|
138
138
|
|
|
139
139
|
const populateAttribution = (salesOrder) => {
|
|
140
|
-
const sponsorId = util.getSponsorId();
|
|
140
|
+
const sponsorId = util.getSponsorId();
|
|
141
141
|
const enableGuestCheckout = getCachedConfigField('enableGuestCheckout');
|
|
142
142
|
|
|
143
143
|
if (sponsorId) {
|
|
@@ -164,22 +164,10 @@ const populateAttribution = (salesOrder) => {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
const getDefaultShipCode = () => {
|
|
168
|
-
let defaultCode = '';
|
|
169
|
-
const useShipMethodsApi = getCachedConfigField('useShipMethodsApi')
|
|
170
|
-
if (useShipMethodsApi) {
|
|
171
|
-
const csDefaultCode = getCachedConfigField('defaultShipMethod');
|
|
172
|
-
const shipMethods = PickupUtil.getStoredShipMethods();
|
|
173
|
-
const firstSm = shipMethods.length > 0 ? shipMethods[0].Code : '';
|
|
174
|
-
defaultCode = shipMethods.find((sm) => sm.Code === csDefaultCode) ? csDefaultCode : firstSm;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return defaultCode;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
167
|
const populateShipping = (order, salesOrder) => {
|
|
181
168
|
const user = UserService.getUser();
|
|
182
|
-
const
|
|
169
|
+
const useShipMethodsApi = getCachedConfigField('useShipMethodsApi')
|
|
170
|
+
const defaultCode = useShipMethodsApi ? getCachedConfigField('defaultShipMethod') : '';
|
|
183
171
|
const method = order.selectedShippingMethod;
|
|
184
172
|
const code = method ? method.Code : defaultCode;
|
|
185
173
|
|
|
@@ -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";
|
|
@@ -604,6 +604,7 @@ let productSearchService = function() {
|
|
|
604
604
|
const createProductFromBasicProduct = function(basicProduct) {
|
|
605
605
|
let siteUrl = UrlService.getSiteUrl();
|
|
606
606
|
let productData = {};
|
|
607
|
+
const {active, MySite_search_API_Base_URLs} = getCachedConfiguration('Equinox_Markets');
|
|
607
608
|
if (basicProduct.sku) {
|
|
608
609
|
if (typeof(basicProduct.sku) === 'object') {
|
|
609
610
|
productData.sku = basicProduct.sku[0];
|
|
@@ -612,6 +613,11 @@ let productSearchService = function() {
|
|
|
612
613
|
}
|
|
613
614
|
// eslint-disable-next-line
|
|
614
615
|
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"
|
|
616
|
+
//use equinox image when using product-search-api and market is active
|
|
617
|
+
if(MySite_search_API_Base_URLs !== '' && active) {
|
|
618
|
+
productData.thumbnail = basicProduct.fullImage
|
|
619
|
+
}
|
|
620
|
+
|
|
615
621
|
}
|
|
616
622
|
if (basicProduct.name) {
|
|
617
623
|
if (typeof(basicProduct.name) === 'object') {
|
|
@@ -201,16 +201,10 @@ let PickupUtil = function() {
|
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
// if the calling code knows that loadShipMethods has finished then this
|
|
205
|
-
// function can be called directly if the calling function is not async.
|
|
206
|
-
function getStoredShipMethods() {
|
|
207
|
-
return JSON.parse((sessionStorage.getItem(SHIP_METHODS) || '[]'));
|
|
208
|
-
}
|
|
209
|
-
|
|
210
204
|
async function getShipMethods() {
|
|
211
205
|
await promise;
|
|
212
206
|
|
|
213
|
-
return
|
|
207
|
+
return JSON.parse((sessionStorage.getItem(SHIP_METHODS) || []));
|
|
214
208
|
}
|
|
215
209
|
|
|
216
210
|
async function getPickupPoints() {
|
|
@@ -227,7 +221,6 @@ let PickupUtil = function() {
|
|
|
227
221
|
markers: generateMarkers,
|
|
228
222
|
loadShipMethods,
|
|
229
223
|
getShipMethods,
|
|
230
|
-
getStoredShipMethods,
|
|
231
224
|
getPickupPoints
|
|
232
225
|
}
|
|
233
226
|
}();
|