5

I want to set in our website reserve product after add to the basket.

example:

Shoes available in stock: 5 pcs.

When customer add 2 pcs to the basket then now in website is available 3 pcs.

After 24 hours when customer no finalize trasaction then delete product from basket and return this 2 pcs to stock.

Any solution?

4

I have the solution for you but there are some major issues with decreasing stock when you add the product to cart. If a customer adds maximum products cart, then someone next can't add more because it is out of stock. So please make sure you understand what you are doing.

- Create an event to the observer when a product is added to cart

  1. app/code/Training/Test/etc/frontend/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_quote_product_add_after">
        <observer name="training_test_inventory" instance="Training\Test\Observer\DecreaseStockObserver"/>
    </event>
</config>
  1. app/code/Training/Test/Observer/DecreaseStockObserver.php
<?php

namespace Training\Test\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\CatalogInventory\Api\StockManagementInterface;
use Magento\Framework\Event\Observer;
use Magento\CatalogInventory\Observer\ItemsForReindex;
use Magento\CatalogInventory\Observer\ProductQty;

class DecreaseStockObserver implements ObserverInterface
{

    /**
     * @var StockManagementInterface
     */
    private $stockManagement;

    /**
     * @var ItemsForReindex
     */
    private $itemsForReindex;
    /**
     * @var ProductQty
     */
    private $productQty;

    /**
     * SubtractQuoteInventoryObserver constructor.
     * @param StockManagementInterface $stockManagement
     * @param ProductQty $productQty
     * @param ItemsForReindex $itemsForReindex
     */
    public function __construct(
        StockManagementInterface $stockManagement,
        ProductQty $productQty,
        ItemsForReindex $itemsForReindex
    ) {
        $this->stockManagement = $stockManagement;
        $this->productQty = $productQty;
        $this->itemsForReindex = $itemsForReindex;
    }

    /**
     * @param Observer $observer
     * @return void
     */
    public function execute(Observer $observer)
    {
        $event = $observer->getEvent();
        $items = $this->productQty->getProductQty($event->getItems());
        $itemsForReindex = $this->stockManagement->registerProductsSale(
            $items
        );
        $this->itemsForReindex->setItems($itemsForReindex);
    }
}
  • Create a cronjob to delete carts and revert qty to stock:
  1. app/code/Training/Test/etc/crontab.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="default">
        <job name="training_flush_quotes" instance="Training\Test\Cron\FlushQuotes"
             method="execute">
            <schedule>0 * * * *</schedule>
        </job>
    </group>
</config>
  1. app/code/Training/Test/Cron/FlushQuotes.php
<?php

namespace Training\Test\Cron;

use Magento\Quote\Api\CartRepositoryInterface;
use Magento\CatalogInventory\Api\StockManagementInterface;
use Magento\CatalogInventory\Observer\ProductQty;
use Magento\Framework\Api\SearchCriteriaBuilder;

class FlushQuotes
{
    private $cartRepository;
    /**
     * @var StockManagementInterface
     */
    private $stockManagement;
    /**
     * @var SearchCriteriaBuilder
     */
    private $searchCriteriaBuilder;
    /**
     * @var ProductQty
     */
    private $productQty;
    /**
     * @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor
     */
    protected $stockIndexerProcessor;

    /**
     * @var \Magento\Catalog\Model\Indexer\Product\Price\Processor
     */
    protected $priceIndexer;

    /**
     * PreviewQuotaManager constructor.
     * @param CartRepositoryInterface $cartRepository
     * @param StockManagementInterface $stockManagement
     * @param ProductQty $productQty
     * @param SearchCriteriaBuilder $searchCriteriaBuilder
     * @param \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexerProcessor
     * @param \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer
     */
    public function __construct(
        CartRepositoryInterface $cartRepository,
        StockManagementInterface $stockManagement,
        ProductQty $productQty,
        SearchCriteriaBuilder $searchCriteriaBuilder,
        \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexerProcessor,
        \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer
    ) {
        $this->cartRepository = $cartRepository;
        $this->stockManagement = $stockManagement;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        $this->productQty = $productQty;
        $this->stockIndexerProcessor = $stockIndexerProcessor;
        $this->priceIndexer = $priceIndexer;
    }

    /**
     * @return void
     * @throws \Exception
     */
    public function execute()
    {
        $carts = $this->cartRepository->getList($this->searchCriteriaBuilder->create())
            ->getItems();
        foreach ($carts as $cart) {
            /** @var \Magento\Quote\Api\Data\CartInterface $cart */
            $this->revertProductsSales($cart);
            $this->cartRepository->delete($cart);
        }

    }

    /**
     * @param $cart
     */
    private function revertProductsSales(\Magento\Quote\Api\Data\CartInterface $cart)
    {
        $items = $cart->getAllItems();
        $itemsToUpdate = $this->productQty->getProductQty($items);
        $this->stockManagement->revertProductsSale(
            $itemsToUpdate
        );
        if (!empty($itemsToUpdate)) {
            $updatedItemIds = array_keys($itemsToUpdate);
            $this->stockIndexerProcessor->reindexList($updatedItemIds);
            $this->priceIndexer->reindexList($updatedItemIds);
        }
    }
}

Try this solution, maybe it will solve your issue

Regards

  • I created this files and upload on server. After php bin/magento setup:upgrade and cache clean I try add pieces to the basket but after this still this pcs available on store. – Sylvester Dec 27 '18 at 18:04
  • I tested on my local environment, it is still working. But you still have to fix some issues about stock after place the order, add same product to cart, update cart and any issue that you can detect. As I said, this is only the solution I can suggest you, it is not a full module – bachlee89 Dec 28 '18 at 0:29
  • Can you help is detect issue and help fix it ? – Sylvester Dec 28 '18 at 18:34
  • @Sylvester did you add the registration.php and etc/module.xml files? – Arno Vande Cappelle Jan 2 '19 at 16:44
  • @ Arno Vende Cappelle, No, I only added step by step solution Lee provide. – Sylvester Jan 2 '19 at 19:03
0

For all those who land here from google, it looks like it is better to use the Magento Reservations API now, which is part of Magento Multi-Stock-Inventory module, see this: https://devdocs.magento.com/guides/v2.3/inventory/reservations.html

You would probably bind to the same events as @bachlee89 showed in his solution, but instead of decreasing quantity in stock - you create a reservation and then reset/clean up it on a cron-job for abandoned carts.

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.