1

I need to set cart discount based on individual qty and individual 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 Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory

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="Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory">
        <plugin name="Vendor_Module::CalculatorFactory" type="Vendor\Module\Plugin\CalculatorFactory"  />
    </type>
</config>

Create model file.

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

<?php
namespace Vendor\Module\Model\Rule\Action\Discount;

use Magento\Quote\Model\Quote\Item\AbstractItem;
use Magento\SalesRule\Model\Rule;
use Magento\SalesRule\Model\Rule\Action\Discount\Data;

class PercentBuyMinNTiered extends \Vendor\Module\Model\Rule\Action\Discount\AbstractDiscount
{
    /**
     * @param \Magento\SalesRule\Model\Rule $rule
     * @param \Magento\Quote\Model\Quote\Item\AbstractItem $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 \Magento\SalesRule\Model\Rule $rule
     * @return float
     */
    public function fixQuantity($qty, $rule)
    {
        $step = $rule->getDiscountStep();
        if ($step) {
            $qty = floor($qty / $step) * $step;
        }

        return $qty;
    }

    /**
     * @param \Magento\SalesRule\Model\Rule $rule
     * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
     * @param float $qty
     * @param float $rulePercent
     * @return Data
     */
    protected function _calculate($rule, $item, $qty, $rulePercent)
    {
        /** @var \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData */
         $discountData = $this->discountFactory->create();

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

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $cart = $objectManager->get('\Magento\Checkout\Model\Cart');        
        $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.

$tierJsonData comming in DB from salesrule table field name is tier_qty_discount.

[{"tier_qty_discount":"10","record_id":"0"},{"tier_qty_discount":"20","record_id":"1"},{"tier_qty_discount":"30","record_id":"2"]

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

1 Answer 1

0

Could you please try with this code. You can modify '_calculate' method like below:

    protected function _calculate($rule, $item, $qty, $rulePercent)
    {
        /** @var \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData */
         $discountData = $this->discountFactory->create();

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $cart = $objectManager->get('\Magento\Checkout\Model\Cart');
        $cartItems = $cart->getQuote()->getAllItems();

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

        $tierJsonData = $rule->getTierQtyDiscount();
        $tierPrices = [];
        foreach ($tierJsonData as $key => $value) {
            $tierPrices[$value['price']] = $value['price'] * ($value['percentage_discount'] / 100);
        }
        arsort($tierPrices);
        $itemPrice = $itemPrices[$item->getItemId()];
        $tierPrice = 0;
        foreach ($tierPrices as $key => $value) {
            if ($itemPrice >= $key) {
                $tierPrice = $value;
                break;
            }
        }
        $discountData->setAmount($tierPrice);
        $discountData->setBaseAmount($tierPrice);
        $discountData->setOriginalAmount($tierPrice);
        $discountData->setBaseOriginalAmount($tierPrice);       

         return $discountData;

    }
1
  • I have checked but not adding discount based on item level with qty. I have updated $tierJsonData in question. Commented Mar 15, 2023 at 4:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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