Skip to content

Commit cb363f4

Browse files
author
Sergey Semenov
committed
MAGETWO-56998: [Backport] Simple child product without a special price still shown as "was (original price)" #4442 #5097 - for 2.1
1 parent f599a3b commit cb363f4

File tree

5 files changed

+298
-1
lines changed

5 files changed

+298
-1
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ConfigurableProduct\Pricing\Render;
7+
8+
use Magento\Catalog\Pricing\Price\FinalPrice;
9+
use Magento\Catalog\Pricing\Price\RegularPrice;
10+
use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface;
11+
use Magento\Framework\Pricing\Price\PriceInterface;
12+
use Magento\Framework\Pricing\Render\RendererPool;
13+
use Magento\Framework\Pricing\SaleableInterface;
14+
use Magento\Framework\View\Element\Template\Context;
15+
16+
class FinalPriceBox extends \Magento\Catalog\Pricing\Render\FinalPriceBox
17+
{
18+
/**
19+
* @var ConfigurableOptionsProviderInterface
20+
*/
21+
private $configurableOptionsProvider;
22+
23+
/**
24+
* @param Context $context
25+
* @param SaleableInterface $saleableItem
26+
* @param PriceInterface $price
27+
* @param RendererPool $rendererPool
28+
* @param ConfigurableOptionsProviderInterface $configurableOptionsProvider
29+
* @param array $data
30+
*/
31+
public function __construct(
32+
Context $context,
33+
SaleableInterface $saleableItem,
34+
PriceInterface $price,
35+
RendererPool $rendererPool,
36+
ConfigurableOptionsProviderInterface $configurableOptionsProvider,
37+
array $data = []
38+
) {
39+
$this->configurableOptionsProvider = $configurableOptionsProvider;
40+
parent::__construct($context, $saleableItem, $price, $rendererPool, $data);
41+
}
42+
43+
/**
44+
* Define if the special price should be shown
45+
*
46+
* @return bool
47+
*/
48+
public function hasSpecialPrice()
49+
{
50+
$product = $this->getSaleableItem();
51+
foreach ($this->configurableOptionsProvider->getProducts($product) as $subProduct) {
52+
$regularPrice = $subProduct->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE)->getValue();
53+
$finalPrice = $subProduct->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue();
54+
if ($finalPrice < $regularPrice) {
55+
return true;
56+
}
57+
}
58+
return false;
59+
}
60+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ConfigurableProduct\Test\Unit\Pricing\Render;
7+
8+
use Magento\Catalog\Pricing\Price\FinalPrice;
9+
use Magento\Catalog\Pricing\Price\RegularPrice;
10+
use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface;
11+
use Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox;
12+
13+
class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase
14+
{
15+
/**
16+
* @var \Magento\Framework\View\Element\Template\Context|\PHPUnit_Framework_MockObject_MockObject
17+
*/
18+
private $context;
19+
20+
/**
21+
* @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject
22+
*/
23+
private $saleableItem;
24+
25+
/**
26+
* @var \Magento\Framework\Pricing\Price\PriceInterface|\PHPUnit_Framework_MockObject_MockObject
27+
*/
28+
private $price;
29+
30+
/**
31+
* @var \Magento\Framework\Pricing\Render\RendererPool|\PHPUnit_Framework_MockObject_MockObject
32+
*/
33+
private $rendererPool;
34+
35+
/**
36+
* @var ConfigurableOptionsProviderInterface|\PHPUnit_Framework_MockObject_MockObject
37+
*/
38+
private $configurableOptionsProvider;
39+
40+
/**
41+
* @var FinalPriceBox
42+
*/
43+
private $model;
44+
45+
protected function setUp()
46+
{
47+
$this->context = $this->getMockBuilder(\Magento\Framework\View\Element\Template\Context::class)
48+
->disableOriginalConstructor()
49+
->getMock();
50+
51+
$this->saleableItem = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
52+
->disableOriginalConstructor()
53+
->getMock();
54+
55+
$this->price = $this->getMockBuilder(\Magento\Framework\Pricing\Price\PriceInterface::class)
56+
->getMockForAbstractClass();
57+
58+
$this->rendererPool = $this->getMockBuilder(\Magento\Framework\Pricing\Render\RendererPool::class)
59+
->disableOriginalConstructor()
60+
->getMock();
61+
62+
$this->configurableOptionsProvider = $this->getMockBuilder(ConfigurableOptionsProviderInterface::class)
63+
->getMockForAbstractClass();
64+
65+
$this->model = new FinalPriceBox(
66+
$this->context,
67+
$this->saleableItem,
68+
$this->price,
69+
$this->rendererPool,
70+
$this->configurableOptionsProvider
71+
);
72+
}
73+
74+
/**
75+
* @param float $regularPrice
76+
* @param float $finalPrice
77+
* @param bool $expected
78+
* @dataProvider hasSpecialPriceDataProvider
79+
*/
80+
public function testHasSpecialPrice(
81+
$regularPrice,
82+
$finalPrice,
83+
$expected
84+
) {
85+
$priceMockOne = $this->getMockBuilder(\Magento\Framework\Pricing\Price\PriceInterface::class)
86+
->getMockForAbstractClass();
87+
88+
$priceMockOne->expects($this->once())
89+
->method('getValue')
90+
->willReturn($regularPrice);
91+
92+
$priceMockTwo = $this->getMockBuilder(\Magento\Framework\Pricing\Price\PriceInterface::class)
93+
->getMockForAbstractClass();
94+
95+
$priceMockTwo->expects($this->once())
96+
->method('getValue')
97+
->willReturn($finalPrice);
98+
99+
$priceInfoMock = $this->getMockBuilder(\Magento\Framework\Pricing\PriceInfo\Base::class)
100+
->disableOriginalConstructor()
101+
->getMock();
102+
103+
$priceInfoMock->expects($this->exactly(2))
104+
->method('getPrice')
105+
->willReturnMap([
106+
[RegularPrice::PRICE_CODE, $priceMockOne],
107+
[FinalPrice::PRICE_CODE, $priceMockTwo],
108+
]);
109+
110+
$productMock = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class)
111+
->setMethods(['getPriceInfo'])
112+
->getMockForAbstractClass();
113+
114+
$productMock->expects($this->exactly(2))
115+
->method('getPriceInfo')
116+
->willReturn($priceInfoMock);
117+
118+
$this->configurableOptionsProvider->expects($this->once())
119+
->method('getProducts')
120+
->with($this->saleableItem)
121+
->willReturn([$productMock]);
122+
123+
$this->assertEquals($expected, $this->model->hasSpecialPrice());
124+
}
125+
126+
/**
127+
* @return array
128+
*/
129+
public function hasSpecialPriceDataProvider()
130+
{
131+
return [
132+
[10., 20., false],
133+
[10., 10., false],
134+
[20., 10., true],
135+
];
136+
}
137+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
9+
<referenceBlock name="render.product.prices">
10+
<arguments>
11+
<argument name="configurable" xsi:type="array">
12+
<item name="prices" xsi:type="array">
13+
<item name="final_price" xsi:type="array">
14+
<item name="render_class" xsi:type="string">Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox</item>
15+
<item name="render_template" xsi:type="string">Magento_ConfigurableProduct::product/price/final_price.phtml</item>
16+
</item>
17+
</item>
18+
</argument>
19+
</arguments>
20+
</referenceBlock>
21+
</layout>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
// @codingStandardsIgnoreFile
8+
9+
?>
10+
11+
<?php
12+
/** @var \Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox$block */
13+
14+
/** @var \Magento\Framework\Pricing\Price\PriceInterface $priceModel */
15+
$priceModel = $block->getPriceType('regular_price');
16+
17+
/** @var \Magento\Framework\Pricing\Price\PriceInterface $finalPriceModel */
18+
$finalPriceModel = $block->getPriceType('final_price');
19+
$idSuffix = $block->getIdSuffix() ? $block->getIdSuffix() : '';
20+
$schema = ($block->getZone() == 'item_view') ? true : false;
21+
?>
22+
<?php if ($block->hasSpecialPrice()): ?>
23+
<span class="special-price">
24+
<?php /* @escapeNotVerified */ echo $block->renderAmount($finalPriceModel->getAmount(), [
25+
'display_label' => __('Special Price'),
26+
'price_id' => $block->getPriceId('product-price-' . $idSuffix),
27+
'price_type' => 'finalPrice',
28+
'include_container' => true,
29+
'schema' => $schema
30+
]); ?>
31+
</span>
32+
<span class="old-price no-display">
33+
<?php /* @escapeNotVerified */ echo $block->renderAmount($priceModel->getAmount(), [
34+
'display_label' => __('Regular Price'),
35+
'price_id' => $block->getPriceId('old-price-' . $idSuffix),
36+
'price_type' => 'oldPrice',
37+
'include_container' => true,
38+
'skip_adjustments' => true
39+
]); ?>
40+
</span>
41+
<?php else: ?>
42+
<?php /* @escapeNotVerified */ echo $block->renderAmount($finalPriceModel->getAmount(), [
43+
'price_id' => $block->getPriceId('product-price-' . $idSuffix),
44+
'price_type' => 'finalPrice',
45+
'include_container' => true,
46+
'schema' => $schema
47+
]); ?>
48+
<?php endif; ?>
49+
50+
<?php if ($block->showMinimalPrice()): ?>
51+
<?php if ($block->getUseLinkForAsLowAs()):?>
52+
<a href="<?php /* @escapeNotVerified */ echo $block->getSaleableItem()->getProductUrl(); ?>" class="minimal-price-link">
53+
<?php /* @escapeNotVerified */ echo $block->renderAmountMinimal(); ?>
54+
</a>
55+
<?php else:?>
56+
<span class="minimal-price-link">
57+
<?php /* @escapeNotVerified */ echo $block->renderAmountMinimal(); ?>
58+
</span>
59+
<?php endif?>
60+
<?php endif; ?>

app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ define([
2828
'<% } %>',
2929
mediaGallerySelector: '[data-gallery-role=gallery-placeholder]',
3030
mediaGalleryInitial: null,
31+
regularPriceSelector: '.old-price',
3132
onlyMainImg: false
3233
},
3334

@@ -246,6 +247,7 @@ define([
246247
this._resetChildren(element);
247248
}
248249
this._reloadPrice();
250+
this._displayRegularPriceBlock(this.simpleProduct);
249251
this._changeProductImage();
250252
},
251253

@@ -442,7 +444,7 @@ define([
442444
},
443445

444446
/**
445-
* Returns pracies for configured products
447+
* Returns prices for configured products
446448
*
447449
* @param {*} config - Products configuration
448450
* @returns {*}
@@ -485,6 +487,23 @@ define([
485487
undefined :
486488
_.first(config.allowedProducts);
487489

490+
},
491+
492+
/**
493+
* Show or hide regular price block
494+
*
495+
* @param {*} optionId
496+
* @private
497+
*/
498+
_displayRegularPriceBlock: function (optionId) {
499+
if (typeof optionId != 'undefined'
500+
&& this.options.spConfig.optionPrices[optionId].oldPrice.amount
501+
!= this.options.spConfig.optionPrices[optionId].finalPrice.amount
502+
) {
503+
$(this.options.regularPriceSelector).show();
504+
} else {
505+
$(this.options.regularPriceSelector).hide();
506+
}
488507
}
489508

490509
});

0 commit comments

Comments
 (0)