0

How to override Magento\SalesRule\Model\RulesApplier class in custom module ?

i have tried

etc/di.xml

<preference for="Magento\SalesRule\Model\RulesApplier" type="Myvendor\SalesRule\Model\RulesApplier" />

Myvendor/SalesRule/Model/RulesApplier.php <?php

namespace Myvendor\SalesRule\Model;

use Magento\Quote\Model\Quote\Address;
use Magento\Quote\Model\Quote\Item\AbstractItem;
use Magento\SalesRule\Model\Quote\ChildrenValidationLocator;
use Magento\Framework\App\ObjectManager;
use Magento\SalesRule\Model\ResourceModel\Rule\Collection;
use Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory;
use Magento\SalesRule\Model\Rule\Action\Discount\DataFactory;
use Magento\SalesRule\Api\Data\RuleDiscountInterfaceFactory;
use Magento\SalesRule\Api\Data\DiscountDataInterfaceFactory;
use Magento\GiftCard\Model\Catalog\Product\Type\Giftcard as GiftCardType;

/**
 * Rule applier model
 */
class RulesApplier extends \Magento\SalesRule\Model\RulesApplier
{
    /**
     * Application Event Dispatcher
     *
     * @var \Magento\Framework\Event\ManagerInterface
     */
    protected $_eventManager;

    /**
     * @var \Magento\SalesRule\Model\Utility
     */
    protected $validatorUtility;

    /**
     * @var ChildrenValidationLocator
     */
    private $childrenValidationLocator;

    /**
     * @var CalculatorFactory
     */
    private $calculatorFactory;

    /**
     * @var \Magento\SalesRule\Model\Rule\Action\Discount\DataFactory
     */
    protected $discountFactory;

    /**
     * @var RuleDiscountInterfaceFactory
     */
    private $discountInterfaceFactory;

    /**
     * @var DiscountDataInterfaceFactory
     */
    private $discountDataInterfaceFactory;

    /**
     * @var array
     */
    private $discountAggregator;

    /**
     * RulesApplier constructor.
     * @param CalculatorFactory $calculatorFactory
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param Utility $utility
     * @param ChildrenValidationLocator|null $childrenValidationLocator
     * @param DataFactory|null $discountDataFactory
     * @param RuleDiscountInterfaceFactory|null $discountInterfaceFactory
     * @param DiscountDataInterfaceFactory|null $discountDataInterfaceFactory
     */
    public function __construct(
        \Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory $calculatorFactory,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\SalesRule\Model\Utility $utility,
        ChildrenValidationLocator $childrenValidationLocator = null,
        DataFactory $discountDataFactory = null,
        RuleDiscountInterfaceFactory $discountInterfaceFactory = null,
        DiscountDataInterfaceFactory $discountDataInterfaceFactory = null
    ) {
        $this->calculatorFactory = $calculatorFactory;
        $this->validatorUtility = $utility;
        $this->_eventManager = $eventManager;
        $this->childrenValidationLocator = $childrenValidationLocator
             ?: ObjectManager::getInstance()->get(ChildrenValidationLocator::class);
        $this->discountFactory = $discountDataFactory ?: ObjectManager::getInstance()->get(DataFactory::class);
        $this->discountInterfaceFactory = $discountInterfaceFactory
            ?: ObjectManager::getInstance()->get(RuleDiscountInterfaceFactory::class);
        $this->discountDataInterfaceFactory = $discountDataInterfaceFactory
            ?: ObjectManager::getInstance()->get(DiscountDataInterfaceFactory::class);
    }

    /**
     * Apply rules to current order item
     * Applied fix to prevent cart rule apply to gc product
     * @param AbstractItem $item
     * @param Collection $rules
     * @param bool $skipValidation
     * @param mixed $couponCode
     * @return array
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public function applyRules($item, $rules, $skipValidation, $couponCode)
    {
        $address = $item->getAddress();
        $appliedRuleIds = [];
        $this->discountAggregator = [];
        /* @var $rule Rule */
        foreach ($rules as $rule) {
            if (!$this->validatorUtility->canProcessRule($rule, $address)) {
                continue;
            }
            if (!$skipValidation && !$rule->getActions()->validate($item)) {
                if (!$this->childrenValidationLocator->isChildrenValidationRequired($item)) {
                    continue;
                }
                $childItems = $item->getChildren();
                $isContinue = true;
                if (!empty($childItems)) {
                    foreach ($childItems as $childItem) {
                        if ($rule->getActions()->validate($childItem)) {
                            $isContinue = false;
                        }
                    }
                }
                if ($isContinue) {
                    continue;
                }
            }
            $product = $item->getProductType();
            if ($product != GiftCardType::TYPE_GIFTCARD) {
                $this->applyRule($item, $rule, $address, $couponCode);
            }
            $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId();

            if ($rule->getStopRulesProcessing()) {
                break;
            }
        }

        return $appliedRuleIds;
    }
}

This works but then "ADD to Cart" not working. no logs no error.

4
  • 1
    which function you want to modified? Commented May 11, 2021 at 7:57
  • HI rohan thanks for the comment. i want to override public function applyRules()
    – devhs
    Commented May 11, 2021 at 8:00
  • Any thoughts ??
    – devhs
    Commented May 11, 2021 at 8:14
  • I post my answer. You can check it. Commented May 11, 2021 at 8:20

1 Answer 1

1

You can use it by around plugin. Instead of override use plugin code.

Create di.xml to add plugin code :

app/code/VendorName/ModuleName/etc/di.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <type name="Magento\SalesRule\Model\RulesApplier">
        <plugin name="sales_apply_plugin"
            type="VendorName\ModuleName\Plugin\SalesRule\Model\RulesApplier"
            sortOrder="1"/>
    </type>
</config>

Create RulesApplier.php plugin file

app/code/VendorName/ModuleName/Plugin/SalesRule/Model/RulesApplier.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace VendorName\ModuleName\Plugin\SalesRule\Model;

class RulesApplier
{
  
    public function aroundApplyRules(
        \Magento\SalesRule\Model\RulesApplier $subject,
        \Closure $proceed,
        $item,
        $rules,
        $skipValidation,
        $couponCode
    ) {
        // Add your logic
        $result = $proceed($item, $rules, $skipValidation, $couponCode);
        return $result;
    }
}

Clean cache and check it.

6
  • Actually i was missing parent::__construct($calculatorFactory,$eventManager,$utility,$childrenValidationLocator,$discountDataFactory,$discountInterfaceFactory,$discountDataInterfaceFactory); in my code so that issue was coming
    – devhs
    Commented May 11, 2021 at 8:30
  • 1
    I have update the code which i have used & its working. so do no need to add plugin.
    – devhs
    Commented May 11, 2021 at 8:33
  • I wanted to know if that's ok to add parent construct ? if its what its missing ?
    – devhs
    Commented May 11, 2021 at 8:35
  • 1
    parent construct must be required when override files. As per coding standard, if plugin is possible then avoid to use preference. Commented May 11, 2021 at 8:36
  • Hello, is their any way i can add this changes in the plugin you said $product = $item->getProductType(); if ($product != GiftCardType::TYPE_GIFTCARD) { $this->applyRule($item, $rule, $address, $couponCode); } ?
    – devhs
    Commented May 13, 2021 at 13:59

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.