Skip to content

Commit 79463a5

Browse files
Merge pull request #2044 from magento-panda/PANDA-FIXES-2.2
Fixed issues: - MAGETWO-71393: Incorrect catalog rule price for bundle product with custom option - MAGETWO-85518: Acceptance tests action groups for admin and customer login - MAGETWO-75840: Recently Ordered block displays only one of two products if they were bought from different store views - MAGETWO-86780: Cart rule applying to Shipping Amount.
2 parents 5e2a47f + 9cfaf5a commit 79463a5

File tree

49 files changed

+794
-192
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+794
-192
lines changed

app/code/Magento/Bundle/Pricing/Price/BundleRegularPrice.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function getAmount()
5252
if ($this->product->getPriceType() == Price::PRICE_TYPE_FIXED) {
5353
/** @var \Magento\Catalog\Pricing\Price\CustomOptionPrice $customOptionPrice */
5454
$customOptionPrice = $this->priceInfo->getPrice(CustomOptionPrice::PRICE_CODE);
55-
$price += $customOptionPrice->getCustomOptionRange(true);
55+
$price += $customOptionPrice->getCustomOptionRange(true, $this->getPriceCode());
5656
}
5757
$this->amount[$this->getValue()] = $this->calculator->getMinRegularAmount($price, $this->product);
5858
}
@@ -71,7 +71,7 @@ public function getMaximalPrice()
7171
if ($this->product->getPriceType() == Price::PRICE_TYPE_FIXED) {
7272
/** @var \Magento\Catalog\Pricing\Price\CustomOptionPrice $customOptionPrice */
7373
$customOptionPrice = $this->priceInfo->getPrice(CustomOptionPrice::PRICE_CODE);
74-
$price += $customOptionPrice->getCustomOptionRange(false);
74+
$price += $customOptionPrice->getCustomOptionRange(false, $this->getPriceCode());
7575
}
7676
$this->maximalPrice = $this->calculator->getMaxRegularAmount($price, $this->product);
7777
}

app/code/Magento/Bundle/Pricing/Price/BundleSelectionPrice.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ public function getValue()
128128
'catalog_product_get_final_price',
129129
['product' => $product, 'qty' => $this->bundleProduct->getQty()]
130130
);
131-
$value = $product->getData('final_price') * ($selectionPriceValue / 100);
131+
$price = $this->useRegularPrice ? $product->getData('price') : $product->getData('final_price');
132+
$value = $price * ($selectionPriceValue / 100);
132133
} else {
133134
// calculate price for selection type fixed
134135
$value = $this->priceCurrency->convert($selectionPriceValue);

app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleSelectionPriceTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ public function testGetValueTypeFixedWithSelectionPriceType($useRegularPrice)
201201
[
202202
['qty', null, 1],
203203
['final_price', null, 100],
204+
['price', null, 100],
204205
]
205206
)
206207
);

app/code/Magento/Catalog/Model/Product.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ public function getUpdatedAt()
610610
*
611611
* @param bool $calculate
612612
* @return void
613+
* @deprecated
613614
*/
614615
public function setPriceCalculation($calculate = true)
615616
{
@@ -1164,10 +1165,11 @@ public function setFinalPrice($price)
11641165
*/
11651166
public function getFinalPrice($qty = null)
11661167
{
1167-
if ($this->_getData('final_price') === null) {
1168-
$this->setFinalPrice($this->getPriceModel()->getFinalPrice($qty, $this));
1168+
if ($this->_calculatePrice || $this->_getData('final_price') === null) {
1169+
return $this->getPriceModel()->getFinalPrice($qty, $this);
1170+
} else {
1171+
return $this->_getData('final_price');
11691172
}
1170-
return $this->_getData('final_price');
11711173
}
11721174

11731175
/**

app/code/Magento/Catalog/Model/Product/Option/Value.php

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use Magento\Catalog\Model\Product\Option;
1313
use Magento\Framework\Model\AbstractModel;
1414
use Magento\Catalog\Pricing\Price\BasePrice;
15+
use Magento\Catalog\Pricing\Price\CustomOptionPriceCalculator;
16+
use Magento\Catalog\Pricing\Price\RegularPrice;
1517

1618
/**
1719
* Catalog product option select type model
@@ -21,6 +23,9 @@
2123
* @method \Magento\Catalog\Model\Product\Option\Value setOptionId(int $value)
2224
*
2325
* @SuppressWarnings(PHPMD.LongVariable)
26+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) - added use of constants instead of string literals:
27+
* BasePrice::PRICE_CODE - instead of 'base_price'
28+
* RegularPrice::PRICE_CODE - instead of 'regular_price'
2429
* @since 100.0.2
2530
*/
2631
class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface
@@ -61,6 +66,11 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu
6166
*/
6267
protected $_valueCollectionFactory;
6368

69+
/**
70+
* @var CustomOptionPriceCalculator
71+
*/
72+
private $customOptionPriceCalculator;
73+
6474
/**
6575
* @param \Magento\Framework\Model\Context $context
6676
* @param \Magento\Framework\Registry $registry
@@ -75,9 +85,12 @@ public function __construct(
7585
\Magento\Catalog\Model\ResourceModel\Product\Option\Value\CollectionFactory $valueCollectionFactory,
7686
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
7787
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
78-
array $data = []
88+
array $data = [],
89+
CustomOptionPriceCalculator $customOptionPriceCalculator = null
7990
) {
8091
$this->_valueCollectionFactory = $valueCollectionFactory;
92+
$this->customOptionPriceCalculator = $customOptionPriceCalculator
93+
?? \Magento\Framework\App\ObjectManager::getInstance()->get(CustomOptionPriceCalculator::class);
8194
parent::__construct(
8295
$context,
8396
$registry,
@@ -224,10 +237,8 @@ public function saveValues()
224237
*/
225238
public function getPrice($flag = false)
226239
{
227-
if ($flag && $this->getPriceType() == self::TYPE_PERCENT) {
228-
$basePrice = $this->getOption()->getProduct()->getPriceInfo()->getPrice(BasePrice::PRICE_CODE)->getValue();
229-
$price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100);
230-
return $price;
240+
if ($flag) {
241+
return $this->customOptionPriceCalculator->getOptionPriceByPriceCode($this, BasePrice::PRICE_CODE);
231242
}
232243
return $this->_getData(self::KEY_PRICE);
233244
}
@@ -239,12 +250,7 @@ public function getPrice($flag = false)
239250
*/
240251
public function getRegularPrice()
241252
{
242-
if ($this->getPriceType() == self::TYPE_PERCENT) {
243-
$basePrice = $this->getOption()->getProduct()->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue();
244-
$price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100);
245-
return $price;
246-
}
247-
return $this->_getData(self::KEY_PRICE);
253+
return $this->customOptionPriceCalculator->getOptionPriceByPriceCode($this, RegularPrice::PRICE_CODE);
248254
}
249255

250256
/**

app/code/Magento/Catalog/Pricing/Price/CustomOptionPrice.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,32 +35,42 @@ class CustomOptionPrice extends AbstractPrice implements CustomOptionPriceInterf
3535
*/
3636
protected $excludeAdjustment = null;
3737

38+
/**
39+
* @var CustomOptionPriceCalculator
40+
*/
41+
private $customOptionPriceCalculator;
42+
3843
/**
3944
* @param SaleableInterface $saleableItem
4045
* @param float $quantity
4146
* @param CalculatorInterface $calculator
4247
* @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
43-
* @param array $excludeAdjustment
48+
* @param array|null $excludeAdjustment
49+
* @param CustomOptionPriceCalculator|null $customOptionPriceCalculator
4450
*/
4551
public function __construct(
4652
SaleableInterface $saleableItem,
4753
$quantity,
4854
CalculatorInterface $calculator,
4955
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
50-
$excludeAdjustment = null
56+
$excludeAdjustment = null,
57+
CustomOptionPriceCalculator $customOptionPriceCalculator = null
5158
) {
5259
parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency);
5360
$this->excludeAdjustment = $excludeAdjustment;
61+
$this->customOptionPriceCalculator = $customOptionPriceCalculator
62+
?? \Magento\Framework\App\ObjectManager::getInstance()->get(CustomOptionPriceCalculator::class);
5463
}
5564

5665
/**
5766
* Get minimal and maximal option values
5867
*
68+
* @param string $priceCode
5969
* @return array
6070
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
6171
* @SuppressWarnings(PHPMD.NPathComplexity)
6272
*/
63-
public function getValue()
73+
public function getValue($priceCode = \Magento\Catalog\Pricing\Price\BasePrice::PRICE_CODE)
6474
{
6575
$optionValues = [];
6676
$options = $this->product->getOptions();
@@ -85,7 +95,8 @@ public function getValue()
8595
} else {
8696
/** @var $optionValue \Magento\Catalog\Model\Product\Option\Value */
8797
foreach ($optionItem->getValues() as $optionValue) {
88-
$price = $optionValue->getPrice($optionValue->getPriceType() == Value::TYPE_PERCENT);
98+
$price =
99+
$this->customOptionPriceCalculator->getOptionPriceByPriceCode($optionValue, $priceCode);
89100
if ($min === null) {
90101
$min = $price;
91102
} elseif ($price < $min) {
@@ -133,12 +144,13 @@ public function getCustomAmount($amount = null, $exclude = null, $context = [])
133144
* Return the minimal or maximal price for custom options
134145
*
135146
* @param bool $getMin
147+
* @param string $priceCode
136148
* @return float
137149
*/
138-
public function getCustomOptionRange($getMin)
150+
public function getCustomOptionRange($getMin, $priceCode = \Magento\Catalog\Pricing\Price\BasePrice::PRICE_CODE)
139151
{
140152
$optionValue = 0.;
141-
$options = $this->getValue();
153+
$options = $this->getValue($priceCode);
142154
foreach ($options as $option) {
143155
if ($getMin) {
144156
$optionValue += $option['min'];
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Pricing\Price;
7+
8+
use Magento\Catalog\Model\Product\Option\Value as ProductOptionValue;
9+
10+
/**
11+
* Calculates prices of custom options of the product.
12+
*/
13+
class CustomOptionPriceCalculator
14+
{
15+
/**
16+
* Calculates prices of custom option by code.
17+
*
18+
* Price is calculated depends on Price Code.
19+
* Existing logic was taken from methods \Magento\Catalog\Model\Product\Option\Value::(getPrice|getRegularPrice)
20+
* where $priceCode was hardcoded and changed to have dynamical approach.
21+
*
22+
* Examples of usage:
23+
* \Magento\Catalog\Pricing\Price\CustomOptionPrice::getValue
24+
* \Magento\Catalog\Model\Product\Option\Value::getPrice
25+
* \Magento\Catalog\Model\Product\Option\Value::getRegularPrice
26+
*
27+
* @param ProductOptionValue $optionValue
28+
* @param string $priceCode
29+
* @return float|int
30+
*/
31+
public function getOptionPriceByPriceCode(
32+
ProductOptionValue $optionValue,
33+
string $priceCode = BasePrice::PRICE_CODE
34+
) {
35+
if ($optionValue->getPriceType() === ProductOptionValue::TYPE_PERCENT) {
36+
$basePrice = $optionValue->getOption()->getProduct()->getPriceInfo()->getPrice($priceCode)->getValue();
37+
$price = $basePrice * ($optionValue->getData(ProductOptionValue::KEY_PRICE) / 100);
38+
return $price;
39+
}
40+
return $optionValue->getData(ProductOptionValue::KEY_PRICE);
41+
}
42+
}

app/code/Magento/Catalog/Test/Unit/Model/Product/Option/ValueTest.php

Lines changed: 34 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,32 @@ class ValueTest extends \PHPUnit\Framework\TestCase
1919
*/
2020
private $model;
2121

22+
/**
23+
* @var \Magento\Catalog\Pricing\Price\CustomOptionPriceCalculator
24+
*/
25+
private $customOptionPriceCalculatorMock;
26+
27+
protected function setUp()
28+
{
29+
$mockedResource = $this->getMockedResource();
30+
$mockedCollectionFactory = $this->getMockedValueCollectionFactory();
31+
32+
$this->customOptionPriceCalculatorMock = $this->createMock(
33+
\Magento\Catalog\Pricing\Price\CustomOptionPriceCalculator::class
34+
);
35+
36+
$helper = new ObjectManager($this);
37+
$this->model = $helper->getObject(
38+
\Magento\Catalog\Model\Product\Option\Value::class,
39+
[
40+
'resource' => $mockedResource,
41+
'valueCollectionFactory' => $mockedCollectionFactory,
42+
'customOptionPriceCalculator' => $this->customOptionPriceCalculatorMock,
43+
]
44+
);
45+
$this->model->setOption($this->getMockedOption());
46+
}
47+
2248
public function testSaveProduct()
2349
{
2450
$this->model->setValues([100])
@@ -35,11 +61,16 @@ public function testSaveProduct()
3561

3662
public function testGetPrice()
3763
{
38-
$this->model->setPrice(1000);
64+
$price = 1000;
65+
$this->model->setPrice($price);
3966
$this->model->setPriceType(Value::TYPE_PERCENT);
40-
$this->assertEquals(1000, $this->model->getPrice(false));
67+
$this->assertEquals($price, $this->model->getPrice(false));
4168

42-
$this->assertEquals(100, $this->model->getPrice(true));
69+
$percentPice = 100;
70+
$this->customOptionPriceCalculatorMock->expects($this->atLeastOnce())
71+
->method('getOptionPriceByPriceCode')
72+
->willReturn($percentPice);
73+
$this->assertEquals($percentPice, $this->model->getPrice(true));
4374
}
4475

4576
public function testGetValuesCollection()
@@ -78,23 +109,6 @@ public function testDeleteValue()
78109
$this->assertInstanceOf(\Magento\Catalog\Model\Product\Option\Value::class, $this->model->deleteValue(1));
79110
}
80111

81-
protected function setUp()
82-
{
83-
$mockedResource = $this->getMockedResource();
84-
$mockedCollectionFactory = $this->getMockedValueCollectionFactory();
85-
$mockedContext = $this->getMockedContext();
86-
$helper = new ObjectManager($this);
87-
$this->model = $helper->getObject(
88-
\Magento\Catalog\Model\Product\Option\Value::class,
89-
[
90-
'resource' => $mockedResource,
91-
'valueCollectionFactory' => $mockedCollectionFactory,
92-
'context' => $mockedContext
93-
]
94-
);
95-
$this->model->setOption($this->getMockedOption());
96-
}
97-
98112
/**
99113
* @return \Magento\Catalog\Model\ResourceModel\Product\Option\Value\CollectionFactory
100114
*/
@@ -243,61 +257,4 @@ private function getMockedResource()
243257

244258
return $mock;
245259
}
246-
247-
/**
248-
* @return \Magento\Framework\Model\Context
249-
*/
250-
private function getMockedContext()
251-
{
252-
$mockedRemoveAction = $this->getMockedRemoveAction();
253-
$mockEventManager = $this->getMockedEventManager();
254-
255-
$mockBuilder = $this->getMockBuilder(\Magento\Framework\Model\Context::class)
256-
->setMethods(['getActionValidator', 'getEventDispatcher'])
257-
->disableOriginalConstructor();
258-
$mock = $mockBuilder->getMock();
259-
260-
$mock->expects($this->any())
261-
->method('getActionValidator')
262-
->will($this->returnValue($mockedRemoveAction));
263-
264-
$mock->expects($this->any())
265-
->method('getEventDispatcher')
266-
->will($this->returnValue($mockEventManager));
267-
268-
return $mock;
269-
}
270-
271-
/**
272-
* @return RemoveAction
273-
*/
274-
private function getMockedRemoveAction()
275-
{
276-
$mockBuilder = $this->getMockBuilder(\Magento\Framework\Model\Context::class)
277-
->setMethods(['isAllowed'])
278-
->disableOriginalConstructor();
279-
$mock = $mockBuilder->getMock();
280-
281-
$mock->expects($this->any())
282-
->method('isAllowed')
283-
->will($this->returnValue(true));
284-
285-
return $mock;
286-
}
287-
288-
/**
289-
* @return \Magento\Framework\Event\ManagerInterface
290-
*/
291-
private function getMockedEventManager()
292-
{
293-
$mockBuilder = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class)
294-
->setMethods(['dispatch'])
295-
->disableOriginalConstructor();
296-
$mock = $mockBuilder->getMockForAbstractClass();
297-
298-
$mock->expects($this->any())
299-
->method('dispatch');
300-
301-
return $mock;
302-
}
303260
}

0 commit comments

Comments
 (0)