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?

2
+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);
}
  • It reflects a Fatal error: call to a member function validate() on string – divya sekar Nov 26 '19 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? – Siarhey Uchukhlebau Nov 26 '19 at 12:33
  • Thank you so much @Siarhey Uchukhlebau finally i done it by your way – divya sekar Nov 28 '19 at 6:55
  • @divyasekar I'm glad to help you :) – Siarhey Uchukhlebau Nov 28 '19 at 7:27
  • 1
    here i explained in detail magento.stackexchange.com/questions/298484/… can please help me – divya sekar Dec 12 '19 at 9:21
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.

  • In magento 2.1.3 ver, shows a error of class magento\framework\serialize\serializer\json does not exist – divya sekar Nov 26 '19 at 12:08
  • Oh....!! Strange .. – Rohan Hapani Nov 26 '19 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
        }
    }
}
  • i was get a fatal error prnt.sc/q1qeu3 – divya sekar Nov 25 '19 at 11:55
  • Tru $rule->validate($item); or else add your controller code in question. – Dhaduk Mitesh Nov 25 '19 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 – divya sekar Nov 27 '19 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). – Dhaduk Mitesh Nov 27 '19 at 9:15
  • If you have your custom rule then you can get rule from custom model and set in $rules. – Dhaduk Mitesh Nov 27 '19 at 9:16
1

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;
    }
}
  • 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 Nov 28 '19 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? – divya sekar Nov 28 '19 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 – divya sekar Nov 28 '19 at 12:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.