Keep Limit for Guest Customer Coupon Usage

Keep Limit for Guest Customer Coupon Usage

Hello Guys,

Welcome Back to our Magento Academy!
Subscribe Our Blog and Keep updated.
In Magento Default you can add limit for maximum usage of coupon per customer which works only for Registered customer but not for Guest Customer.
In Today Topic We are showing you how you can keep limit of usage of coupons for guest customer,
So First of all you need to create a module as Below
NameSpace/SalesRule
create registration.php File
<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'NameSpace_SalesRule',
    __DIR__
);
 
 
then create etc/module.xml
 
 
<?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="NameSpace_SalesRule" setup_version="1.0.0">
        <sequence>
            <module name="Magento_SalesRule"/>
        </sequence>
    </module>
</config>
 
Now create etc/db_schema.xml
 
It will create a table salesrule_guest same as salesrule_customer but here we are taking
customer email instead of customer_id

<?xml version="1.0"?>
 
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
       
    <table name="salesrule_guest" resource="default" engine="innodb" comment="Salesrule Guest">
        <column xsi:type="int" name="rule_guest_id" padding="10" unsigned="true" nullable="false" identity="true"
                comment="Rule Guest Id"/>
        <column xsi:type="int" name="rule_id" padding="10" unsigned="true" nullable="false" identity="false" default="0"
                comment="Rule ID"/>
        <column xsi:type="varchar" name="customer_email"  nullable="true"
                 comment="Customer Email"/>
        <column xsi:type="smallint" name="times_used" padding="5" unsigned="true" nullable="false" identity="false"
                default="0" comment="Times Used"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="rule_guest_id"/>
        </constraint>
        <index referenceId="SALESRULE_CUSTOMER_RULE_ID_CUSTOMER_EMAIL" indexType="btree">
            <column name="rule_id"/>
            <column name="customer_email"/>
        </index>
        <index referenceId="SALESRULE_CUSTOMER_CUSTOMER_EMAIL_RULE_ID" indexType="btree">
            <column name="customer_email"/>
            <column name="rule_id"/>
        </index>
    </table>
</schema>

Create Module File Model\Rule\Guest.php

<?php
 
namespace NameSpace\SalesRule\Model\Rule;

 
class Guest extends \Magento\Framework\Model\AbstractModel
{
    /**
     * Constructor
     *
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->_init(\NameSpace\SalesRule\Model\ResourceModel\Rule\Guest::class);
    }
    /**
     * Load by customer rule
     *
     * @param int $customerId
     * @param int $ruleId
     * @return $this
     */
    public function loadByGuestRule($customerEmail, $ruleId)
    {
        $this->_getResource()->loadByGuestRule($this, $customerEmail, $ruleId);
        return $this;
    }
}

Create ResourceModel File Model\ResourceModel\Rule\Guest.php

<?php
 amespace NameSpace\SalesRule\Model\ResourceModel\Rule;

 
class Guest extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    /**
     * Constructor
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('salesrule_guest', 'rule_guest_id');
    }
 
    public function loadByGuestRule($rule, $customerEmail, $ruleId)
    {
        $connection = $this->getConnection();
        $select = $connection->select()->from(
            $this->getMainTable()
        )->where(
            'customer_email = :customer_email'
        )->where(
            'rule_id = :rule_id'
        );
        $data = $connection->fetchRow($select, [':rule_id' => $ruleId, ':customer_email' => $customerEmail]);
        if (false === $data) {
            // set empty data, as an existing rule object might be used
            $data = [];
        }
        $rule->setData($data);
        return $this;
    }
}

Create Collection File Model\ResourceModel\Rule\Guest\Collection.php

<?php
 
namespace NameSpace\SalesRule\Model\ResourceModel\Rule\Guest;

 
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * Collection constructor
     *
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->_init(
            \NameSpace\SalesRule\Model\Rule\Guest::class,
            \NameSpace\SalesRule\Model\ResourceModel\Rule\Guest::class
        );
    }
}



 
Now create after Plugin for canProcessRule() function 
of Magento\SalesRule\Model\Utility with name like Plugin/UtilityPlugin.php 
 
<?php
 
namespace NameSpace\SalesRule\Plugin;

use Magento\SalesRule\Model\Utility;

/**
 * Plugin For Utility
 */
class UtilityPlugin
{
   
    /**
     * @var OrderCollectionFactory
     */
    protected $ruleGuestFactory;
    /**
     * UtilityPlugin constructor.
     * @param Request $request
     */
    public function __construct(        
        \NameSpace\SalesRule\Model\Rule\GuestFactory $ruleGuestFactory
    ) {
        
        $$this->ruleGuestFactory = $ruleGuestFactory;
    }
    
     
    public function afterCanProcessRule(Utility $subject, $result, $rule, $address)
    {
        if($result == false) {
            return $result;
        }
        
 */
      $ruleId = $rule->getId();
      if ($ruleId && $rule->getUsesPerCustomer()) {
          $customerEmail = $address->getQuote()->getCustomerEmail();
           /** @var \NameSpace\SalesRule\Model\Rule\Guest $ruleGuest */
          $ruleGuest = $this->ruleGuestFactory->create();
          $ruleGuest->loadByGuestRule($customerEmail, $ruleId);
          if ($ruleGuest->getId()) {
              if ($ruleGuest->getTimesUsed() >= $rule->getUsesPerCustomer()) {
                 $rule->setIsValidForAddress($address, false);
                 return false;
              }
          }
        return $result;
      }
    }
 
 
}//end class  
 
Hope It will work for you
Subscribe Our Blog and Keep updated.
 
Thanks and Keep Visiting!

Leave a Reply
Your email address will not be published. *