Skip to content

Commit 27f2d9d

Browse files
committed
MC-35065: Catalog pricerules are not working with custom options as expected in Magento 2.3.0 product details page
1 parent 70223c0 commit 27f2d9d

File tree

2 files changed

+112
-3
lines changed

2 files changed

+112
-3
lines changed

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Magento\Catalog\Model\Product\Option;
1111
use Magento\Framework\Model\AbstractModel;
1212
use Magento\Catalog\Pricing\Price\BasePrice;
13+
use Magento\Catalog\Pricing\Price\CalculateCustomOptionCatalogRule;
14+
use Magento\Framework\App\ObjectManager;
1315
use Magento\Catalog\Pricing\Price\CustomOptionPriceCalculator;
1416
use Magento\Catalog\Pricing\Price\RegularPrice;
1517

@@ -69,6 +71,11 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu
6971
*/
7072
private $customOptionPriceCalculator;
7173

74+
/**
75+
* @var CalculateCustomOptionCatalogRule
76+
*/
77+
private $calculateCustomOptionCatalogRule;
78+
7279
/**
7380
* @param \Magento\Framework\Model\Context $context
7481
* @param \Magento\Framework\Registry $registry
@@ -77,6 +84,7 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu
7784
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
7885
* @param array $data
7986
* @param CustomOptionPriceCalculator|null $customOptionPriceCalculator
87+
* @param CalculateCustomOptionCatalogRule|null $CalculateCustomOptionCatalogRule
8088
*/
8189
public function __construct(
8290
\Magento\Framework\Model\Context $context,
@@ -85,11 +93,14 @@ public function __construct(
8593
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
8694
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
8795
array $data = [],
88-
CustomOptionPriceCalculator $customOptionPriceCalculator = null
96+
CustomOptionPriceCalculator $customOptionPriceCalculator = null,
97+
CalculateCustomOptionCatalogRule $CalculateCustomOptionCatalogRule = null
8998
) {
9099
$this->_valueCollectionFactory = $valueCollectionFactory;
91100
$this->customOptionPriceCalculator = $customOptionPriceCalculator
92-
?? \Magento\Framework\App\ObjectManager::getInstance()->get(CustomOptionPriceCalculator::class);
101+
?? ObjectManager::getInstance()->get(CustomOptionPriceCalculator::class);
102+
$this->calculateCustomOptionCatalogRule = $CalculateCustomOptionCatalogRule
103+
?? ObjectManager::getInstance()->get(CalculateCustomOptionCatalogRule::class);
93104

94105
parent::__construct(
95106
$context,
@@ -253,7 +264,11 @@ public function saveValues()
253264
public function getPrice($flag = false)
254265
{
255266
if ($flag) {
256-
return $this->customOptionPriceCalculator->getOptionPriceByPriceCode($this, BasePrice::PRICE_CODE);
267+
return $this->calculateCustomOptionCatalogRule->execute(
268+
$this->getProduct(),
269+
(float)$this->getData(self::KEY_PRICE),
270+
$this->getPriceType() === self::TYPE_PERCENT
271+
);
257272
}
258273
return $this->_getData(self::KEY_PRICE);
259274
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Pricing\Price;
9+
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\Product\PriceModifierInterface;
12+
use Magento\Framework\Pricing\PriceCurrencyInterface;
13+
14+
/**
15+
* Calculates prices of custom options of the product with catalog rules applied.
16+
*/
17+
class CalculateCustomOptionCatalogRule
18+
{
19+
/**
20+
* @var PriceCurrencyInterface
21+
*/
22+
private $priceCurrency;
23+
24+
/**
25+
* @var PriceModifierInterface
26+
*/
27+
private $priceModifier;
28+
29+
/**
30+
* @param PriceCurrencyInterface $priceCurrency
31+
* @param PriceModifierInterface $priceModifier
32+
*/
33+
public function __construct(
34+
PriceCurrencyInterface $priceCurrency,
35+
PriceModifierInterface $priceModifier
36+
) {
37+
$this->priceModifier = $priceModifier;
38+
$this->priceCurrency = $priceCurrency;
39+
}
40+
41+
/**
42+
* Calculate prices of custom options of the product with catalog rules applied.
43+
*
44+
* @param Product $product
45+
* @param float $optionPriceValue
46+
* @param bool $isPercent
47+
* @return float
48+
*/
49+
public function execute(
50+
Product $product,
51+
float $optionPriceValue,
52+
bool $isPercent
53+
): float {
54+
$regularPrice = (float)$product->getPriceInfo()
55+
->getPrice(RegularPrice::PRICE_CODE)
56+
->getValue();
57+
$catalogRulePrice = $this->priceModifier->modifyPrice(
58+
$regularPrice,
59+
$product
60+
);
61+
62+
// Apply catalog price rules to product options only if catalog price rules are applied to product.
63+
if ($catalogRulePrice < $regularPrice) {
64+
$optionPrice = $this->getOptionPriceWithoutPriceRule($optionPriceValue, $isPercent, $regularPrice);
65+
$totalCatalogRulePrice = $this->priceModifier->modifyPrice(
66+
$regularPrice + $optionPrice,
67+
$product
68+
);
69+
$finalOptionPrice = $totalCatalogRulePrice - $catalogRulePrice;
70+
} else {
71+
$finalOptionPrice = $this->getOptionPriceWithoutPriceRule(
72+
$optionPriceValue,
73+
$isPercent,
74+
$regularPrice
75+
);
76+
}
77+
78+
return $this->priceCurrency->convertAndRound($finalOptionPrice);
79+
}
80+
81+
82+
/**
83+
* Calculate option price without catalog price rule discount.
84+
*
85+
* @param float $optionPriceValue
86+
* @param bool $isPercent
87+
* @param float $basePrice
88+
* @return float
89+
*/
90+
private function getOptionPriceWithoutPriceRule(float $optionPriceValue, bool $isPercent, float $basePrice): float
91+
{
92+
return $isPercent ? $basePrice * $optionPriceValue / 100 : $optionPriceValue;
93+
}
94+
}

0 commit comments

Comments
 (0)