Back to Top

Override Product Tier Prices in Magento 2

Updated 24 July 2024

Hello Friends!
In this blog, we will learn how we can override product’s tier prices on category product page and view product page.


In Magento 2, to override the product’s tier prices, we have to create plugins and preference. So, please follow the below steps:

1. Declare plugins and preferences: Here, we will declare required plugins and preferences in the di.xml file inside the app/code/Vendor/CustomModule/etc/ directory.

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

  <preference for="Magento\Catalog\Model\Product\Type\Price"  
    type="Vendor\CustomModule\Rewrite\Catalog\Model\Product\Type\Price" />

  <type name="Magento\Catalog\Pricing\Price\MinimalTierPriceCalculator">
        <plugin name="tier_price_info" 
          type="Vendor\CustomModule\Plugin\Catalog\Pricing\Price\MinimalTierPriceCalculator" 
          sortOrder="999" 
          disabled="false"  />
  </type>

  <type name="Magento\Catalog\Pricing\Price\FinalPrice">
        <plugin name="after_final_price_info" 
          type="Vendor\CustomModule\Plugin\Catalog\Pricing\Price\ChangeTierPriceInfo" 
          sortOrder="999" 
          disabled="false"  />
  </type>

</config>

2. Create preference class file Price.php for Magento\Catalog\Model\Product\Type\Price class inside the app/code/Vendor/CustomModule/Rewrite/Catalog/Model/Product/Type/ directory. In preference class, we will override ‘getExistingPrices’ method of Price Class.

<?php
/**
 * Vendor Desc.
 * php version 7.3.*
 *
 * @category Vendor
 * @package Vendor_CustomModule
 * @author Vendor
 * @copyright Vendor (https://example.com)
 * @license https://example.com/license.html
 */
declare(strict_types=1);

namespace Vendor\CustomModule\Rewrite\Catalog\Model\Product\Type;

use Magento\Catalog\Model\Product;
use Magento\Customer\Api\GroupManagementInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Store\Model\Store;
use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory;
use Magento\Framework\App\ObjectManager;
use Magento\Store\Api\Data\WebsiteInterface;
use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory;

/**
 * Product type price model
 */
class Price extends \Magento\Catalog\Model\Product\Type\Price
{
    /**
     * Product price cache tag
     */
    const CACHE_TAG = 'PRODUCT_PRICE';

    /**
     * @var array
     */
    protected static $attributeCache = [];

    /**
     * Core event manager proxy
     *
     * @var \Magento\Framework\Event\ManagerInterface
     */
    protected $_eventManager;

    /**
     * Customer session
     *
     * @var \Magento\Customer\Model\Session
     */
    protected $_customerSession;

    /**
     * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
     */
    protected $_localeDate;

    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;

    /**
     * Rule factory
     *
     * @var \Magento\CatalogRule\Model\ResourceModel\RuleFactory
     */
    protected $_ruleFactory;

    /**
     * @var PriceCurrencyInterface
     */
    protected $priceCurrency;

    /**
     * @var GroupManagementInterface
     */
    protected $_groupManagement;

    /**
     * @var \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory
     */
    protected $tierPriceFactory;

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $config;

    /**
     * @var ProductTierPriceExtensionFactory
     */
    private $tierPriceExtensionFactory;

    /**
     * Constructor
     *
     * @param \Magento\CatalogRule\Model\ResourceModel\RuleFactory $ruleFactory
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
     * @param \Magento\Customer\Model\Session $customerSession
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param PriceCurrencyInterface $priceCurrency
     * @param GroupManagementInterface $groupManagement
     * @param ProductTierPriceInterfaceFactory $tierPriceFactory
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $config
     * @param ProductTierPriceExtensionFactory|null $tierPriceExtensionFactory
     */
    public function __construct(
        \Magento\CatalogRule\Model\ResourceModel\RuleFactory $ruleFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        PriceCurrencyInterface $priceCurrency,
        GroupManagementInterface $groupManagement,
        ProductTierPriceInterfaceFactory $tierPriceFactory,
        \Magento\Framework\App\Config\ScopeConfigInterface $config,
        ProductTierPriceExtensionFactory $tierPriceExtensionFactory = null
    ) {
        parent::__construct(
            $ruleFactory,
            $storeManager,
            $localeDate,
            $customerSession,
            $eventManager,
            $priceCurrency,
            $groupManagement,
            $tierPriceFactory,
            $config,
            $tierPriceExtensionFactory
        );
    }
    
    /**
     * Gets the 'tier_price' array from the product
     *
     * @param Product $product
     * @param string $key
     * @param bool $returnRawData
     * @return array
     */
    protected function getExistingPrices($product, $key, $returnRawData = false)
    {
        $prices = $product->getData($key);
        
        if ($prices === null) {
            $attribute = $product->getResource()->getAttribute($key);
            if ($attribute) {
                $attribute->getBackend()->afterLoad($product);
                $prices = $product->getData($key);
            }
        }

        if ($prices === null || !is_array($prices)) {
            return ($returnRawData ? $prices : []);
        }

        if ($key == 'tier_price' && !empty($prices)) {
            $prevTier = $product->getData($key);
           
            //custom tier prices array
            $result = [
                [
                    "website_id"=>0,
                    "customer_group_id"=>32000,
                    "qty"=>2.0000,
                    "price_value_type"=>'fixed',
                    'value'=>35.0000,
                    'store_id'=>1
                ]
            ];

            $prevTiers = [];
            if (!empty($prevTier)) {
                foreach ($prevTier as $prev) {
                    $newKey = $prev["website_id"]."-".
                        $prev["all_groups"]."-".
                        $prev["cust_group"];
                    $prevTiers[$newKey] = $prev;
                }
            }
            if (!empty($result)) {
                foreach ($result as $tier) {
                    $allGroup = ($tier["customer_group_id"] != "32000")? "0" : "1";
                    $genKey = $tier["website_id"]."-".$allGroup."-".
                        $tier["customer_group_id"];
                    
                    if (array_key_exists($genKey, $prevTiers)) {
                        $each = [];
                        $each["price_id"]   = $prevTiers[$genKey]["price_id"] ?? 0;
                        $each["website_id"] = $tier["website_id"]        ?? "0";
                        $each["all_groups"] = $allGroup                  ?? "0";
                        $each["cust_group"] = $tier["customer_group_id"] ?? "0";
                        $each["price_qty"]  = $tier["qty"]               ?? "0";
    
                        $each["percentage_value"]=$prevTiers[$genKey][
                            "percentage_value"] ?? null;
                        $each["price"]           = $prevTiers[$genKey]["price"]
                            ?? "0";
                        $each["website_price"] = $prevTiers[$genKey]["website_price"]
                            ?? "0";
    
                        if ($tier["price_value_type"] == "fixed") {
                            $each["percentage_value"] = null;
                            $each["price"]            = $tier["value"] ?? "0";
                            $each["website_price"]    = $tier["value"] ?? "0";
                        }
                        if ($tier["price_value_type"] == "percent") {
                            $each["percentage_value"] = $tiers["value"]      ?? "0";
                            $each["price"] = $prevTiers[$genKey]["price"] ?? "0";
                            $each["website_price"] = $prevTiers[$genKey][
                                "website_price"] ?? "0";
                        }
                        $prices[] = $each;
                    }
                }
            }
        }
        
        return $prices;
    }
}

3. Create MinimalTierPriceCalculator.php file inside the app/code/Vendor/CustomModule/Plugin/Catalog/Pricing/Price/ directory. In this file, we will create ‘aroundGetValue’ plugin method of ‘getValue’ method of Magento\Catalog\Pricing\Price\MinimalTierPriceCalculator class.

<?php
/**
 * Vendor Desc.
 * php version 7.3.*
 *
 * @category  Vendor
 * @package   Vendor_CustomModule
 * @author    Vendor
 * @copyright Vendor (https://example.com)
 * @license   https://example.com/license.html
 */
namespace Venodr\CustomModule\Plugin\Catalog\Pricing\Price;

use Magento\Framework\Pricing\SaleableInterface;

class MinimalTierPriceCalculator
{
    /**
     * Get raw value of "as low as" as a minimal among tier prices{@inheritdoc}
     *
     * @param \Magento\Catalog\Pricing\Price\MinimalTierPriceCalculator $subject
     * @param \Closure $proceed
     * @param SaleableInterface $saleableItem
     *
     * @return float|null
     */
    
    public function aroundGetValue(
        \Magento\Catalog\Pricing\Price\MinimalTierPriceCalculator $subject,
        \Closure $proceed,
        SaleableInterface $saleableItem
    ) {
        $tierPrices        = [];
        $productTierPrices = [];
        $productTierPrices = $saleableItem->getTierPrices();
        
        if (!empty($productTierPrices)) {
            $result = [
                [
                    "website_id"=>0,
                    "customer_group_id"=>32000,
                    "qty"=>2.0000,
                    "price_value_type"=>'fixed',
                    'value'=>35.0000,
                    'store_id'=>1
                ]
            ];
            if (!empty($result)) {
                foreach ($result as $tier) {
                    $tierPrices[] = $tier["value"];
                }
                if (!empty($tierPrices)) {
                    return $tierPrices ? min($tierPrices) : null;
                }
            }
        }
        
        return $proceed($saleableItem);
    }
}

4. Create ChangeTierPriceInfo.php file inside the app/code/Vendor/CustomModule/Plugin/Catalog/Pricing/Price/ directory. In this file, we will create ‘aroundGetValue’ plugin method of ‘getValue’ method of \Magento\Catalog\Pricing\Price\FinalPrice Class.

Searching for an experienced
Magento 2 Company ?
Find out More
<?php
/**
 * Vendor Desc.
 * php version 7.3.*
 *
 * @category  Vendor
 * @package   Vendor_CustomModule
 * @author    Vendor
 * @copyright Vendor (https://example.com)
 * @license   https://example.com/license.html
 */
namespace Vendor\CustomModule\Plugin\Catalog\Pricing\Price;

use Magento\Framework\Session\SessionManagerInterface;
use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory;
use Magento\Framework\Stdlib\CookieManagerInterface;
 
class ChangeTierPriceInfo
{
    /**
     * @var \Magento\Catalog\Model\Product
     */
    protected $productModel;

    /**
     * @var \Magento\Framework\App\RequestInterface
     */
    protected $request;

    /**
     * Constructor
     *
     * @param \Magento\Catalog\Model\Product $productModel
     * @param \Magento\Framework\App\RequestInterface $request
     */
    public function __construct(
        \Magento\Catalog\Model\Product $productModel,
        \Magento\Framework\App\RequestInterface $request
    ) {
        $this->request      = $request;
        $this->productModel = $productModel;
    }

    /**
     * Get price value
     *
     * @param \Magento\Catalog\Pricing\Price\FinalPrice $subject
     * @param \Closure $proceed
     *
     * @return void
     */
    public function aroundGetValue(
        \Magento\Catalog\Pricing\Price\FinalPrice $subject,
        \Closure $proceed
    ) {
        $finalTierPrice = [];
        
        $productId = $this->request->getParam("id") ?? 0;
        $product   = $this->productModel->load($productId);
    
        $productObj = $subject->getProduct();
        $prevTier   = $productObj->getData("tier_price");
        $prevTiers = [];

        if (!empty($prevTier)) {
            foreach ($prevTier as $prev) {
                $newKey = $prev["website_id"]."-".$prev["all_groups"].
                    "-".$prev["cust_group"];
                $prevTiers[$newKey] = $prev;
            }
        }
        
        //custom tier prices array
        $result = [
            [
                "website_id"=>0,
                "customer_group_id"=>32000,
                "qty"=>2.0000,
                "price_value_type"=>'fixed',
                'value'=>35.0000,
                'store_id'=>1
            ]
        ];
            
        if (!empty($result)) {
            foreach ($result as $tier) {
                $allGroup = ($tier["customer_group_id"] != "32000")? "0" : "1";
                $genKey = $tier["website_id"]."-".$allGroup."-".
                    $tier["customer_group_id"];
                if (array_key_exists($genKey, $prevTiers)) {
                    $each = [];
                    $each["price_id"]   = $prevTiers[$genKey]["price_id"] ?? 0;
                    $each["website_id"] = $tier["website_id"]        ?? "0";
                    $each["all_groups"] = $allGroup                  ?? "0";
                    $each["cust_group"] = $tier["customer_group_id"] ?? "0";
                    $each["price_qty"]  = $tier["qty"]               ?? "0";

                    $each["percentage_value"] = $prevTiers[$genKey][
                        "percentage_value"] ?? null;
                    $each["price"] = $prevTiers[$genKey]["price"] ?? "0";
                    $each["website_price"]    = $prevTiers[$genKey][
                        "website_price"] ?? "0";

                    if ($tier["price_value_type"] == "fixed") {
                        $each["percentage_value"] = null;
                        $each["price"]            = $tier["value"] ?? "0";
                        $each["website_price"]    = $tier["value"] ?? "0";
                    }
                    if ($tier["price_value_type"] == "percent") {
                        $each["percentage_value"] = $tiers["value"]   ?? "0";
                        $each["price"] = $prevTiers[$genKey]["price"] ?? "0";
                        $each["website_price"]    = $prevTiers[$genKey][
                            "website_price"] ?? "0";
                    }
                    $finalTierPrice[] = $each;
                }
            }
        }

        //set modified tier prices array in product data
        if (!empty($productObj->getData('tier_price')) && !empty($finalTierPrice)) {
            $productObj->setData('tier_price', $finalTierPrice);
        }
        
        return $proceed();
    }
}

5. See the result in the following images. Here, we have created a product and set the tier price to $40 as displayed in the image. After overriding the tier price, It will display $35 as in the following image.

tier1
Created product and set price $50
tier2
Added tier price
result1
Overridden Tier price on product page
result2
Overridden Tier Price on category product page

Hope this will be helpful. Thanks 🙂

Previous Blog: Override Product Special Price in Magento 2

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home