Skip to content

Commit a8f3b9e

Browse files
committed
#22856: Catalog price rules are not working with custom options as expected.
1 parent ea71192 commit a8f3b9e

File tree

11 files changed

+400
-149
lines changed

11 files changed

+400
-149
lines changed

app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
7-
/**
8-
* Product options abstract type block
9-
*
10-
* @author Magento Core Team <core@magentocommerce.com>
11-
*/
6+
declare(strict_types=1);
127

138
namespace Magento\Catalog\Block\Product\View\Options;
149

10+
use Magento\Catalog\Pricing\Price\BasePrice;
11+
use Magento\Catalog\Pricing\Price\CalculateCustomOptionCatalogRule;
1512
use Magento\Catalog\Pricing\Price\CustomOptionPriceInterface;
13+
use Magento\Framework\App\ObjectManager;
1614

1715
/**
1816
* Product options section abstract block.
@@ -47,20 +45,29 @@ abstract class AbstractOptions extends \Magento\Framework\View\Element\Template
4745
*/
4846
protected $_catalogHelper;
4947

48+
/**
49+
* @var CalculateCustomOptionCatalogRule
50+
*/
51+
private $calculateCustomOptionCatalogRule;
52+
5053
/**
5154
* @param \Magento\Framework\View\Element\Template\Context $context
5255
* @param \Magento\Framework\Pricing\Helper\Data $pricingHelper
5356
* @param \Magento\Catalog\Helper\Data $catalogData
5457
* @param array $data
58+
* @param CalculateCustomOptionCatalogRule $calculateCustomOptionCatalogRule
5559
*/
5660
public function __construct(
5761
\Magento\Framework\View\Element\Template\Context $context,
5862
\Magento\Framework\Pricing\Helper\Data $pricingHelper,
5963
\Magento\Catalog\Helper\Data $catalogData,
60-
array $data = []
64+
array $data = [],
65+
CalculateCustomOptionCatalogRule $calculateCustomOptionCatalogRule = null
6166
) {
6267
$this->pricingHelper = $pricingHelper;
6368
$this->_catalogHelper = $catalogData;
69+
$this->calculateCustomOptionCatalogRule = $calculateCustomOptionCatalogRule
70+
?? ObjectManager::getInstance()->get(CalculateCustomOptionCatalogRule::class);
6471
parent::__construct($context, $data);
6572
}
6673

@@ -161,6 +168,15 @@ protected function _formatPrice($value, $flag = true)
161168
$priceStr = $sign;
162169

163170
$customOptionPrice = $this->getProduct()->getPriceInfo()->getPrice('custom_option_price');
171+
172+
if (!$value['is_percent']) {
173+
$value['pricing_value'] = $this->calculateCustomOptionCatalogRule->execute(
174+
$this->getProduct(),
175+
(float)$value['pricing_value'],
176+
(bool)$value['is_percent']
177+
);
178+
}
179+
164180
$context = [CustomOptionPriceInterface::CONFIGURATION_OPTION_FLAG => true];
165181
$optionAmount = $customOptionPrice->getCustomAmount($value['pricing_value'], null, $context);
166182
$priceStr .= $this->getLayout()->getBlock('product.price.render.default')->renderAmount(

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

Lines changed: 43 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Catalog\Model\Product;
89

@@ -11,8 +12,10 @@
1112
use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterfaceFactory;
1213
use Magento\Catalog\Api\Data\ProductInterface;
1314
use Magento\Catalog\Model\Product;
15+
use Magento\Catalog\Model\Product\Option\Value;
1416
use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection;
15-
use Magento\Catalog\Pricing\Price\BasePrice;
17+
use Magento\Catalog\Pricing\Price\CalculateCustomOptionCatalogRule;
18+
use Magento\Framework\App\ObjectManager;
1619
use Magento\Framework\EntityManager\MetadataPool;
1720
use Magento\Framework\Exception\LocalizedException;
1821
use Magento\Framework\Model\AbstractExtensibleModel;
@@ -108,6 +111,11 @@ class Option extends AbstractExtensibleModel implements ProductCustomOptionInter
108111
*/
109112
private $customOptionValuesFactory;
110113

114+
/**
115+
* @var CalculateCustomOptionCatalogRule
116+
*/
117+
private $calculateCustomOptionCatalogRule;
118+
111119
/**
112120
* @param \Magento\Framework\Model\Context $context
113121
* @param \Magento\Framework\Registry $registry
@@ -121,6 +129,7 @@ class Option extends AbstractExtensibleModel implements ProductCustomOptionInter
121129
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
122130
* @param array $data
123131
* @param ProductCustomOptionValuesInterfaceFactory|null $customOptionValuesFactory
132+
* @param CalculateCustomOptionCatalogRule $calculateCustomOptionCatalogRule
124133
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
125134
*/
126135
public function __construct(
@@ -135,14 +144,17 @@ public function __construct(
135144
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
136145
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
137146
array $data = [],
138-
ProductCustomOptionValuesInterfaceFactory $customOptionValuesFactory = null
147+
ProductCustomOptionValuesInterfaceFactory $customOptionValuesFactory = null,
148+
CalculateCustomOptionCatalogRule $calculateCustomOptionCatalogRule = null
139149
) {
140150
$this->productOptionValue = $productOptionValue;
141151
$this->optionTypeFactory = $optionFactory;
142152
$this->validatorPool = $validatorPool;
143153
$this->string = $string;
144154
$this->customOptionValuesFactory = $customOptionValuesFactory ?:
145-
\Magento\Framework\App\ObjectManager::getInstance()->get(ProductCustomOptionValuesInterfaceFactory::class);
155+
ObjectManager::getInstance()->get(ProductCustomOptionValuesInterfaceFactory::class);
156+
$this->calculateCustomOptionCatalogRule = $calculateCustomOptionCatalogRule ??
157+
ObjectManager::getInstance()->get(CalculateCustomOptionCatalogRule::class);
146158

147159
parent::__construct(
148160
$context,
@@ -156,10 +168,7 @@ public function __construct(
156168
}
157169

158170
/**
159-
* Get resource instance
160-
*
161-
* @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
162-
* @deprecated 101.1.0 because resource models should be used directly
171+
* @inheritdoc
163172
*/
164173
protected function _getResource()
165174
{
@@ -439,10 +448,12 @@ public function afterSave()
439448
*/
440449
public function getPrice($flag = false)
441450
{
442-
if ($flag && $this->getPriceType() == self::$typePercent) {
443-
$basePrice = $this->getProduct()->getPriceInfo()->getPrice(BasePrice::PRICE_CODE)->getValue();
444-
$price = $basePrice * ($this->_getData(self::KEY_PRICE) / 100);
445-
return $price;
451+
if ($flag) {
452+
return $this->calculateCustomOptionCatalogRule->execute(
453+
$this->getProduct(),
454+
(float)$this->getData(self::KEY_PRICE),
455+
$this->getPriceType() === Value::TYPE_PERCENT
456+
);
446457
}
447458
return $this->_getData(self::KEY_PRICE);
448459
}
@@ -536,9 +547,7 @@ public function getSearchableData($productId, $storeId)
536547
}
537548

538549
/**
539-
* Clearing object's data
540-
*
541-
* @return $this
550+
* @inheritdoc
542551
*/
543552
protected function _clearData()
544553
{
@@ -548,9 +557,7 @@ protected function _clearData()
548557
}
549558

550559
/**
551-
* Clearing cyclic references
552-
*
553-
* @return $this
560+
* @inheritdoc
554561
*/
555562
protected function _clearReferences()
556563
{
@@ -571,9 +578,7 @@ protected function _getValidationRulesBeforeSave()
571578
}
572579

573580
/**
574-
* Get product SKU
575-
*
576-
* @return string
581+
* @inheritdoc
577582
*/
578583
public function getProductSku()
579584
{
@@ -585,9 +590,7 @@ public function getProductSku()
585590
}
586591

587592
/**
588-
* Get option id
589-
*
590-
* @return int|null
593+
* @inheritdoc
591594
* @codeCoverageIgnoreStart
592595
*/
593596
public function getOptionId()
@@ -596,60 +599,47 @@ public function getOptionId()
596599
}
597600

598601
/**
599-
* Get option title
600-
*
601-
* @return string
602+
* @inheritdoc
602603
*/
603604
public function getTitle()
604605
{
605606
return $this->_getData(self::KEY_TITLE);
606607
}
607608

608609
/**
609-
* Get option type
610-
*
611-
* @return string
610+
* @inheritdoc
612611
*/
613612
public function getType()
614613
{
615614
return $this->_getData(self::KEY_TYPE);
616615
}
617616

618617
/**
619-
* Get sort order
620-
*
621-
* @return int
618+
* @inheritdoc
622619
*/
623620
public function getSortOrder()
624621
{
625622
return $this->_getData(self::KEY_SORT_ORDER);
626623
}
627624

628625
/**
629-
* Get is require
630-
*
631-
* @return bool
632-
* @SuppressWarnings(PHPMD.BooleanGetMethodName)
626+
* @inheritdoc
633627
*/
634628
public function getIsRequire()
635629
{
636630
return $this->_getData(self::KEY_IS_REQUIRE);
637631
}
638632

639633
/**
640-
* Get price type
641-
*
642-
* @return string|null
634+
* @inheritdoc
643635
*/
644636
public function getPriceType()
645637
{
646638
return $this->_getData(self::KEY_PRICE_TYPE);
647639
}
648640

649641
/**
650-
* Get Sku
651-
*
652-
* @return string|null
642+
* @inheritdoc
653643
*/
654644
public function getSku()
655645
{
@@ -697,98 +687,71 @@ public function getImageSizeY()
697687
}
698688

699689
/**
700-
* Set product SKU
701-
*
702-
* @param string $productSku
703-
* @return $this
690+
* @inheritdoc
704691
*/
705692
public function setProductSku($productSku)
706693
{
707694
return $this->setData(self::KEY_PRODUCT_SKU, $productSku);
708695
}
709696

710697
/**
711-
* Set option id
712-
*
713-
* @param int $optionId
714-
* @return $this
698+
* @inheritdoc
715699
*/
716700
public function setOptionId($optionId)
717701
{
718702
return $this->setData(self::KEY_OPTION_ID, $optionId);
719703
}
720704

721705
/**
722-
* Set option title
723-
*
724-
* @param string $title
725-
* @return $this
706+
* @inheritdoc
726707
*/
727708
public function setTitle($title)
728709
{
729710
return $this->setData(self::KEY_TITLE, $title);
730711
}
731712

732713
/**
733-
* Set option type
734-
*
735-
* @param string $type
736-
* @return $this
714+
* @inheritdoc
737715
*/
738716
public function setType($type)
739717
{
740718
return $this->setData(self::KEY_TYPE, $type);
741719
}
742720

743721
/**
744-
* Set sort order
745-
*
746-
* @param int $sortOrder
747-
* @return $this
722+
* @inheritdoc
748723
*/
749724
public function setSortOrder($sortOrder)
750725
{
751726
return $this->setData(self::KEY_SORT_ORDER, $sortOrder);
752727
}
753728

754729
/**
755-
* Set is require
756-
*
757-
* @param bool $isRequired
758-
* @return $this
730+
* @inheritdoc
759731
*/
760732
public function setIsRequire($isRequired)
761733
{
762734
return $this->setData(self::KEY_IS_REQUIRE, $isRequired);
763735
}
764736

765737
/**
766-
* Set price
767-
*
768-
* @param float $price
769-
* @return $this
738+
* @inheritdoc
770739
*/
771740
public function setPrice($price)
772741
{
773742
return $this->setData(self::KEY_PRICE, $price);
774743
}
775744

776745
/**
777-
* Set price type
778-
*
779-
* @param string $priceType
780-
* @return $this
746+
* @inheritdoc
781747
*/
782748
public function setPriceType($priceType)
783749
{
784750
return $this->setData(self::KEY_PRICE_TYPE, $priceType);
785751
}
786752

787753
/**
788-
* Set Sku
789-
*
790-
* @param string $sku
791-
* @return $this
754+
* @inheritdoc
792755
*/
793756
public function setSku($sku)
794757
{
@@ -929,7 +892,7 @@ public function setExtensionAttributes(
929892
private function getOptionRepository()
930893
{
931894
if (null === $this->optionRepository) {
932-
$this->optionRepository = \Magento\Framework\App\ObjectManager::getInstance()
895+
$this->optionRepository = ObjectManager::getInstance()
933896
->get(\Magento\Catalog\Model\Product\Option\Repository::class);
934897
}
935898
return $this->optionRepository;
@@ -943,7 +906,7 @@ private function getOptionRepository()
943906
private function getMetadataPool()
944907
{
945908
if (null === $this->metadataPool) {
946-
$this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance()
909+
$this->metadataPool = ObjectManager::getInstance()
947910
->get(\Magento\Framework\EntityManager\MetadataPool::class);
948911
}
949912
return $this->metadataPool;

0 commit comments

Comments
 (0)