How to Create Custom Sales Rule Condition in Magento 2

How to Create Custom Sales Rule Condition in Magento 2

Many times while selling products online you have to enable your shipping service for limited areas only. Due to Higher shipping/export rates, banned products, strict customs laws or tough cash handling this all results in admin to restrict order shipping to limited areas. Luckily, using Magento 2 you can create shopping cart rules that allow you to check for dynamic conditions

However, if you want to create your custom shopping cart rules that trigger specific code in reaction to that event. To do the same you have to create your custom extension to fulfil your business needs as we never recommended to modify core files. Let’s take an example of settings up custom sales rules for the city field of the shopping cart page. You can also create custom shopping cart rules for different events.

To do the same first, we need to create “events.xml” file inside etc folder and add paste below code in that file.

app\code\Vendor\Extension\etc\events.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">

    <event name="salesrule_rule_condition_combine">

    <observer name="customer_rule" 
instance="Vendor\Extension\Observer\Shippingcityconditionobserver" />
    </event>
</config>

Now, we create “Shippingcityconditionobserver.php” inside observer folder.

app\code\Vendor\Extension\Observer\Shippingcityconditionobserver.php

<?php
namespace Vendor\Extension\Observer;

class Shippingcityconditionobserver implements \Magento\Framework\Event\ObserverInterface
{
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $additional = $observer->getAdditional();
        $conditions = (array) $additional->getConditions();

        $conditions = array_merge_recursive($conditions, [
            $this->getCustomerFirstOrderCondition()
        ]);

        $additional->setConditions($conditions);
        return $this;
    }

    private function getCustomerFirstOrderCondition()
    {
        return [
            'label'=> __('Shipping city'),
            'value'=> \Vendor\Extension\Model\Rule\Condition\Shippingcity::class
        ];
    }
}

Create one more file “di.xml” file at the following path.

app\code\Vendor\Extension\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="Vendor\Extension\Model\Rule\Condition\Shippingcity">
        <arguments>
            <argument name="data" xsi:type="array">
                <item name="form_name" xsi:type="string">sales_rule_form</item>
            </argument>
        </arguments>
    </type>
</config>

Lastly, create one more file named “Shippingcity.php” at this location.

app\code\Vendor\Extension\Model\Rule\Condition\Shippingcity.php

<?php
namespace Vendor\Extension\Model\Rule\Condition;
class Shippingcity extends \Magento\Rule\Model\Condition\AbstractCondition
{

    protected $_checkoutSession;

    public function __construct(
        \Magento\Rule\Model\Condition\Context $context,
        \Magento\Checkout\Model\Session $checkoutSession,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->_checkoutSession = $checkoutSession;
    }

public function loadAttributeOptions()
    {
        $this->setAttributeOption([
            'shipping_city' => __('Shipping city')
        ]);
        return $this;
    }

    public function getInputType()
    {
       return 'select';  // input type for admin condition
    }

    public function getValueElementType()
    {
        return 'text';
    }

    public function validate(\Magento\Framework\Model\AbstractModel $model)
    {
        $city = $this->_checkoutSession->getQuote()->getShippingAddress()->getCity();
        $model->setData('shipping_city', $city);  // validation value
        return parent::validate($model);
    }
}

Simply clear the cache and you will find an option in admin backend. You can also play with the above code to create different kinds of custom shipping rules.

Lastly, if you found this blog helpful, don’t forget to share it with your colleagues and Magento Friends and Let us know if you are facing any issue while implementing this code.

Happy Coding! ?

 

Previous Article

On-Page SEO Tips for E-commerce Websites to Achieve Success

Next Article

The Ultimate Guide For Starting Your Own E-commerce Store in 2020

Write a Comment
  1. I have 2 questions.
    1. what if we want to validate multi conditional (if-and-if), should we do loop validate method?
    2. if we have ‘multiselect’ on ValueElementType, how to validate it too?
    thanks

  2. Why do we have to define form_name in di.xml ? It works without defining it in di.xml.

  3. After using this code, I am getting infinite loop error while firing setPaymentMethod using graphql query in adobe commerce.

Leave a Comment

Your email address will not be published. Required fields are marked *

Get Connect With Us

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨