5

How to remove special price if qty is low.

Instead of setting from and to date from advanced pricing, I need to remove special price based on if qty is lower.

2

To customize price calculation, you need to change the code where magento calculate final_price in Price Model.

So, if you need to remove special price based on minimum quentity, you require to create new attribute for product which lets say "Min Qty for Special Price" and then you need to override Price.php Model and SpecialPrice.php of pricebox.

Check the below code to add attribute programatically.

[Package_Name][Module_Name]\Setup\InstallData.php

<?php

namespace [Package_Name][Module_Name]\Setup;

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallData implements InstallDataInterface
{
    /**
     * EAV setup factory
     *
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * Init
     *
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'min_qty_special_price',
            [
                'type' => 'int',
                'backend' => '',
                'frontend' => '',
                'label' => 'Minimum Qty for Special Price',
                'input' => 'text',
                'class' => 'validate-digits',
                'source' => '',
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
                'visible' => true,
                'required' => false,
                'user_defined' => false,
                'searchable' => false,
                'filterable' => false,
                'comparable' => false,
                'visible_on_front' => false,
                'used_in_product_listing' => true,
                'unique' => false,
                'apply_to' => '',
                'group' => 'Advanced Pricing'
            ]
        );
    }
}

Once you create attribute you need to override \Magento\Catalog\Model\Product\Type\Price.php. Check below code to override Price.php and add your custom code to calculate final price based on minimum qty that we have set using above attribute i.e. min_qty_special_price.

This code will use when we add product to cart and every places where magento need to calculate Final Price of the product.

[Package_Name][Module_Name]\Model\Catalog\Product\Type\Price.php

<?php

namespace [Package_Name][Module_Name]\Model\Catalog\Product\Type;

use Magento\Customer\Api\GroupManagementInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;

/**
 * Product type price model
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Price extends \Magento\Catalog\Model\Product\Type\Price
{
    /**
     * @var \Magento\CatalogInventory\Api\StockStateInterface
     */
    protected $_stockState;

    /**
     * Price 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 \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory $tierPriceFactory
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $config
     * @param \Magento\CatalogInventory\Api\StockStateInterface $stockState
     *
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    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,
        \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory $tierPriceFactory,
        \Magento\Framework\App\Config\ScopeConfigInterface $config,
        \Magento\CatalogInventory\Api\StockStateInterface $stockState
    ) {
        $this->_stockState = $stockState;

        parent::__construct($ruleFactory, $storeManager, $localeDate, $customerSession, $eventManager, $priceCurrency, $groupManagement, $tierPriceFactory, $config);
    }

    /**
     * Get base price with apply Group, Tier, Special prises
     *
     * @param Product $product
     * @param float|null $qty
     *
     * @return float
     */
    public function getBasePrice($product, $qty = null)
    {
        $price = (float) $product->getPrice();

        $specialPrice = $this->_applySpecialPrice($product, $price);

        if($this->_isSpecialPriceAllowedBasedOnMinQty($product))
            $specialPrice = $price;

        return min(
            $this->_applyTierPrice($product, $qty, $price),
            $specialPrice
        );
    }

    /**
     * @param Product $product
     *
     * @return bool
     */
    protected function _isSpecialPriceAllowedBasedOnMinQty($product)
    {
        $minQtyForSpecialPrice = $product->getMinQtySpecialPrice();
        if(isset($minQtyForSpecialPrice) && $minQtyForSpecialPrice != "")
        {
            // get Current Stock Qty
            $stockQty = $this->_stockState->getStockQty($product->getId(), $product->getStore()->getWebsiteId());

            // check Min Qty with Stock Qty
            $minQtyForSpecialPrice = (int) $minQtyForSpecialPrice;
            if($minQtyForSpecialPrice != 0 && $minQtyForSpecialPrice >= $stockQty)
                return true;
        }

        return false;
    }
}

Once you will override Price.php, you need to override SpecialPrice.php from pricing to determine whether to display special price in PriceBox or not on Product Listing and Product View pages.

[Package_Name][Module_Name]\Pricing\Catalog\Price\SpecialPrice.php

<?php

namespace [Package_Name][Module_Name]\Pricing\Catalog\Price;

use Magento\Framework\App\ObjectManager;

/**
 * Special price model
 */
class SpecialPrice extends \Magento\Catalog\Pricing\Price\SpecialPrice
{
    /**
     * @return bool|float
     */
    public function getValue()
    {
        if (null === $this->value) {            

            $this->value = false;
            $specialPrice = $this->getSpecialPrice();
            if ($specialPrice !== null && $specialPrice !== false && $this->isScopeDateInInterval()) {
                $this->value = (float) $specialPrice;
            }

            if($this->_isSpecialPriceAllowedBasedOnMinQty())
                $this->value = (float) $this->product->getPrice();
        }

        return $this->value;
    }

    /**
     * @return bool
     */
    protected function _isSpecialPriceAllowedBasedOnMinQty()
    {
        $minQtyForSpecialPrice = $this->product->getMinQtySpecialPrice();

        if(isset($minQtyForSpecialPrice) && $minQtyForSpecialPrice != "")
        {
            // get Stock State Object
            $stockState = ObjectManager::getInstance()->get('\Magento\CatalogInventory\Api\StockStateInterface');

            // get Current Stock Qty
            $stockQty = $stockState->getStockQty($this->product->getId(), $this->product->getStore()->getWebsiteId());

            // check Min Qty with Stock Qty
            $minQtyForSpecialPrice = (int) $minQtyForSpecialPrice;
            if($minQtyForSpecialPrice != 0 && $minQtyForSpecialPrice >= $stockQty)
                return true;
        }

        return false;
    }
}

Finally, to complete the override, we need to specify preferences to di.xml.

[Package_Name][Module_Name]\etc\di.xml

<?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="[Package_Name]\[Module_Name]\Model\Catalog\Product\Type\Price" />
    <preference for="Magento\Catalog\Pricing\Price\SpecialPrice" type="[Package_Name]\[Module_Name]\Pricing\Catalog\Price\SpecialPrice" />
</config>
2

Totally it's called tier pricing.

It is available when you edit a product in the Advanced Pricing or under the Price field depending on your Magento 2 version

In the Tier Price area, you need to click the Add Tier button and do the following:

Customer Group: choose to which group this is gonna apply
Quantity: 20
Price: 100

Then repeat this step with the following:

Customer Group: choose to which group this is gonna apply
Quantity: 10
Price: 50

Hope this helps you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.