1

In my website i have bounded the user to only add one product into the cart , however from the session quote object it loads multiple products. How can i restrict quote object to show only last added the product in the checkout. I have tried out my solution in the session.php by overriding it.

Can any one suggest what change i need to make more in the below code to restrict the quote object with lastly added item.

<?php 
namespace Project\Cart\Model;
class Session extends \Magento\Checkout\Model\Session{
const CHECKOUT_STATE_BEGIN = 'begin';

/**
 * Quote instance
 *
 * @var Quote
 */
protected $_quote;

/**
 * Customer Data Object
 *
 * @var CustomerInterface|null
 */
protected $_customer;

/**
 * Whether load only active quote
 *
 * @var bool
 */
protected $_loadInactive = false;

/**
 * Loaded order instance
 *
 * @var \Magento\Sales\Model\Order
 */
protected $_order;

/**
 * @var \Magento\Sales\Model\OrderFactory
 */
protected $_orderFactory;

/**
 * @var \Magento\Customer\Model\Session
 */
protected $_customerSession;

/**
 * @var \Magento\Quote\Api\CartRepositoryInterface
 */
protected $quoteRepository;

/**
 * @var \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress
 */
protected $_remoteAddress;

/**
 * @var \Magento\Framework\Event\ManagerInterface
 */
protected $_eventManager;

/**
 * @var \Magento\Store\Model\StoreManagerInterface
 */
protected $_storeManager;

/**
 * @var \Magento\Customer\Api\CustomerRepositoryInterface
 */
protected $customerRepository;

/**
 * @param QuoteIdMaskFactory
 */
protected $quoteIdMaskFactory;

/**
 * @param bool
 */
protected $isQuoteMasked;

/**
 * @var \Magento\Quote\Model\QuoteFactory
 */
protected $quoteFactory;



public function loadCustomerQuote()
{
    if (!$this->_customerSession->getCustomerId()) {
        return $this;
    }

    $this->_eventManager->dispatch('load_customer_quote_before', ['checkout_session' => $this]);

    try {
        $customerQuote = $this->quoteRepository->getForCustomer($this->_customerSession->getCustomerId());
    } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
        $customerQuote = $this->quoteFactory->create();
    }
    $customerQuote->setStoreId($this->_storeManager->getStore()->getId());
    $allItems = $customerQuote->getAllVisibleItems();
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    //$quoteId = get quote id 
    $quoteItemObj = $objectManager->create('\Magento\Quote\Model\Quote\Item');
    $i=0;
    $cartObj = $objectManager->create('\Magento\Checkout\Model\Cart');

    if(isset($allItems) && count($allItems) > 0) {
        foreach ($allItems as $item) 
        {
            $i++;
            $quoteItem = $quoteItemObj->load($item->getItemId());
            if(count($allItems) != $i) {
                $quoteItem->delete();//delete item
            }
        }
        $cartObj->save();
    }
    if ($customerQuote->getId() && $this->getQuoteId() != $customerQuote->getId()) {
        if($this->getQuoteId() != "") {
            $quote = $this->quoteRepository->get($this->getQuoteId());
            if ($this->_quote) {
                $this->quoteRepository->delete($this->getQuote());
            }
            //$this->quoteRepository->delete($this->getQuoteId());

            //$items = $quote->getAllItems();
            $this->setQuoteId($customerQuote->getId());
            //$quote = $this->quoteRepository->get($quote->getId());
            //$quote->setCustomerId($this->_customerSession->getCustomerId());
            $this->quoteRepository->save($customerQuote);

            // if ($this->_quote) {
                // $this->quoteRepository->delete($this->_quote);
            // }
            $this->_quote = $customerQuote;
        }
    } else {
        $this->getQuote()->getBillingAddress();
        $this->getQuote()->getShippingAddress();
        $this->getQuote()->setCustomer($this->_customerSession->getCustomerDataObject())
            ->setTotalsCollectedFlag(false)
            ->collectTotals();
        $this->quoteRepository->save($this->getQuote());
    }
    return $this;
}
}
8
  • You can use Buy Now functionality. if you want to allow only one product to purchase at time Commented Dec 27, 2017 at 11:50
  • THe functionality on the website is somewhat different with the buy now default functionality. So i had to implement it by custom overriding. Commented Dec 27, 2017 at 11:53
  • Could you please tell me exact requirement so accordingly . i will try to help you. Commented Dec 27, 2017 at 11:55
  • In the implementation we allow only one product with multiple quantities of the same product can be added to the cart , but not the different products in the single order also modification or adding of buy now will require lot of modifications in the implementation as per the dependency. Commented Dec 27, 2017 at 11:58
  • you can use observer like checkout_cart_product_add_after and remove existing product with your condition. Commented Dec 27, 2017 at 12:02

1 Answer 1

4

Try following way:

app/code/SR/Stackexchange/etc/frontend/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\Checkout\Model\Cart">
        <plugin name="SR_Stackexchange::add_to_cart" type="SR\Stackexchange\Plugin\Checkout\Model\Cart" sortOrder="1"/>
    </type>
</config>

app/code/SR/Stackexchange/Plugin/Checkout/Model/Cart.php


namespace SR\Stackexchange\Plugin\Checkout\Model;

use Magento\Catalog\Model\Product;

class Cart
{
    /**
     * @var \Magento\Checkout\Model\Session
     */
    protected $checkoutSession;

    /**
     * Cart constructor.
     *
     * @param \Magento\Checkout\Model\Session $checkoutSession
     */
    public function __construct(
        \Magento\Checkout\Model\Session $checkoutSession
    ) {
        $this->checkoutSession = $checkoutSession;
    }

    /**
     * @param \Magento\Checkout\Model\Cart $subject
     * @param \Closure $proceed
     * @param $productInfo
     * @param null $requestInfo
     * @return mixed
     */
    public function aroundAddProduct(
        \Magento\Checkout\Model\Cart $subject,
        \Closure $proceed,
        $productInfo,
        $requestInfo = null
    ) {

        if ($productInfo instanceof Product) {
            $productId = $productInfo->getId();
        } elseif (is_int($productInfo) || is_string($productInfo)) {
            $productId = $productInfo;
        } else {
            return $proceed($productInfo, $requestInfo);
        }

        $isSameProduct = 0;
        $quote = $this->checkoutSession->getQuote();
        $items = $quote->getAllItems();
        foreach ($items as $item) {
            if($productId == $item->getProductId()) {
                $isSameProduct = 1;
                break;
            }
        }

        if($isSameProduct) {
            return $proceed($productInfo, $requestInfo);
        }

        $quote->removeAllItems()->save();
        return $proceed($productInfo, $requestInfo);
    }
}

Now you need to modify when merging quote after login: app/code/SR/Stackexchange/etc/frontend/events.xml


<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_quote_merge_before">
        <observer name="SR_Stackexchange_sales_quote_merge_before" instance="SR\Stackexchange\Observer\SalesQuoteMergeBefore"/>
    </event>
</config>

app/code/SR/Stackexchange/Observer/SalesQuoteMergeBefore.php


namespace SR\Stackexchange\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;

class SalesQuoteMergeBefore implements ObserverInterface
{
    /**
     * Avoid shopping carts merging on customer login
     *
     * @param EventObserver $observer
     */
    public function execute(EventObserver $observer)
    {
        if ($observer->getSource()->hasItems()) {
            $currentQuote = $observer->getSource();
            $productId = 0;
            foreach ($currentQuote->getAllVisibleItems() as $item) {
                $productId = $item->getProductId();
            }

            if (is_object($observer->getQuote()) && $observer->getQuote()->getId()) {
                $oldQuote = $observer->getQuote();
                $hasSameProduct = 0;
                foreach ($oldQuote->getAllVisibleItems() as $item) {
                    if($productId == $item->getProductId()) {
                        $hasSameProduct = 1;
                    }
                }
                if($hasSameProduct == 0) {
                    $observer->getQuote()->removeAllItems();
                }
            }
        }
    }
}

Clear cache.

NB: You can change 'SR/Stackexchange' your own module name

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.