Skip to content

Commit 76e7f9a

Browse files
authored
CIF-1196 - Update pricing information on product component (#194)
* CIF-1226 - Update Product Filters in Components for Magento 2.3.4 Schema * CIF-1196 - Add new prices to product query * CIF-1196 - Add advanced pricing information to sling model * CIF-1196 - Update client-side price fetching * CIF-1196 - Update tests * CIF-1196 - Update tests
1 parent e96d6ea commit 76e7f9a

File tree

16 files changed

+1012
-220
lines changed

16 files changed

+1012
-220
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*******************************************************************************
2+
*
3+
* Copyright 2020 Adobe. All rights reserved.
4+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License. You may obtain a copy
6+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software distributed under
9+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
10+
* OF ANY KIND, either express or implied. See the License for the specific language
11+
* governing permissions and limitations under the License.
12+
*
13+
******************************************************************************/
14+
15+
package com.adobe.cq.commerce.core.components.internal.models.v1.product;
16+
17+
import java.math.BigDecimal;
18+
import java.text.NumberFormat;
19+
import java.util.Locale;
20+
21+
import com.adobe.cq.commerce.core.components.internal.models.v1.Utils;
22+
import com.adobe.cq.commerce.core.components.models.product.Price;
23+
import com.adobe.cq.commerce.magento.graphql.PriceRange;
24+
25+
public class PriceImpl implements Price {
26+
27+
private NumberFormat priceFormatter;
28+
29+
private Locale locale;
30+
31+
private String currency;
32+
33+
private Double regularPriceMin;
34+
private Double regularPriceMax;
35+
36+
private Double finalPriceMin;
37+
private Double finalPriceMax;
38+
39+
private Double discountAmountMin;
40+
private Double discountAmountMax;
41+
42+
private Double discountPercentMin;
43+
private Double discountPercentMax;
44+
45+
private Boolean isDiscounted;
46+
private Boolean isRange;
47+
48+
public PriceImpl(PriceRange range, Locale locale) {
49+
this.locale = locale;
50+
this.currency = range.getMinimumPrice().getFinalPrice().getCurrency().toString();
51+
52+
this.regularPriceMin = range.getMinimumPrice().getRegularPrice().getValue();
53+
this.finalPriceMin = range.getMinimumPrice().getFinalPrice().getValue();
54+
this.discountAmountMin = range.getMinimumPrice().getDiscount().getAmountOff();
55+
this.discountPercentMin = range.getMinimumPrice().getDiscount().getPercentOff();
56+
57+
if (range.getMaximumPrice() != null) {
58+
this.regularPriceMax = range.getMaximumPrice().getRegularPrice().getValue();
59+
this.finalPriceMax = range.getMaximumPrice().getFinalPrice().getValue();
60+
this.discountAmountMax = range.getMaximumPrice().getDiscount().getAmountOff();
61+
this.discountPercentMax = range.getMaximumPrice().getDiscount().getPercentOff();
62+
}
63+
}
64+
65+
private NumberFormat getPriceFormatter() {
66+
if (priceFormatter == null) {
67+
priceFormatter = Utils.buildPriceFormatter(locale, currency);
68+
}
69+
return priceFormatter;
70+
}
71+
72+
@Override
73+
public Boolean isRange() {
74+
if (isRange == null) {
75+
isRange = finalPriceMin != null && finalPriceMax != null && new BigDecimal(finalPriceMin).compareTo(new BigDecimal(
76+
finalPriceMax)) != 0;
77+
}
78+
return isRange;
79+
}
80+
81+
@Override
82+
public Boolean isDiscounted() {
83+
if (isDiscounted == null) {
84+
// discountAmountMin > 0
85+
isDiscounted = discountAmountMin != null && BigDecimal.ZERO.compareTo(new BigDecimal(discountAmountMin)) < 0;
86+
}
87+
88+
return isDiscounted;
89+
}
90+
91+
@Override
92+
public String getCurrency() {
93+
return currency;
94+
}
95+
96+
@Override
97+
public Double getRegularPrice() {
98+
return regularPriceMin;
99+
}
100+
101+
@Override
102+
public String getFormattedRegularPrice() {
103+
return getPriceFormatter().format(regularPriceMin);
104+
}
105+
106+
@Override
107+
public Double getFinalPrice() {
108+
return finalPriceMin;
109+
}
110+
111+
@Override
112+
public String getFormattedFinalPrice() {
113+
return getPriceFormatter().format(finalPriceMin);
114+
}
115+
116+
@Override
117+
public Double getDiscountAmount() {
118+
return discountAmountMin;
119+
}
120+
121+
@Override
122+
public String getFormattedDiscountAmount() {
123+
return getPriceFormatter().format(discountAmountMin);
124+
}
125+
126+
@Override
127+
public Double getDiscountPercent() {
128+
return discountPercentMin;
129+
}
130+
131+
@Override
132+
public Double getRegularPriceMax() {
133+
return isRange() ? regularPriceMax : Double.NaN;
134+
}
135+
136+
@Override
137+
public String getFormattedRegularPriceMax() {
138+
return isRange() ? getPriceFormatter().format(regularPriceMax) : "";
139+
}
140+
141+
@Override
142+
public Double getFinalPriceMax() {
143+
return isRange() ? finalPriceMax : Double.NaN;
144+
}
145+
146+
@Override
147+
public String getFormattedFinalPriceMax() {
148+
return isRange() ? getPriceFormatter().format(finalPriceMax) : "";
149+
}
150+
151+
@Override
152+
public Double getDiscountAmountMax() {
153+
return isRange() ? discountAmountMax : Double.NaN;
154+
}
155+
156+
@Override
157+
public String getFormattedDiscountAmountMax() {
158+
return isRange() ? getPriceFormatter().format(discountAmountMax) : "";
159+
}
160+
161+
@Override
162+
public Double getDiscountPercentMax() {
163+
return isRange() ? discountPercentMax : Double.NaN;
164+
}
165+
166+
}

bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/models/v1/product/ProductImpl.java

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package com.adobe.cq.commerce.core.components.internal.models.v1.product;
1616

1717
import java.io.IOException;
18-
import java.text.NumberFormat;
1918
import java.util.ArrayList;
2019
import java.util.Collections;
2120
import java.util.Comparator;
@@ -38,8 +37,8 @@
3837
import org.slf4j.LoggerFactory;
3938

4039
import com.adobe.cq.commerce.core.components.client.MagentoGraphqlClient;
41-
import com.adobe.cq.commerce.core.components.internal.models.v1.Utils;
4240
import com.adobe.cq.commerce.core.components.models.product.Asset;
41+
import com.adobe.cq.commerce.core.components.models.product.Price;
4342
import com.adobe.cq.commerce.core.components.models.product.Product;
4443
import com.adobe.cq.commerce.core.components.models.product.Variant;
4544
import com.adobe.cq.commerce.core.components.models.product.VariantAttribute;
@@ -96,17 +95,20 @@ public class ProductImpl implements Product {
9695
@Inject
9796
private XSSAPI xssApi;
9897

99-
private NumberFormat priceFormatter;
10098
private Boolean configurable;
10199
private Boolean loadClientPrice;
102100

103101
private AbstractProductRetriever productRetriever;
104102

103+
private Locale locale;
104+
105105
@PostConstruct
106106
private void initModel() {
107107
// Parse slug from URL
108108
String slug = parseProductSlug();
109109

110+
locale = currentPage.getLanguage(false);
111+
110112
// Get MagentoGraphqlClient from the resource.
111113
MagentoGraphqlClient magentoGraphqlClient = MagentoGraphqlClient.create(resource);
112114

@@ -147,12 +149,17 @@ public String getSku() {
147149

148150
@Override
149151
public String getCurrency() {
150-
return productRetriever.fetchProduct().getPrice().getRegularPrice().getAmount().getCurrency().toString();
152+
return getPriceRange().getCurrency();
151153
}
152154

153155
@Override
154156
public Double getPrice() {
155-
return productRetriever.fetchProduct().getPrice().getRegularPrice().getAmount().getValue();
157+
return getPriceRange().getFinalPrice();
158+
}
159+
160+
@Override
161+
public Price getPriceRange() {
162+
return new PriceImpl(productRetriever.fetchProduct().getPriceRange(), locale);
156163
}
157164

158165
@Override
@@ -233,7 +240,7 @@ public Boolean loadClientPrice() {
233240

234241
@Override
235242
public String getFormattedPrice() {
236-
return getPriceFormatter().format(getPrice());
243+
return getPriceRange().getFormattedFinalPrice();
237244
}
238245

239246
@Override
@@ -242,7 +249,6 @@ public AbstractProductRetriever getProductRetriever() {
242249
}
243250

244251
/* --- Mapping methods --- */
245-
246252
private Variant mapVariant(ConfigurableVariant variant) {
247253
SimpleProduct product = variant.getProduct();
248254

@@ -251,9 +257,7 @@ private Variant mapVariant(ConfigurableVariant variant) {
251257
productVariant.setDescription(safeDescription(product));
252258
productVariant.setSku(product.getSku());
253259
productVariant.setColor(product.getColor());
254-
productVariant.setCurrency(product.getPrice().getRegularPrice().getAmount().getCurrency().toString());
255-
productVariant.setPrice(product.getPrice().getRegularPrice().getAmount().getValue());
256-
productVariant.setFormattedPrice(getPriceFormatter().format(productVariant.getPrice()));
260+
productVariant.setPriceRange(new PriceImpl(product.getPriceRange(), locale));
257261
productVariant.setInStock(ProductStockStatus.IN_STOCK.equals(product.getStockStatus()));
258262

259263
// Map variant attributes
@@ -322,17 +326,6 @@ private String parseProductSlug() {
322326
return request.getRequestPathInfo().getSelectorString();
323327
}
324328

325-
private NumberFormat getPriceFormatter() {
326-
if (priceFormatter == null) {
327-
// Initialize NumberFormatter with locale from current page.
328-
// Alternatively, the locale can potentially be retrieved via
329-
// the storeConfig query introduced with Magento 2.3.1
330-
Locale locale = currentPage.getLanguage(false);
331-
priceFormatter = Utils.buildPriceFormatter(locale, productRetriever.fetchProduct() != null ? getCurrency() : null);
332-
}
333-
return priceFormatter;
334-
}
335-
336329
private String safeDescription(ProductInterface product) {
337330
ComplexTextValue description = product.getDescription();
338331
if (description == null) {

bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/models/v1/product/ProductRetriever.java

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import com.adobe.cq.commerce.magento.graphql.ProductAttributeFilterInput;
2525
import com.adobe.cq.commerce.magento.graphql.ProductInterface;
2626
import com.adobe.cq.commerce.magento.graphql.ProductInterfaceQueryDefinition;
27-
import com.adobe.cq.commerce.magento.graphql.ProductPricesQueryDefinition;
27+
import com.adobe.cq.commerce.magento.graphql.ProductPriceQueryDefinition;
2828
import com.adobe.cq.commerce.magento.graphql.ProductsQueryDefinition;
2929
import com.adobe.cq.commerce.magento.graphql.Query;
3030
import com.adobe.cq.commerce.magento.graphql.QueryQuery;
@@ -71,12 +71,17 @@ protected String generateQuery(String slug) {
7171
.storeConfig(generateStoreConfigQuery())).toString();
7272
}
7373

74-
private ProductPricesQueryDefinition generatePriceQuery() {
74+
private ProductPriceQueryDefinition generatePriceQuery() {
7575
return q -> q
76-
.regularPrice(rp -> rp
77-
.amount(a -> a
78-
.currency()
79-
.value()));
76+
.regularPrice(r -> r
77+
.value()
78+
.currency())
79+
.finalPrice(f -> f
80+
.value()
81+
.currency())
82+
.discount(d -> d
83+
.amountOff()
84+
.percentOff());
8085
}
8186

8287
private SimpleProductQueryDefinition generateSimpleProductQuery() {
@@ -89,7 +94,8 @@ private SimpleProductQueryDefinition generateSimpleProductQuery() {
8994
.urlKey()
9095
.stockStatus()
9196
.color()
92-
.price(generatePriceQuery())
97+
.priceRange(r -> r
98+
.minimumPrice(generatePriceQuery()))
9399
.mediaGalleryEntries(g -> g
94100
.disabled()
95101
.file()
@@ -114,14 +120,16 @@ protected ProductInterfaceQueryDefinition generateProductQuery() {
114120
.thumbnail(t -> t.label().url())
115121
.urlKey()
116122
.stockStatus()
117-
.price(generatePriceQuery())
118123
.mediaGalleryEntries(g -> g
119124
.disabled()
120125
.file()
121126
.label()
122127
.position()
123128
.mediaType())
124129
.onConfigurableProduct(cp -> cp
130+
.priceRange(r -> r
131+
.maximumPrice(generatePriceQuery())
132+
.minimumPrice(generatePriceQuery()))
125133
.configurableOptions(o -> o
126134
.label()
127135
.attributeCode()
@@ -132,7 +140,10 @@ protected ProductInterfaceQueryDefinition generateProductQuery() {
132140
.attributes(a -> a
133141
.code()
134142
.valueIndex())
135-
.product(generateSimpleProductQuery())));
143+
.product(generateSimpleProductQuery())))
144+
.onSimpleProduct(sp -> sp
145+
.priceRange(r -> r
146+
.minimumPrice(generatePriceQuery())));
136147

137148
// Apply product query hook
138149
if (productQueryHook != null) {

0 commit comments

Comments
 (0)