2

I was add a condition action in custom module admin form in magento 2

enter image description here

I used this blog to create a condition action: https://www.mageworx.com/blog/2016/09/magento-2-module-with-conditions-model-fieldset/

Database:

enter image description here

how we can apply those saved condition in the frontend?

23
  • where you want to apply that condition? Commented Nov 22, 2019 at 5:31
  • i need to above condition will applied to restrict payment method, Reference extension meetanshi.com/magento-2-payment-restrictions.html Commented Nov 22, 2019 at 6:18
  • prnt.sc/q0f3uv Commented Nov 22, 2019 at 6:25
  • Well, It's long process to do that. It would be better to solve your question in small parts. Commented Nov 22, 2019 at 6:35
  • i was completed every part in the extension except the conditions to be met, based on cart attributes, customer attributes Commented Nov 22, 2019 at 7:04

4 Answers 4

3
+50

Any rule-model could be used this way:

$ruleModel->validate($validationModel);

But your rule model must extend the \Magento\Rule\Model\AbstractModel class and object which you will validate must have desired data (subtotal in your case, so I suppose it will be instance of \Magento\Quote\Model\Quote\Address).

So, an example will be looking like this:

$address = $block->getAddress(); // or $quote->getAddress();
$rules = $block->getRules(); // load all availabel rules from DB
foreach ($rules as $rule) {
    if ($rule->validate($address)) {
        echo __('Pass conditions of the rule %1', $rule->getId());
    } else {
        echo __('Missed rule %1', $rule->getId());
    }
}

The $rule->validate() will call this code:

/**
 * Validate rule conditions to determine if rule can run
 *
 * @param \Magento\Framework\DataObject $object
 * @return bool
 */
public function validate(\Magento\Framework\DataObject $object)
{
    return $this->getConditions()->validate($object);
}
7
  • It reflects a Fatal error: call to a member function validate() on string Commented Nov 26, 2019 at 12:10
  • @divyasekar Check why your $rule is a string. It must be instance of \Magento\Rule\Model\AbstractModel How you load a rules? Commented Nov 26, 2019 at 12:33
  • Thank you so much @Siarhey Uchukhlebau finally i done it by your way Commented Nov 28, 2019 at 6:55
  • @divyasekar I'm glad to help you :) Commented Nov 28, 2019 at 7:27
  • 1
    here i explained in detail magento.stackexchange.com/questions/298484/… can please help me Commented Dec 12, 2019 at 9:21
2

Updated

Finally i found out a way for validate a condition by @Siarhey Uchukhlebau answer

<?php
namespace Vendor\Module\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
     protected $_pageFactory;
     protected $cart;
     protected $quoteFactory;
     Protected $rule;
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $pageFactory,
        \Magento\Checkout\Model\Cart $cart,
        \Magento\Quote\Model\Quote\Address $quoteFactory,
        \Vendor\Module\Model\Rule $rule
   )
    {
        $this->_pageFactory = $pageFactory;
        $this->cart = $cart;
        $this->quoteFactory = $quoteFactory;
        $this->rule = $rule;
        return parent::__construct($context);
    }
    public function execute()
    {

    // Testing execution 

        $quoteId = $this->cart->getQuote()->getId();
        $quoteAddress = $this->quoteFactory->getCollection();
        $rules = $this->rule->getCollection();
        $validate =array();

        foreach ($quoteAddress as $address):
            if( $quoteId == $address['quote_id']):
                $addressId = $address['address_id'];
            endif;    
        endforeach;
        foreach($rules as $rule):
           $quote = $this->quoteFactory->load($addressId);
           $validate = $rule->validate($quote);
        endforeach;
        return  $validate;
    }
    public function validate(\Magento\Framework\DataObject $object)
    {
        return $this->getConditions()->validate($object);
    }

}

Vendor/Module/Model/Rule.php

<?php
namespace Vendor/Module\Model;
use Magento\Quote\Model\Quote\Address;
use Magento\Rule\Model\AbstractModel;
/**
 * Class Rule
 * @package Vendor\Module\Model
 *
 * @method int|null getRuleId()
 * @method Rule setRuleId(int $id)
 */
class Rule extends AbstractModel
{
    /**
     * Prefix of model events names
     *
     * @var string
     */
    protected $_eventPrefix = 'vendor_module';
    /**
     * Parameter name in event
     *
     * In observe method you can use $observer->getEvent()->getRule() in this case
     *
     * @var string
     */
    protected $_eventObject = 'rule';
    /** @var \Magento\SalesRule\Model\Rule\Condition\CombineFactory */
    protected $condCombineFactory;
    /** @var \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory */
    protected $condProdCombineF;
    /**
     * Store already validated addresses and validation results
     *
     * @var array
     */
    protected $validatedAddresses = [];
    /**
     * @param \Magento\Framework\Model\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Data\FormFactory $formFactory
     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
     * @param \Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory
     * @param \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF
     * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
     * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
     * @param array $data
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
     \Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory,
     \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF,
       \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->condCombineFactory = $condCombineFactory;
        $this->condProdCombineF = $condProdCombineF;
        parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
    }
    /**
     * Set resource model and Id field name
     *
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->_init('Vendor\Module\Model\ResourceModel\Rule');
        $this->setIdFieldName('rule_id');
    }
    /**
     * Get rule condition combine model instance
     *
     * @return \Magento\SalesRule\Model\Rule\Condition\Combine
     */
      public function getConditionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    /**
     * Get rule condition product combine model instance
     *
     * @return \Magento\SalesRule\Model\Rule\Condition\Product\Combine
     */
    public function getActionsInstance()
    {
        return $this->condProdCombineF->create();
    }
    /**
     * Check cached validation result for specific address
     *
     * @param Address $address
     * @return bool
     */
    public function hasIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? true : false;
    }
    /**
     * Set validation result for specific address to results cache
     *
     * @param Address $address
     * @param bool $validationResult
     * @return $this
     */
    public function setIsValidForAddress($address, $validationResult)
    {
        $addressId = $this->_getAddressId($address);
        $this->validatedAddresses[$addressId] = $validationResult;
        return $this;
    }
    /**
     * Get cached validation result for specific address
     *
     * @param Address $address
     * @return bool
     * @SuppressWarnings(PHPMD.BooleanGetMethodName)
     */
    public function getIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? $this->validatedAddresses[$addressId] : false;
    }
    /**
     * Return id for address
     *
     * @param Address $address
     * @return string
     */
    private function _getAddressId($address)
    {
        if ($address instanceof Address) {
            return $address->getId();
        }
        return $address;
    }
}
3
  • Hi @divyasekar, Rajan here, can you please let me know if you have added a condition like subtotal greater than 100 then it will apply on your rule so in your code where is that code on which it will take your rule condition?
    – Rajan Soni
    Commented Nov 28, 2019 at 11:25
  • i didn't get you rajan, let me please clarify me if you asking about how to validate a condition rule? (or) where going to validate a condition rule? Commented Nov 28, 2019 at 11:49
  • i was take rule from model file and validate a condition on (controller or observer) file that you required. let see my edited post @rajan Commented Nov 28, 2019 at 12:06
1

As I understand your question, You need to convert serialize value into unserialize form. For that, Use this below code :

protected $salesRuleFactory;
protected $serializer;

public function __construct(
    \Magento\SalesRule\Model\RuleFactory $salesRuleFactory,
    \Magento\Framework\Serialize\Serializer\Json $serializer
){
    $this->salesRuleFactory = $salesRuleFactory;
    $this->serializer = $serializer;
}


public function yourFunction()
{   
    $ruleId = 1;
    $rule = $this->salesRuleFactory->create()->load($ruleId);
    print_r($this->serializer->unserialize($rule->getConditionsSerialized()));
}

Output :

Array
(
    [type] => Magento\SalesRule\Model\Rule\Condition\Combine
    [attribute] => 
    [operator] => 
    [value] => 1
    [is_value_processed] => 
    [aggregator] => all
    [conditions] => Array
        (
            [0] => Array
                (
                    [type] => Magento\SalesRule\Model\Rule\Condition\Product\Found
                    [attribute] => 
                    [operator] => 
                    [value] => 1
                    [is_value_processed] => 
                    [aggregator] => all
                    [conditions] => Array
                        (
                            [0] => Array
                                (
                                    [type] => Magento\SalesRule\Model\Rule\Condition\Product
                                    [attribute] => category_ids
                                    [operator] => ()
                                    [value] => 25,16
                                    [is_value_processed] => 
                                    [attribute_scope] => 
                                )

                        )

                )

        )

)

Then, you can get value from this array based on your requirements.

2
  • In magento 2.1.3 ver, shows a error of class magento\framework\serialize\serializer\json does not exist Commented Nov 26, 2019 at 12:08
  • Oh....!! Strange .. Commented Nov 26, 2019 at 12:34
1

Use this code:

$product_id = '1';
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$customer_group = $objectManager->get('\Magento\Customer\Model\Session')->getCustomer()->getGroupId();
$rules = $objectManager->create('\Magento\SalesRule\Model\RuleFactory')->create()->getCollection();
$rules->setValidationFilter(1, $customer_group);
$rules->setOrder('sort_order', 'ASC');
foreach ($rules as $rule) {
    $product = $objectManager->get('Magento\Catalog\Model\Product')->load($product_id);
    $item = $objectManager->create('Magento\Catalog\Model\Product');
    $item->setProduct($product);
    $validate = $rule->getActions()->validate($item);
    // Validate rule for product
    if ($validate) {
        $dataToEncode = $rule->getConditionsSerialized();
        $conditions = $this->json->unserialize($dataToEncode);
        $countCondition = count($conditions);
        if ($countCondition >= 7) {
            // Write your code based on $conditions
        }
    }
}
6
  • i was get a fatal error prnt.sc/q1qeu3 Commented Nov 25, 2019 at 11:55
  • Tru $rule->validate($item); or else add your controller code in question. Commented Nov 25, 2019 at 12:05
  • above function works for catalog rule but i need to validate cart details like subtotal, shipping country etc @Dhaduk Mitesh its there any possible ways to check a cart details Commented Nov 27, 2019 at 7:57
  • You just load your cart product here in payment page. And if it is validate for your item then you can do anything in if ($validate). Commented Nov 27, 2019 at 9:15
  • If you have your custom rule then you can get rule from custom model and set in $rules. Commented Nov 27, 2019 at 9:16

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.