How to create around Plugin for the getSavePercent method of the \Magento\Catalog\Pricing\Price\TierPrice class?

magento.stackexchange https://magento.stackexchange.com/questions/190603

  •  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

Was it helpful?

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top