Magento 2: Custom cart price rule condition

conditionmagento2shopping-cart-price-rules

I want to create a cart price rule condition that checks for a cart item's buyRequest object to act upon it accordingly. A rule should only be applied when that buyRequest contains a certain value.

I followed this howto to create a custom condition for cart price rules.
However the condition created shows up in the "conditions" section of the rule.

enter image description here

But I need my condition in the "actions" part of the rule as a cart item condition:

enter image description here

I feel like I am so close but I can't quite figure it out. I also browsed through the core's code for the existing 3 cart item attributes ("Price in cart", "Quantity in cart" and "Row total in cart") but could not figure out what they are doing different to show up down there.

Any hint is welcome, thank you.

Best Answer

To add new conditions under Cart Item Attribute you need to follow the below steps:

Step 1: Create registration.php under

app/code/M2Expert/SalesRule/registration.php

with below content:

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'M2Expert_SalesRule',
    __DIR__ );

Step 2: Create module.xml under

app/code/M2Expert/SalesRule/etc/module.xml

with content:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="M2Expert_SalesRule" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Backend"/>
            <module name="Magento_Sales"/>
            <module name="Magento_Quote"/>
            <module name="Magento_Checkout"/>
            <module name="Magento_Catalog" />
            <module name="Magento_ConfigurableProduct" />
        </sequence>
    </module>
</config>

Step 3: Create di.xml under:

app/code/M2Expert/SalesRule/etc/di.xml

with content:

<?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\Condition\Product">
        <plugin name="sales_rule_custom_condition" sortOrder="100" type="M2Expert\SalesRule\Plugin\SalesRule\Conditions\Product"/>
    </type>
</config>

Step 4: Create Product.php under

app/code/M2Expert/SalesRule/Plugin/SalesRule/Conditions/Product.php

with content:

<?php

namespace M2Expert\SalesRule\Plugin\SalesRule\Conditions;

use Magento\Config\Model\Config\Source\Yesno as SourceConfig;

/**
 * Additional attr for validator.
 */
class Product
{
    /**
     * Name For Condition Attribute
     */
    public const CONDITION_ATTRIBUTE_NAME = 'quote_item_is_custom_condition';

    /**
     * @var SourceConfig
     */
    private $sourceConfig;

    public function __construct(
        SourceConfig $sourceConfig
    ) {
        $this->sourceConfig = $sourceConfig;
    }

    /**
     * @param \Magento\Rule\Model\Condition\Product\AbstractProduct $subject
     * @param \Magento\SalesRule\Model\Rule\Condition\Product $result
     *
     * @return \Magento\SalesRule\Model\Rule\Condition\Product
     */
    public function afterLoadAttributeOptions(
        \Magento\Rule\Model\Condition\Product\AbstractProduct $subject,
        \Magento\SalesRule\Model\Rule\Condition\Product $result
    ) {
        $attributes = $subject->getAttributeOption();
        $attributes[self::CONDITION_ATTRIBUTE_NAME] = __('My custom condition');
        $subject->setAttributeOption($attributes);

        return $result;
    }

    /**
     * @param \Magento\Rule\Model\Condition\Product\AbstractProduct $subject
     * @param $result
     *
     * @return array
     */
    public function afterGetValueSelectOptions(\Magento\Rule\Model\Condition\Product\AbstractProduct $subject, $result)
    {
        if ($subject->getAttribute() === self::CONDITION_ATTRIBUTE_NAME) {

            return $this->sourceConfig->toOptionArray();
        }

        return $result;
    }

    /**
     * @param \Magento\Rule\Model\Condition\Product\AbstractProduct $subject
     * @param string $result
     *
     * @return string
     */
    public function afterGetInputType(\Magento\Rule\Model\Condition\Product\AbstractProduct $subject, $result)
    {
        if ($subject->getAttribute() === self::CONDITION_ATTRIBUTE_NAME) {
            return 'boolean';
        }

        return $result;
    }

    /**
     * @param \Magento\Rule\Model\Condition\Product\AbstractProduct $subject
     * @param string $result
     *
     * @return string
     */
    public function afterGetValueElementType(\Magento\Rule\Model\Condition\Product\AbstractProduct $subject, $result)
    {
        if ($subject->getAttribute() === self::CONDITION_ATTRIBUTE_NAME) {
            return 'select';
        }

        return $result;
    }

    /**
     * @param \Magento\Rule\Model\Condition\Product\AbstractProduct $subject
     * @param array $result
     *
     * @return array
     */
    public function afterGetOperatorSelectOptions(
        \Magento\Rule\Model\Condition\Product\AbstractProduct $subject,
        $result
    ) {
        if ($subject->getAttribute() === self::CONDITION_ATTRIBUTE_NAME) {
            foreach ($result as $key => $item) {
                if ($item['value'] === '<=>') {
                    unset($result[$key]);
                }
            }
        }

        return $result;
    }

    /**
     * @param \Magento\Rule\Model\Condition\Product\AbstractProduct $subject
     * @param \Magento\Framework\Model\AbstractModel $object
     */
    public function beforeValidate(
        \Magento\Rule\Model\Condition\Product\AbstractProduct $subject,
        \Magento\Framework\Model\AbstractModel $object
    ) {
        if ($object instanceof \Magento\Quote\Api\Data\CartItemInterface
            && $object->getQuote()
            && $object->getQuote()->getItems()
        ) {
            // your logic goes here
        }
    }
}

Thats it!!!! Run all the necessary commands and check in admin.

Related Topic