Skip to content

Magento 2: Add discount based on individual qty and item to cart

I need to set cart discount based on individual qty and item for cart.

For example if cart have 2 item then lowest price item to give higher percentage discount, like need to add 10% and 20% discount then lowest price item to give 20% and second item to give 10%

If cart have 1 product with 3 qty then need to set discount to individual qty for only first two qty like 20% and 10% third qty to give 0 discount.

I need tier discount based on individual qty based lowest price to higher percentage discount to cart item.

For this custom flow I have used plugin MagentoSalesRuleModelRuleActionDiscountCalculatorFactory

File path:
app/code/Vendor/Module/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">
   <type name="MagentoSalesRuleModelRuleActionDiscountCalculatorFactory">
        <plugin name="Vendor_Module::CalculatorFactory" type="VendorModulePluginCalculatorFactory"  />
    </type>
</config>

Create model file.

File path:
app/code/Vendor/Module/Model/Rule/Action/Discount/PercentBuyMinNTiered.php

<?php
namespace VendorModuleModelRuleActionDiscount;

use MagentoQuoteModelQuoteItemAbstractItem;
use MagentoSalesRuleModelRule;
use MagentoSalesRuleModelRuleActionDiscountData;

class PercentBuyMinNTiered extends VendorModuleModelRuleActionDiscountAbstractDiscount
{
    /**
     * @param MagentoSalesRuleModelRule $rule
     * @param MagentoQuoteModelQuoteItemAbstractItem $item
     * @param float $qty
     * @return Data
     */
    public function calculate($rule, $item, $qty)
    {
        $rulePercent = min(100, $rule->getDiscountAmount());
        $discountData = $this->_calculate($rule, $item, $qty, $rulePercent);
        return $discountData;
    }

    /**
     * @param float $qty
     * @param MagentoSalesRuleModelRule $rule
     * @return float
     */
    public function fixQuantity($qty, $rule)
    {
        $step = $rule->getDiscountStep();
        if ($step) {
            $qty = floor($qty / $step) * $step;
        }

        return $qty;
    }

    /**
     * @param MagentoSalesRuleModelRule $rule
     * @param MagentoQuoteModelQuoteItemAbstractItem $item
     * @param float $qty
     * @param float $rulePercent
     * @return Data
     */
    protected function _calculate($rule, $item, $qty, $rulePercent)
    {
        /** @var MagentoSalesRuleModelRuleActionDiscountData $discountData */
         $discountData = $this->discountFactory->create();

        $quoteId = $item->getQuoteId();
        $productPrice = $item->getPrice();

        $objectManager = MagentoFrameworkAppObjectManager::getInstance();
        $cart = $objectManager->get('MagentoCheckoutModelCart');        
        $itemsCollection = $cart->getQuote()->getItemsCollection();
        $itemsVisible = $cart->getQuote()->getAllVisibleItems();
        $cartItems = $cart->getQuote()->getAllItems();

        $productPrice = [];
        foreach($cartItems as $key => $itemData) {
            $itemsPrice[$key] = $itemData->getPrice();
        }

        $itemsPrices = json_econde($itemsPrice);
        $minValue = min($itemsPrices);
       

        $tierJsonData = $rule->getTierQtyDiscount();
        if ($tierJsonData) {
        }   

        $_rulePct = 20 / 100;  //20 is percent to give disocunt to higer price product and 10 need to give lower price item.
        $discountData->setAmount((1 * $minValue) * $_rulePct);
        $discountData->setBaseAmount((1 * $minValue) * $_rulePct);
        $discountData->setOriginalAmount((1 * $minValue) * $_rulePct);
        $discountData->setBaseOriginalAmount(((1 * $minValue) * $_rulePct));       

         return $discountData;

    }
}

To the calculate function how can we add discount to individual items.
I have facing issue with set discount based on individual item and based on individual qty.

Note: Right now added some static value and object manager for developing purpose.