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
- 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>
- 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:
- 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>
- 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