@nuskin/ns-product-lib 1.3.7

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/src/product.js ADDED
@@ -0,0 +1,803 @@
1
+ "use strict";
2
+
3
+ const { isTrue } = require("@nuskin/ns-common-lib");
4
+
5
+ const ProductUtils = require("./productUtils.js");
6
+
7
+ const Agelocme = require("./agelocme.js");
8
+ const PriceType = require("./priceType.js");
9
+ const ProductStatus = require("./productStatus.js");
10
+
11
+ const Product = function(productData) {
12
+ this.priceMap = {};
13
+ this.pvMap = {};
14
+ this.cvMap = {};
15
+ this.orderTypes = {};
16
+ this.childSkus = [];
17
+ this.custTypes = [];
18
+ this.addOns = [];
19
+ this.productCarouselImages = [];
20
+
21
+ //class variables to be used instead of getters/setters
22
+ this.globalProductID = "";
23
+ this.sku = "";
24
+ this.title = "";
25
+ this.country = "";
26
+ this.lang = "";
27
+ this.shortDescr = "";
28
+ this.longDescr = "";
29
+ this.sizeWeight = "";
30
+ this.nettoWeight = "";
31
+ this.productLabels = {};
32
+ this.count = "";
33
+ this.flavor = "";
34
+ this.shade = "";
35
+ this.size = "";
36
+ this.variantType = "";
37
+ this.variantDropdownLabel = "";
38
+ this.variantDropdownPlaceholder = "";
39
+ this.variantsLabel = "";
40
+ this.ingredients = "";
41
+ this.benefits = "";
42
+ this.usage = "";
43
+ this.resources = "";
44
+ this.contentSection = "";
45
+ this.videos = "";
46
+ this.personalOffer = false;
47
+ this.groupOffer = false;
48
+ this.scanQualified;
49
+ this.status = ProductStatus.ReleasedForSale;
50
+ this.availableQuantity = 0; // total available quantity
51
+ this.maxQuantity = 999; // max quantity allowed for purchase
52
+ this.priceType = null;
53
+ this.division = "";
54
+ this.backOrderDate = null;
55
+ this.baseSku = "";
56
+ this.variants = {};
57
+ this.eventName = null; // set if pricing is based off of an event
58
+ // Used to remember an event that was used for pricing in case ADR checkbox was clicked where
59
+ // event pricing is not available. If the event was active when the product was added then
60
+ // then the event can be used for the duration of the cart.
61
+ this.savedEventName = null;
62
+ this.salesLabel = "";
63
+ this.searchScore = 0;
64
+ this.isExclusive = false;
65
+ this.movie = "";
66
+ this.youtube = "";
67
+ this.marketAttributes = {};
68
+ this.salesEventText = "";
69
+
70
+ // agelocme stuff
71
+ this.agelocme = null; // object containing agelocme information (like code, label, name)
72
+
73
+ this.setMarketAttributes = function(productStatus) {
74
+ if (productStatus.marketAttributes) {
75
+ this.marketAttributes = productStatus.marketAttributes;
76
+ }
77
+ };
78
+
79
+ this.getAgelocmeKeyPart = function() {
80
+ let keyPart = null;
81
+ if (this.agelocme) {
82
+ keyPart =
83
+ this.agelocme.code +
84
+ "-" +
85
+ this.agelocme.label +
86
+ "-" +
87
+ this.agelocme.name;
88
+ }
89
+
90
+ return keyPart;
91
+ };
92
+
93
+ this.getHighlightedSku = function() {
94
+ let rv = this.sku;
95
+ if (this.highlightedSku) rv = this.highlightedSku;
96
+ return rv;
97
+ };
98
+
99
+ this.getProductSearchTitle = function() {
100
+ if (this.agelocme && this.agelocme.label) {
101
+ return this.agelocme.label;
102
+ }
103
+ return this.title;
104
+ };
105
+
106
+ this.getProductSearchSku = function() {
107
+ if (this.agelocme && this.agelocme.code) {
108
+ return this.agelocme.code;
109
+ }
110
+ return this.getHighlightedSku();
111
+ };
112
+
113
+ this.getDescription = function() {
114
+ let description = this.longDescr;
115
+ if (!description || description.length === 0) {
116
+ return this.shortDescr;
117
+ }
118
+ return description;
119
+ };
120
+
121
+ this.setFullImage = function(fullImage) {
122
+ if (fullImage) {
123
+ this.fullImage = fullImage.replace("http:", "https:");
124
+ } else {
125
+ this.fullImage = "";
126
+ }
127
+ };
128
+
129
+ this.getFullImage = function() {
130
+ return this.fullImage ? this.fullImage.replace("http:", "https:") : "";
131
+ };
132
+
133
+ this.setProductCarouselImages = function(productCarouselImages) {
134
+ this.productCarouselImages = productCarouselImages;
135
+ };
136
+
137
+ this.getProductCarouselImages = function() {
138
+ return this.productCarouselImages;
139
+ };
140
+
141
+ this.setImageAltText = function(altText) {
142
+ if (altText) {
143
+ this.imageAltText = altText;
144
+ } else {
145
+ this.imageAltText = this.title;
146
+ }
147
+ };
148
+
149
+ this.getImageAltText = function() {
150
+ return this.imageAltText || this.title;
151
+ };
152
+
153
+ this.setThumbnail = function(thumbnail) {
154
+ if (thumbnail) {
155
+ this.thumbnail = thumbnail.replace("http:", "https:");
156
+ } else {
157
+ this.thumbnail = "";
158
+ }
159
+ };
160
+
161
+ this.setThumbnailFromSku = function(sku) {
162
+ // WARNING: Base URL will need to be handled in the client (call setBaseUrl)
163
+ // eslint-disable-next-line max-len
164
+ // this.thumbnail = `${RunConfigService.getBaseUrl()}/content/products/${ProductUtils.getTokenizedSku(sku)}/jcr:content/fullImage.img.100.100.png`;
165
+
166
+ this.thumbnail = `/content/products/${ProductUtils.getTokenizedSku(
167
+ sku
168
+ )}/jcr:content/fullImage.img.100.100.png`;
169
+ };
170
+
171
+ this.getThumbnail = function() {
172
+ return this.thumbnail ? this.thumbnail.replace("http:", "https:") : "";
173
+ };
174
+
175
+ this.hasAvailableQuantity = function(qty = 1) {
176
+ return Math.min(this.maxQuantity, this.availableQuantity) >= qty;
177
+ };
178
+
179
+ this.setPoints = function(points) {
180
+ this.points = ensureFloatVal(points) || "";
181
+ };
182
+
183
+ this.getPointsFixed = function() {
184
+ return parseFloat(this.points).toFixed(2);
185
+ };
186
+
187
+ this.setCv = function(cv) {
188
+ this.cv = ensureFloatVal(cv) || "";
189
+ };
190
+
191
+ this.getCvFixed = function() {
192
+ return parseFloat(this.cv).toFixed(2);
193
+ };
194
+
195
+ this.setPv = function(pv) {
196
+ this.pv = ensureFloatVal(pv) || "";
197
+ };
198
+
199
+ this.getPvFixed = function() {
200
+ return parseFloat(this.pv || 0).toFixed(2);
201
+ };
202
+
203
+ this.setPrice = function(price) {
204
+ this.price = ensureFloatVal(price, true);
205
+ };
206
+
207
+ this.setFormattedPrice = function(formattedPrice) {
208
+ this.formattedPrice = formattedPrice;
209
+ };
210
+
211
+ /**
212
+ * Use to save the eventName if one exists. Added originally for when a product is
213
+ * added to the cart the event pricing needs to be remembered if toggling between
214
+ * pricetypes with event pricing and pricetype without event pricing
215
+ */
216
+ this.lockEventName = function() {
217
+ if (!this.savedEventName && this.eventName) {
218
+ this.savedEventName = this.eventName;
219
+ }
220
+ };
221
+
222
+ this.setPriceAndPvFromType = function(_priceType, _activeEvents = null) {
223
+ // WARNING: priceType needs to be handled client-side
224
+ // const priceType = ConfigService.getMarketConfig().showWholeSalePricing && !AccountManager.isLoggedIn()
225
+ // ? PriceType.WWHL
226
+ // : (_priceType ? _priceType : this.priceType),
227
+ const priceType = _priceType ? _priceType : this.priceType;
228
+ const eventPricing = getEventPricing(this, priceType, _activeEvents);
229
+
230
+ let changed = false;
231
+ if (
232
+ !this.price ||
233
+ priceType !== this.priceType ||
234
+ this.eventName !== eventPricing.eventName
235
+ ) {
236
+ this.setPrice(eventPricing.price || this.getPricing(priceType));
237
+ this.setCv(eventPricing.cv || this.getCvWithType(priceType));
238
+ this.setPv(eventPricing.pv || this.getPvWithType(priceType));
239
+ this.priceType = priceType;
240
+ this.eventName = eventPricing.eventName;
241
+ changed = true;
242
+ }
243
+
244
+ this.variantSkus().forEach((variantSku) => {
245
+ if (
246
+ this.variants[variantSku].setPriceAndPvFromType(
247
+ priceType,
248
+ _activeEvents
249
+ )
250
+ ) {
251
+ changed = true;
252
+ }
253
+ }, this);
254
+
255
+ return changed;
256
+ };
257
+
258
+ this.getPrice = function() {
259
+ return this.price ? this.price : 0;
260
+ };
261
+
262
+ this.getPriceFixed = function() {
263
+ if (typeof this.price === "number") {
264
+ return parseFloat(this.price.toFixed(2));
265
+ } else {
266
+ return this.getPrice();
267
+ }
268
+ };
269
+
270
+ this.getOriginalPrice = function() {
271
+ return this.priceType ? this.priceMap[this.priceType] : null;
272
+ };
273
+
274
+ this.addPricing = function(type, price) {
275
+ this.priceMap[type] = price;
276
+ };
277
+
278
+ this.addPricingFromStatus = function(productStatus, priceType) {
279
+ let modified = false;
280
+
281
+ if (!priceType) {
282
+ priceType = this.priceType;
283
+ }
284
+
285
+ // previous code stored sku as all caps
286
+ const productStatusSku = productStatus.SKU || productStatus.sku;
287
+ if (productStatusSku === this.sku) {
288
+ this.globalProductID = productStatus.globalProductID;
289
+ this.status = productStatus.status;
290
+ this.availableQuantity = productStatus.availableQuantity;
291
+ this.maxQuantity = productStatus.maxQuantity || 999;
292
+ if (productStatus.backordered) {
293
+ this.backOrderDate = productStatus.backorderedAvailableDate;
294
+ }
295
+ if (productStatus.price) {
296
+ this.setPoints(productStatus.price.PTS);
297
+ Object.keys(productStatus.price).forEach((priceKey) => {
298
+ this.addPricing(priceKey, productStatus.price[priceKey]);
299
+ }, this);
300
+ }
301
+ if (productStatus.psv) {
302
+ Object.keys(productStatus.psv).forEach((psvKey) => {
303
+ this.addPvWithType(psvKey, productStatus.psv[psvKey]);
304
+ }, this);
305
+ }
306
+ if (productStatus.csv) {
307
+ Object.keys(productStatus.csv).map((csvKey) => {
308
+ this.addCvWithType(csvKey, productStatus.csv[csvKey]);
309
+ }, this);
310
+ }
311
+ this.orderTypes = ProductUtils.mergeOrderTypes(this.orderTypes, productStatus.orderType);
312
+ if(productStatus.childSkus) {
313
+ this.childSkus = productStatus.childSkus;
314
+ }
315
+ this.setPriceAndPvFromType(priceType);
316
+ modified = true;
317
+ } else {
318
+ let variant = this.getVariant(productStatusSku);
319
+
320
+ if (variant) {
321
+ if (variant.addPricingFromStatus(productStatus, priceType)) {
322
+ variant.setMarketAttributes(productStatus);
323
+ updateBaseRanges(this, variant);
324
+ modified = true;
325
+ }
326
+ }
327
+ }
328
+
329
+ return modified;
330
+ };
331
+
332
+ this.addPvWithType = function(type, pv) {
333
+ this.pvMap[type] = pv;
334
+ };
335
+
336
+ this.addCvWithType = function(type, cv) {
337
+ this.cvMap[type] = cv;
338
+ };
339
+
340
+ this.getPricing = function(type) {
341
+ let retVal = null;
342
+
343
+ if (type) {
344
+ retVal = this.priceMap[type];
345
+
346
+ if (!retVal && isAdrType(type)) {
347
+ retVal = this.priceMap[getOppisiteAdrType(type)];
348
+ }
349
+ }
350
+ return retVal;
351
+ };
352
+
353
+ this.getEventPriceTypes = () => {
354
+ const eventPriceTypes = [];
355
+
356
+ Object.keys(this.priceMap).forEach(priceTypeKey => {
357
+ const eventPriceType = priceTypeKey.substring(0, priceTypeKey.indexOf(`-${this.priceType}`));
358
+
359
+ if (eventPriceType) {
360
+ eventPriceTypes.push(eventPriceType);
361
+ }
362
+ });
363
+
364
+ return eventPriceTypes;
365
+ };
366
+
367
+ this.getPvWithType = function(type) {
368
+ let rv = this.pvMap[type];
369
+ if (rv == null) {
370
+ // Assumption: we always have WWHL from the service
371
+ // default to wholesale if a PV of a particular type is not there
372
+ rv = this.pvMap[PriceType.WWHL];
373
+ }
374
+ return rv;
375
+ };
376
+
377
+ this.getCvWithType = function(type) {
378
+ let rv = this.cvMap[type];
379
+ if (rv == null) {
380
+ rv = this.cvMap[PriceType.WWHL];
381
+ }
382
+ return rv;
383
+ };
384
+
385
+ this.hasAdrOption = function() {
386
+ return this.orderTypes["adr"];
387
+ };
388
+
389
+ this.isAdrOnly = function() {
390
+ return this.hasAdrOption() && !this.hasOrderOption();
391
+ };
392
+
393
+ this.hasMultipleOrderTypes = function() {
394
+ return this.hasOrderOption() && this.hasAdrOption();
395
+ };
396
+
397
+ this.hasOrderOption = function() {
398
+ return this.orderTypes["order"];
399
+ };
400
+
401
+ this.isDistributor = function() {
402
+ return this.custTypes.includes("10");
403
+ };
404
+
405
+ this.isCustomer = function() {
406
+ return this.custTypes.includes("20");
407
+ };
408
+
409
+ this.isPreferredCustomer = function() {
410
+ return this.custTypes.includes("30");
411
+ };
412
+
413
+ this.isBase = function() {
414
+ return this.sku.substring(2, 4) === "55";
415
+ };
416
+
417
+ this.isVariant = function() {
418
+ return this.baseSku.length > 0 && this.variantSkus().length === 0;
419
+ };
420
+
421
+ this.setVariant = function(variantProduct) {
422
+ if (variantProduct && variantProduct.sku) {
423
+ this.variants[variantProduct.sku] = variantProduct;
424
+ }
425
+ };
426
+
427
+ this.getVariant = function(sku) {
428
+ return this.variants[sku];
429
+ };
430
+
431
+ this.variantSkus = function() {
432
+ return Object.keys(this.variants);
433
+ };
434
+
435
+ this.getVariantsList = function() {
436
+ return Object.values(this.variants);
437
+ };
438
+
439
+ this.getMinPrice = function() {
440
+ return this.priceMap[`min-${this.priceType}`];
441
+ };
442
+
443
+ this.getMaxPrice = function() {
444
+ return this.priceMap[`max-${this.priceType}`];
445
+ };
446
+
447
+ this.getMinPv = function() {
448
+ return this.pvMap[`min-${this.priceType}`];
449
+ };
450
+
451
+ this.getMaxPv = function() {
452
+ return this.pvMap[`max-${this.priceType}`];
453
+ };
454
+
455
+ this.toJSON = function() {
456
+ let retData = {};
457
+ retData.sku = this.sku;
458
+ retData.globalProductID = this.globalProductID;
459
+ retData.title = this.title;
460
+ retData.country = this.country;
461
+ retData.language = this.lang;
462
+ retData.shortDescr = this.shortDescr;
463
+ retData.longDescr = this.longDescr;
464
+ retData.fullImage = this.fullImage;
465
+ retData.imageAltText = this.imageAltText;
466
+ retData.productCarouselImages = this.productCarouselImages;
467
+ retData.thumbnail = this.thumbnail;
468
+ retData.ingredients = this.ingredients;
469
+ retData.benefits = this.benefits;
470
+ retData.usage = this.usage;
471
+ retData.resources = this.resources;
472
+ retData.videos = this.videos;
473
+ retData.movie = this.movie;
474
+ retData.youtube = this.youtube;
475
+ retData.salesEventText = this.salesEventText;
476
+ retData.contentSection = this.contentSection;
477
+ retData.scanQualified = this.scanQualified;
478
+ retData.availableQuantity = this.availableQuantity;
479
+ retData.maxQuantity = this.maxQuantity;
480
+ retData.points = this.points;
481
+ retData.cv = this.cv;
482
+ retData.pv = this.pv;
483
+ retData.priceType = this.priceType;
484
+ retData.price = this.price;
485
+ retData.priceMap = this.priceMap;
486
+ retData.cvMap = this.cvMap;
487
+ retData.pvMap = this.pvMap;
488
+ retData.orderTypes = this.orderTypes;
489
+ retData.childSkus = this.childSkus;
490
+ retData.custTypes = this.custTypes;
491
+ retData.division = this.division;
492
+ retData.backOrderDate = this.backOrderDate;
493
+ retData.agelocme = this.agelocme ? this.agelocme.toJSON() : null;
494
+ retData.count = this.count;
495
+ retData.flavor = this.flavor;
496
+ retData.size = this.size;
497
+ retData.shade = this.shade;
498
+ retData.status = this.status;
499
+ retData.variantType = this.variantType;
500
+ retData.variantDropdownLabel = this.variantDropdownLabel;
501
+ retData.variantDropdownPlaceholder = this.variantDropdownPlaceholder;
502
+ retData.variantsLabel = this.variantsLabel;
503
+ retData.groupOffer = this.groupOffer;
504
+ retData.personalOffer = this.personalOffer;
505
+ retData.savedEventName = this.savedEventName;
506
+ retData.salesLabel = this.salesLabel;
507
+ retData.eventName = this.eventName;
508
+ retData.sizeWeight = this.sizeWeight;
509
+ retData.nettoWeight = this.nettoWeight;
510
+ retData.productLabels = this.productLabels;
511
+ retData.variants = toVariantJSON(this.variants);
512
+ retData.searchScore = this.searchScore;
513
+ retData.isExclusive = this.isExclusive;
514
+ retData.marketAttributes = this.marketAttributes;
515
+
516
+ return retData;
517
+ };
518
+
519
+ this.setMeCommerceProductData = function(/*productData*/) {
520
+ console.error("setMeCommerceProductData is deprecated!");
521
+ };
522
+
523
+ this.setBaseUrl = function(baseUrl) {
524
+ this.thumbnail = ProductUtils.applyBaseUrl(this.thumbnail, baseUrl);
525
+ this.fullImage = ProductUtils.applyBaseUrl(this.fullImage, baseUrl);
526
+
527
+ if (this.isBase()) {
528
+ for (const variantSku in this.variants) {
529
+ const variant = this.variants[variantSku];
530
+ variant.setBaseUrl(baseUrl);
531
+ }
532
+ }
533
+ };
534
+
535
+ this.setProductData = function(productData) {
536
+ let data;
537
+
538
+ if (productData) {
539
+ if (productData instanceof Product) {
540
+ data = productData.toJSON();
541
+ } else {
542
+ data = productData;
543
+ }
544
+ if (data.sku) {
545
+ this.sku = data.sku;
546
+ }
547
+ this.globalProductID = data.globalProductID || '';
548
+ this.title = data.title;
549
+ this.country = data.country;
550
+ this.lang = data.language;
551
+ this.shortDescr = data.shortDescr;
552
+ this.longDescr = data.longDescr;
553
+ this.isExclusive = isTrue(data.isExclusive);
554
+
555
+ // WARNING: Browser Detection will need to be handled in the client
556
+ // if (!BrowserDetection.isEdge() && !BrowserDetection.isFirefox()) {
557
+ // this.fullImage = data.fullImage ? `${data.fullImage.split('?')[0]}?format=pjpg` : undefined;
558
+ // this.thumbnail = data.thumbnail ? `${data.thumbnail.split('?')[0]}?format=pjpg` : undefined;
559
+ // }
560
+ this.fullImage = data.fullImage;
561
+ this.thumbnail = data.thumbnail;
562
+ this.imageAltText = data.imageAltText;
563
+ this.productCarouselImages = data.productCarouselImages;
564
+
565
+ this.ingredients = data.ingredients;
566
+ this.benefits = data.benefits;
567
+ this.usage = data.usage;
568
+ this.resources = data.resources;
569
+ this.videos = data.videos;
570
+ this.movie = data.movie;
571
+ this.youtube = data.youtube;
572
+ this.salesEventText = data.salesEventText;
573
+ this.contentSection = data.contentSection;
574
+ this.scanQualified = data.scanQualified;
575
+ this.status = data.status ? data.status : this.status;
576
+ if (data.availableQuantity) {
577
+ this.availableQuantity = data.availableQuantity;
578
+ }
579
+ if (data.maxQuantity >= 0) {
580
+ this.maxQuantity = data.maxQuantity;
581
+ }
582
+ if (data.points) {
583
+ this.setPoints(data.points);
584
+ }
585
+ if (data.cv) {
586
+ this.setCv(data.cv);
587
+ }
588
+ if (data.pv) {
589
+ this.setPv(data.pv);
590
+ }
591
+ if (data.price) {
592
+ this.setPrice(data.price);
593
+ }
594
+ if (data.formattedPrice) {
595
+ this.setFormattedPrice(data.formattedPrice);
596
+ }
597
+ if (data.priceType) {
598
+ this.priceType = data.priceType;
599
+ }
600
+ this.count = productData.count;
601
+ this.flavor = productData.flavor;
602
+ this.size = productData.size;
603
+ this.shade = productData.shade;
604
+ this.variantType = productData.variantType;
605
+ this.variantDropdownLabel = productData.variantDropdownLabel;
606
+ this.variantDropdownPlaceholder = productData.variantDropdownPlaceholder;
607
+ this.variantsLabel = productData.variantsLabel;
608
+ this.groupOffer = productData.groupOffer;
609
+ this.personalOffer = productData.personalOffer;
610
+ this.baseSku = productData.baseSku ? productData.baseSku : "";
611
+ this.savedEventName = productData.savedEventName;
612
+ this.sizeWeight = productData.sizeWeight;
613
+ this.nettoWeight = productData.nettoWeight;
614
+ this.productLabels = productData.productLabels;
615
+ this.salesLabel = productData.salesLabel;
616
+ this.eventName = productData.eventName;
617
+ this.variants = fromVariantJSON(this, productData.variants);
618
+ this.searchScore = productData.searchScore ? productData.searchScore : 0;
619
+ this.marketAttributes = productData.marketAttributes;
620
+ this.addOns = productData.addOns || [];
621
+
622
+ if (data.priceType) {
623
+ this.addPricing(data.priceType, data.price);
624
+ this.addPvWithType(data.priceType, data.pv);
625
+ this.addCvWithType(data.priceType, data.cv);
626
+ }
627
+ this.priceMap =
628
+ data.priceMap && Object.keys(data.priceMap).length > 0
629
+ ? data.priceMap
630
+ : this.priceMap;
631
+ this.cvMap =
632
+ data.cvMap && Object.keys(data.cvMap).length > 0
633
+ ? data.cvMap
634
+ : this.cvMap;
635
+ this.pvMap =
636
+ data.pvMap && Object.keys(data.pvMap).length > 0
637
+ ? data.pvMap
638
+ : this.pvMap;
639
+ this.orderTypes = ProductUtils.mergeOrderTypes(this.orderTypes, data.orderTypes);
640
+ if(data.childSkus) {
641
+ this.childSkus = data.childSkus;
642
+ }
643
+ this.custTypes = data.custTypes || [];
644
+
645
+ this.division = data.division;
646
+ this.backOrderDate = data.backOrderDate;
647
+
648
+ if (data.agelocme) {
649
+ this.agelocme = new Agelocme(data.agelocme);
650
+ }
651
+ }
652
+ };
653
+
654
+ this.isEmpty = function() {
655
+ return (
656
+ isFieldEmpty(this.sku) &&
657
+ isFieldEmpty(this.title) &&
658
+ isFieldEmpty(this.country) &&
659
+ isFieldEmpty(this.lang) &&
660
+ isFieldEmpty(this.shortDescr) &&
661
+ isFieldEmpty(this.longDescr) &&
662
+ isFieldEmpty(this.fullImage) &&
663
+ isFieldEmpty(this.thumbnail) &&
664
+ isFieldEmpty(this.points) &&
665
+ isFieldEmpty(this.cv) &&
666
+ isFieldEmpty(this.pv) &&
667
+ Object.keys(this.priceMap).length === 0
668
+ );
669
+ };
670
+
671
+ function isAdrType(priceType) {
672
+ return (
673
+ priceType === PriceType.WADW ||
674
+ priceType === PriceType.ADW ||
675
+ priceType === PriceType.WADR ||
676
+ priceType === PriceType.ADR
677
+ );
678
+ }
679
+
680
+ function getOppisiteAdrType(priceType) {
681
+ let retVal = priceType;
682
+
683
+ switch (priceType) {
684
+ case PriceType.WADW:
685
+ retVal = PriceType.ADW;
686
+ break;
687
+ case PriceType.ADW:
688
+ retVal = PriceType.WADW;
689
+ break;
690
+ case PriceType.WADR:
691
+ retVal = PriceType.ADR;
692
+ break;
693
+ case PriceType.ADR:
694
+ retVal = PriceType.WADR;
695
+ break;
696
+ }
697
+ return retVal;
698
+ }
699
+
700
+ function toVariantJSON(variants) {
701
+ let json = {};
702
+
703
+ Object.keys(variants).forEach((sku) => {
704
+ json[sku] = variants[sku].toJSON();
705
+ });
706
+
707
+ return json;
708
+ }
709
+
710
+ function fromVariantJSON(baseProduct, variantsJson) {
711
+ let variants = {};
712
+
713
+ if (variantsJson) {
714
+ for (const variantSku of Object.keys(variantsJson)) {
715
+ const variantJson = variantsJson[variantSku];
716
+ const variant = new Product(variantJson);
717
+
718
+ variant.baseSku = baseProduct.sku;
719
+
720
+ variants[variantSku] = variant;
721
+ }
722
+ }
723
+
724
+ return variants;
725
+ }
726
+
727
+ function updateBaseRanges(scope, variant) {
728
+ Object.keys(variant.priceMap).forEach((priceType) => {
729
+ let minPriceType = `min-${priceType}`,
730
+ maxPriceType = `max-${priceType}`;
731
+
732
+ scope.priceMap[minPriceType] = Math.min(
733
+ scope.priceMap[minPriceType] || variant.priceMap[priceType],
734
+ variant.priceMap[priceType]
735
+ );
736
+ scope.priceMap[maxPriceType] = Math.max(
737
+ scope.priceMap[maxPriceType] || 0.0,
738
+ variant.priceMap[priceType]
739
+ );
740
+
741
+ scope.pvMap[minPriceType] = Math.min(
742
+ scope.pvMap[minPriceType] || variant.pvMap[priceType],
743
+ variant.pvMap[priceType]
744
+ );
745
+ scope.pvMap[maxPriceType] = Math.max(
746
+ scope.pvMap[maxPriceType] || 0.0,
747
+ variant.pvMap[priceType]
748
+ );
749
+ });
750
+ }
751
+
752
+ function ensureFloatVal(val, acceptString) {
753
+ let intVal;
754
+ if (typeof val === "number") {
755
+ intVal = val;
756
+ } else if (typeof val === "string") {
757
+ intVal = Number(val.replace(/[^0-9.]+/g, ""));
758
+ if (isNaN(intVal) && acceptString) {
759
+ intVal = val;
760
+ }
761
+ }
762
+ return intVal;
763
+ }
764
+
765
+ function isFieldEmpty(fieldValue) {
766
+ return (
767
+ fieldValue === null || fieldValue === undefined || fieldValue.length === 0
768
+ );
769
+ }
770
+
771
+ let activeEvents = [];
772
+ function getEventPricing(scope, priceType, _activeEvents = null) {
773
+ let eventNames = scope.savedEventName
774
+ ? [scope.savedEventName]
775
+ : _activeEvents || activeEvents;
776
+ let retVal = { eventName: null };
777
+
778
+ eventNames.forEach((event) => {
779
+ let _eventPriceType = `${event}-${priceType}`;
780
+
781
+ if (scope.getPricing(_eventPriceType)) {
782
+ retVal.price = scope.getPricing(_eventPriceType);
783
+ retVal.cv = scope.getCvWithType(_eventPriceType);
784
+ retVal.pv = scope.getPvWithType(_eventPriceType);
785
+ retVal.priceType = _eventPriceType;
786
+ retVal.eventName = scope.effectiveEventName = event;
787
+ }
788
+ });
789
+
790
+ return retVal;
791
+ }
792
+
793
+ // WARNING: Product events will need to be handled in the client
794
+ // $.getValue(events.salesevent.ACTIVE_EVENTS, _activeEvents => {
795
+ // if (_activeEvents) {
796
+ // activeEvents = _activeEvents;
797
+ // }
798
+ // }, true);
799
+
800
+ this.setProductData(productData);
801
+ };
802
+
803
+ module.exports = Product;