How to create around Plugin for the getSavePercent method of the \Magento\Catalog\Pricing\Price\TierPrice class?
-
11-12-2020 - |
Question
I have used following code to create around plugin for the getSavePercent method of \Magento\Catalog\Pricing\Price\TierPrice
class.
(My objective is to get two decimals precision.)
<?php
namespace Mymodule\Common\Plugin;
use Magento\Framework\Pricing\Amount\AmountInterface;
use Magento\Framework\Pricing\SaleableInterface;
use Magento\Catalog\Pricing\Price\FinalPrice;
class TierPricePlugin
{
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $scopeConfig;
/**
* @var PriceInfoInterface
*/
protected $priceInfo;
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
SaleableInterface $saleableItem
) {
$this->scopeConfig = $scopeConfig;
$this->priceInfo = $saleableItem->getPriceInfo();
}
/**
* @param AmountInterface $amount
* @return float
*/
public function aroundGetSavePercent(\Magento\Catalog\Pricing\Price\TierPrice $subject, \Closure $proceed, $amount)
{
$precision = $this->scopeConfig->getValue('mymodule_common/tier_prices/precision', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
return round(
100 - ((100 / $this->priceInfo->getPrice(FinalPrice::PRICE_CODE)->getValue())
* $amount->getBaseAmount()),$precision
);
}
}
I get following error.
PHP Fatal error:
Uncaught Error: Cannot instantiate interface Magento\\Framework\\Pricing\\SaleableInterface in /var/www/html/Mysite/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php:73\nStack trace:\n#0
/var/www/html/Mysite/vendor/magento/framework/ObjectManager/ObjectManager.php(71): Magento\\Framework\\ObjectManager\\Factory\\Dynamic\\Developer->create('Magento\\\\Framewo...')\n#1
/var/www/html/Mysite/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(126): Magento\\Framework\\ObjectManager\\ObjectManager->get('Magento\\\\Framewo...')\n#2
/var/www/html/Mysite/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php(53): Magento\\Framework\\ObjectManager\\Factory\\AbstractFactory->resolveArgument(Array, 'Magento\\\\Framewo...', NULL, 'saleableItem', 'Mymodule\\\\Common\\\\P...')\n#3
/var/www/html/Mysite/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php(82): Magento\\Framework\\ObjectManager\\Factory\\Dynamic\\Developer->_resolveArguments('Mymodule\\\\Common\\\\P...', Array, Array)\n#4
/var/www/html/Mysite/vendor/m in /var/www/html/Mysite/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php
Issue seems to be created by following code line
$this->priceInfo->getPrice(FinalPrice::PRICE_CODE)->getValue()
I want to get the final price of the product in my plugin code, so i am using above mentioned line. But there seems to be problem with $this->priceInfo
Solution
You are currently trying to use Magento\Framework\Pricing\SaleableInterface
for which there is no preference set so the ObjectManager is unable to find a concrete class that fulfils this interface. This leads to the error you are seeing when your TierPrice plugin class is being constructed.
Looking at Magento\Framework\Pricing\Price\AbstractPrice
I believe you do not need SaleableInterface
at all as you can get it from the TierPrice $subject.
So you would end up with:
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
) {
$this->scopeConfig = $scopeConfig;
}
public function aroundGetSavePercent(\Magento\Catalog\Pricing\Price\TierPrice $subject, \Closure $proceed, $amount)
{
$precision = $this->scopeConfig->getValue('mymodule_common/tier_prices/precision', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
return round(
100 - ((100 / $subject->getProduct()->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue())
* $amount->getBaseAmount()),$precision
);
}
OTHER TIPS
If your goal is to get 2 decimal precision returned by getSavePercent(), you could try using a preference for the "Magento\Catalog\Pricing\Price\TierPrice" class instead of plugins.
di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference
for="Magento\Catalog\Pricing\Price\TierPrice"
type="Rsk\Demos\Preferences\TierPricePref"/>
</config>
TierPricePref.php
<?php
namespace Rsk\Demos\Preferences;
class TierPricePref extends \Magento\Catalog\Pricing\Price\TierPrice
{
/**
* @param AmountInterface $amount
* @return float
*/
public function getSavePercent(AmountInterface $amount)
{
return round(
100 - ((100 / $this->priceInfo->getPrice(FinalPrice::PRICE_CODE)->getValue())
* $amount->getBaseAmount()), 2 );
}
}
Hope that helps!