2

Can we restrict customer for add to cart once his quote total crosses specific count?

For example i need to restrict customer add to cart action, once the subtotal in quote crosses 500. I have created customer custom attribute called order_limit, can we check this condition and restrict customer to do add to cart action?

I used below event in my events.xml

 <event name="controller_action_predispatch_checkout_cart_add">
    <observer name="checkout_cart_add" instance="[Vendor]\[Module]\Observer\RestrictCart" />
</event>

This is my observer code

class RestrictCart implements ObserverInterface{

protected $_objectManager = null;
protected $_messageManager;
protected $_customerSession; 
protected $quoteFactory; 
protected $_checkoutSession; 
protected $_customer; 

public function __construct(
\Magento\Framework\Message\ManagerInterface $messageManager,
\Magento\Framework\ObjectManagerInterface $objectManager,
\Magento\Customer\Model\Session $customerSession,
\Magento\Quote\Model\QuoteFactory $quoteFactory,
\Magento\Checkout\Model\Session $checkoutSession,
\Magento\Customer\Model\CustomerFactory $customer
){
    $this->_messageManager = $messageManager;
    $this->_objectManager = $objectManager;
    $this->_customerSession = $customerSession; 
    $this->quoteFactory = $quoteFactory;
    $this->_checkoutSession = $checkoutSession;
    $this->_customer = $customer; 
}

public function execute(\Magento\Framework\Event\Observer $observer){

    try{
        if($observer->getRequest()->getParam('product', false)) {               
            $productId = $observer->getRequest()->getParam('product', false);
            $requestedQty = $observer->getRequest()->getParam('qty', false);
            $product = $this->_objectManager->create('Magento\Catalog\Model\Product')->load($observer->getRequest()->getParam('product', false));
            $StockState = $this->_objectManager->get('\Magento\CatalogInventory\Api\StockStateInterface');

            $resource = $this->_objectManager->get('Magento\Framework\App\ResourceConnection');
            $connection = $resource->getConnection();
            if($this->_customerSession->isLoggedIn()){
                $customerId = $this->_customerSession->getCustomer()->getId();
                $cusomerData = $this->getCurrentCustomer($customerId);
                $order_limit = $cusomerData->getOrderLimit();
                $quote = $this->_checkoutSession->getQuote();
                $subTotal = $quote->getSubtotal();
                if($subTotal > $order_limit){
                    $this->_messageManager->addError(__('Order limit Crossed!!!'));
                    return $this;
                }                   
        }


        return $this;
    }catch (\Exception $e) {
        print_r($e->getMessage());
    }
}

public function getQuoteCollection($customerId)
{
    $quote = $this->quoteFactory->create()->getCollection()->addFieldToFilter('customer_id',$customerId);
    return $quote;
}
public function getCurrentCustomer($id){
    $customerObj = $this->_customer->create();
    $customer = $customerObj->load($id);
    return $customer; 
 }
}

This code is working fine only when we add product from detail page, how same thing can be used on updating cart?

2
  • Why you have tried to use controller_action_predispatch_checkout_cart_add ? I donot think is good because this event does not called every time
    – Amit Bera
    Sep 4, 2018 at 8:06
  • okay @amit, i will go with plugin you suggested me Sep 4, 2018 at 8:21

2 Answers 2

1

If you don't want a minimum order amount you can override the native magento feature to save time to invert functionnality. The config is in : config > sales > minimum order amount.

Just override the function validateMinimumAmount($multishipping = false) of the file :

vendor/magento/module-quote/Model/Quote.php

Invert conditions l:2219

if ($amount < $minAmount) { return false; }

in

if ($amount > $minAmount) { return false; }

and l:2230

if ($baseTotal < $minAmount) { return false; }

in

if ($baseTotal > $minAmount) { return false; }

should do the work.

1
  • This will reflect for all customers, can we do it for specific customers? like i have created custom attribute for customer and setting limit for it, so his cart total should not cross it Aug 30, 2018 at 6:02
0

There are two places from where Magento check order minimum amount for order.

validateMinimumAmount(),

As check validateMinimumAmount() at Magento\Quote\Model\Quote and Magento\Quote\Model\Quote\Address

For your requirement, you have to create an aroundPlugin on validateMinimumAmount.

If you don't use multi-address shipping then you have you have to create plugin on Magento\Quote\Model\Quote\Address.

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="\Magento\Quote\Model\Quote\Address">
        <plugin name="order_amount_restrict_on_order_amount" type="VeddorName}\{Module}\Plugin\RestrictOrderamount" sortOrder="10" disabled="false"  />
    </type>
</config>

Plugin Class:

<?php


namespace {VeddorName}\{Module}\Plugin;


class RestrictOrderamount {

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $_scopeConfig;

    public function __construct(
        \Magento\Framework\App\Config\ScopeConfigInterface $_scopeConfig
    ) {

        $this->_scopeConfig = $_scopeConfig;
    }

    public function aroundValidateMinimumAmount(
       \Magento\Quote\Model\Quote\Address $subject,
        callable $proceed,    
        $result    
      )
    {
        $quote = $subject->getQuote();
        $customerId = $quote->getCustomerId();
        $customer = $quote->getCustomer();
        // only worked on loggedin Customer
        if($customerId > 0 && $customer){

            // Assume that yoi
            $order_limit = $customer->getCustomAttribute('$order_limit') == null
            ? null:$customer->getCustomAttribute('$order_limit')->getValue();
            $taxInclude = $this->_scopeConfig->getValue(
                'sales/minimum_order/tax_including',
                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
                $storeId
            );
            $taxes = $taxInclude ? $subject->getBaseTaxAmount() : 0;

           if($order_limit> 0 &&
                   $subject->getBaseSubtotalWithDiscount() + $taxes >= $order_limit)
           {
               return true;
           }else{
               return false;
           }

        }
        return $proceed();
    }
}

Limitation

  • Order amount limit checking only happen oncustomer attribute order_limit when a customer is logged.
  • Also order_limit attribute you have used extension attribute feature.
7
  • Hi Amit, can you please update me code, Aug 30, 2018 at 7:18
  • wait , i will explain in brief
    – Amit Bera
    Aug 30, 2018 at 7:26
  • Yes, i will try this code, can you pls tell when the code executes,? Because i set order limit 100 for one customer, i tried adding product of qty 4 with price 30 each. still its adding to cart Aug 30, 2018 at 7:48
  • validateMinimumAmount will run at Cart page.If the validateMinimumAmount is returning false then a customer cannot go to checkout page. if the user hit checkout page URL directly then they will redirect to cart [age
    – Amit Bera
    Aug 30, 2018 at 7:51
  • Yes, i used your code and tried putting die after customerId, but for me its not showing , i can still go with checkout, Sep 12, 2018 at 13:47

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.