Preventing all coupons / cart rules from being used on specific product in Magento 2
This article will show how to implement a plugin that causes all the cart rules (and coupons) to skip a specific product. That is, no coupons will be used on the specific product.
Creating a test cart rule
To test our module, we will create a simple cart rule, "Get a 10% discount," which will apply a 10% discount on all products in the cart.
This is the rule configuration:
Adding some products to the cart
If we add some products to the cart, we will see that a 10% discount is applied to all the products:
What we want to happen
We want to prevent all the cart rules/coupons from being applied to the "Endeavor Daytrip Backpack" product. That is, instead of a $7.8 discount, we want it to be only $7.5.
To achieve that, lets create our plugin.
The code of the plugin
Let's see the Magento 2 plugin code that prevents all coupons/promotions from being applied to the product with SKU 24-WB06 (Endeavor Daytrip Backpack).
First, let's create the basic plugin structure in app/code/Mexbs/SkipDiscountsForProduct and the following files:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Mexbs_SkipDiscountsForProduct',
__DIR__
);
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Mexbs_SkipDiscountsForProduct" setup_version="1.0.0" />
</config>
Now, let's create the di file that will define the plugin.
<?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\Validator">
<plugin name="mexbsValidatorPlugin" type="Mexbs\SkipDiscountsForProduct\Plugin\Validator"/>
</type>
</config>
Now, let's create the plugin. It will hook to the Validator::canApplyDiscount and will be responsible for preventing any cart rules from being applied to our excluded product.
<?php
namespace Mexbs\SkipDiscountsForProduct\Plugin;
class Validator
{
public function aroundCanApplyDiscount(
\Magento\SalesRule\Model\Validator $subject,
\Closure $proceed,
\Magento\Quote\Model\Quote\Item\AbstractItem $item
){
if($item->getProduct()->getSku() == "24-WB06"){
return false;
}
return $proceed($item);
}
}
Installing the module
Now, we need to run the usual commands to enable the module, compile the code, etc:
php bin/magento module:enable Mexbs_SkipDiscountsForProduct
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush
Testing the module
To test the module, refresh the cart (by pressing the "Update Shopping Cart" button). You should see that the discount is now $4.5, as desired:
That is, the discount was not applied to the "Endeavor Daytrip Backpack" product and this is exactly what we wanted.
To sum up
This article showed how to create a Magento 2 module that prevents all coupons/cart rules from being applied to a specific product.
This code was tested on Magento CE 2.4.7-p3