@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/ns-shop",
3
- "version": "7.0.1",
3
+ "version": "7.1.0-brw-988.1",
4
4
  "description": "The description that will amaze and astound your audience when they read it",
5
5
  "main": "src/shop.js",
6
6
  "scripts": {
@@ -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
- // Search for language nodes for the given market that match the search term.
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
- queryResponsePromise.then(function(responseData) {
459
- let retValue;
460
- let docs, totalNumFound/*, responseHeader*/;
442
+ if(active && MySite_search_API_Base_URLs !== '') {
461
443
 
462
- if (typeof(responseData) === "string") {
463
- docs = $.parseJSON(responseData).response.docs;
464
- totalNumFound = $.parseJSON(responseData).response.numFound;
465
- // responseHeader = $.parseJSON(responseData).responseHeader;
466
- } else {
467
- docs = responseData.response.docs;
468
- totalNumFound = responseData.response.numFound;
469
- // responseHeader = responseData.responseHeader;
470
- }
444
+ productSearchAPI(deferred, {
445
+ searchTerm,
446
+ rows,
447
+ language,
448
+ market,
449
+ groupByVariant: true,
450
+ page: 1
451
+ })
471
452
 
472
- if (searchByOrderType) {
473
- solrUrl = SolrQueryUrlService.getProductsByRoots(docs, language, market, rows, 0, orderTypes);
474
- let _orderTypes = orderTypes;
475
- if (solrUrl.url) {
476
- let productDocuments = [];
477
- queryResponsePromise = $.ajax({
478
- url: solrUrl.url,
479
- type: "POST",
480
- contentType: 'application/json; charset=utf-8',
481
- headers: {
482
- "client_id": getCachedConfigField('solrClientId'),
483
- "client_secret":getCachedConfigField('solrClientSecret')
484
- },
485
- timeout: SolrTimeout,
486
- data: JSON.stringify(solrUrl.postData),
487
- success: function (responseData) {
488
- if (typeof(responseData) === "string") {
489
- docs = $.parseJSON(responseData).response.docs;
490
- totalNumFound = $.parseJSON(responseData).response.numFound;
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
- // Wrap the products in an adaptor for ease of use.
498
- for (let i = 0; i < docs.length; i++) {
499
- //ONLY RETURN PRODUCTS THAT HAVE A MARKET
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
- if (!skuExistsInProductArray(productDocuments, docs[i].sku.toString())) {
506
- let prodAdaptor = new SolrProductAdaptor(docs[i]);
507
- let marketChild = prodAdaptor.getMarketChild(market);
508
- let languageChild = prodAdaptor.getLanguageChild(language);
509
- if (existsInArray(marketChild.getOrderType(), _orderTypes)) {
510
- productDocuments.push({
511
- sku: docs[i].sku,
512
- fullImage: marketChild.getFullImageUrl(),
513
- name: languageChild.getTitle(),
514
- _root_: "product/" + docs[i].sku,
515
- isExclusive: languageChild.getIsExclusive()
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
- let retValue = {
525
- products: productDocuments,
526
- totalNumFound: totalNumFound
527
- };
539
+ let retValue = {
540
+ products: productDocuments,
541
+ totalNumFound: totalNumFound
542
+ };
528
543
 
529
- deferred.resolve(retValue);
530
- },
531
- error: function (xmlHttpRequest, textStatus) {
532
- deferred.reject(textStatus);
533
- //console.log('Search failed!');
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
- } else {
544
- retValue = {
545
- products: docs,
546
- totalNumFound: totalNumFound
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
- // Search for language nodes for the given market that match the search term.
577
- let queryResponsePromise = $.ajax({
578
- url: solrUrl,
579
- type: "GET",
580
- contentType: 'application/json; charset=utf-8',
581
- headers: {
582
- "client_id": getCachedConfigField('solrClientId'),
583
- "client_secret": getCachedConfigField('solrClientSecret')
584
- },
585
- timeout: SolrTimeout,
586
- success: function () {
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
- error: function (xmlHttpRequest, textStatus) {
590
- deferred.reject(textStatus);
620
+ },
621
+ error: function (xmlHttpRequest, textStatus) {
622
+ deferred.reject(textStatus);
591
623
  //console.log('Search failed!');
592
- }
593
- });
624
+ }
625
+ });
594
626
 
595
- queryResponsePromise.then(function(responseData){
596
- let matchingRootProducts, totalNumFound, responseHeader;
627
+ queryResponsePromise.then(function(responseData){
628
+ let matchingRootProducts, totalNumFound, responseHeader;
597
629
 
598
- if (typeof(responseData) === "string") {
599
- matchingRootProducts = $.parseJSON(responseData).response.docs;
600
- totalNumFound = $.parseJSON(responseData).response.numFound;
601
- responseHeader = $.parseJSON(responseData).responseHeader;
602
- } else {
603
- matchingRootProducts = responseData.response.docs;
604
- totalNumFound = responseData.response.numFound;
605
- responseHeader = responseData.responseHeader;
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
- // If the zkConnected header is true, we count on the data returned from the query being accurate.
609
- // If it's false, we will re-try the Solr query so that we are sure we have the most up-to-date information
610
- // (We only try again once, which is what sets the retrySolrRequest variable)
611
- if (responseHeader.zkConnected || !retrySolrRequest) {
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
- solrUrl = SolrQueryUrlService.getProductsByRoots(matchingRootProducts, language, market, rows, 0, orderTypes);
616
-
617
- if (solrUrl.url) {
618
- let productDocuments = [];
619
-
620
- // Return the complete records for the given matches
621
- queryResponsePromise = $.ajax({
622
- url: solrUrl.url,
623
- type: "POST",
624
- contentType: 'application/json; charset=utf-8',
625
- headers: {
626
- "client_id": getCachedConfigField('solrClientId'),
627
- "client_secret": getCachedConfigField('solrClientSecret')
628
- },
629
- data: JSON.stringify(solrUrl.postData),
630
- timeout: SolrTimeout,
631
- success: function (responseData) {
632
- let docs;
633
-
634
- if (typeof(responseData) === "string") {
635
- docs = $.parseJSON(responseData).response.docs;
636
- }
637
- else {
638
- docs = responseData.response.docs;
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
- for (let i = 0; i < matchingRootProducts.length; i++) {
642
- matchingRootProducts[i].path_exact = matchingRootProducts[i]._root_[0];
643
- }
673
+ for (let i = 0; i < matchingRootProducts.length; i++) {
674
+ matchingRootProducts[i].path_exact = matchingRootProducts[i]._root_[0];
675
+ }
644
676
 
645
- // Wrap the products in an adaptor for ease of use.
646
- for (let i = 0; i < docs.length; i++) {
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
- if (docs[i]._childDocuments_) {
649
- for (let m = 0; m < docs[i]._childDocuments_.length; m++) {
650
- if ((docs[i]._childDocuments_[m].path_exact === "product/" + docs[i].sku + '/' + market.toUpperCase()) &&
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
- if (!skuExistsInSolrProductAdaptorArray(productDocuments, docs[i].sku.toString())) {
654
- const match = matchingRootProducts.find(root => root.path_exact === docs[i].path_exact) || null;
655
- const score = match ? match.score : 0;
656
- productDocuments.push(new SolrProductAdaptor(docs[i], score));
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
- let retValue = {
664
- products: productDocuments,
665
- totalNumFound: totalNumFound
666
- };
695
+ let retValue = {
696
+ products: productDocuments,
697
+ totalNumFound: totalNumFound
698
+ };
667
699
 
668
- deferred.resolve(retValue);
669
- },
670
- error: function (xmlHttpRequest, textStatus) {
671
- deferred.reject(textStatus);
700
+ deferred.resolve(retValue);
701
+ },
702
+ error: function (xmlHttpRequest, textStatus) {
703
+ deferred.reject(textStatus);
672
704
  //console.log('Search failed!');
673
- }
674
- });
675
- }
676
- else {
677
- deferred.resolve(undefined);
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
- } else {
680
- getProductsBySearchFields(productResultType, searchTerm, productSearchFields, language, market, rows, start, orderTypes, deferred)
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') {