Magento-2.4.3- Backorders – Inconsistent reference for an interface IsProductSalableInterface

Today, 25.10.2020. I faced a problem is:

There is an inconsistency that a class reference for interface \Magento\InventorySalesApi\Api\IsProductSalableInterface is different between Adminhtml scope and Frontend scope. And “add-to-cart” functionality does not work properly If a stock status of a product is a backorder.

Preconditions:

Magento 2.4.3

Steps to reproduce:

Set a product to be “backorders”

All inventory source items are “Out of Stock”

Actual Result:

I can’t see a button “Add into cart” on a frontend. A product has is_saleable’s value is FALSE

Expected Result:

A product has is_saleable’s value is TRUE

Problem-solving:

There is an inconsistency that a class reference for interface \Magento\InventorySalesApi\Api\IsProductSalableInterface is different between Adminhtml scope and Frontend scope.

You can check di files to find which class will reference to IsProductSalableInterface:

  • vendor/magento/module-inventory-indexer/etc/frontend/di.xml
<preference for="Magento\InventorySalesApi\Api\IsProductSalableInterface" type="Magento\InventoryIndexer\Model\IsProductSalable"/>
  • vendor/magento/module-inventory-sales/etc/di.xml
<preference for="Magento\InventorySalesApi\Api\IsProductSalableInterface" type="Magento\InventorySales\Model\IsProductSalableCondition\IsProductSalableConditionChain"/>

The first one defines a reference for Frontend scope, so when a system checks a product is whether saleable or not, it will use Magento\InventoryIndexer\Model\IsProductSalable.

My Solution :

  • Create a new module
  • Create etc/frontend/di.xml
<preference for="Magento\InventorySalesApi\Api\IsProductSalableInterface" type="Magento\InventorySales\Model\IsProductSalableCondition\IsProductSalableConditionChain"/>

But now, add to cart button has not been shown. So I need to do more:

  • Create a plugin for a class “Magento\InventorySales\Model\IsProductSalableCondition\IsAnySourceItemInStockCondition”. It will check whether a product is a backorder kind or not. If a backorder flag was set then we ignore a condition “Is Any Source Item In Stock Condition”
<type name="Magento\InventorySales\Model\IsProductSalableCondition\IsAnySourceItemInStockCondition">
        <plugin name="betagento_backorders_fixing" type="Betagento\Backorder\Plugin\IsAnySourceItemInStockCondition"/>
    </type>
<?php 
namespace Betagento\Backorder\Plugin;

use Magento\InventoryConfigurationApi\Api\Data\StockItemConfigurationInterface;
use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface;
use Magento\InventorySalesApi\Api\IsProductSalableInterface;


class IsAnySourceItemInStockCondition {

    /**
     * @var GetStockItemConfigurationInterface
     */
    private $getStockItemConfiguration;

    /**
     * @param GetStockItemConfigurationInterface $getStockItemConfiguration
     */
    public function __construct(
        GetStockItemConfigurationInterface $getStockItemConfiguration
    ) {
        $this->getStockItemConfiguration = $getStockItemConfiguration;
    }

    public function aroundExecute(IsProductSalableInterface $subject, \Closure $proceed, string $sku, int $stockId){

        
        $stockItemConfiguration = $this->getStockItemConfiguration->execute($sku, $stockId);
        if ($stockItemConfiguration->getBackorders() !== StockItemConfigurationInterface::BACKORDERS_NO
            && $stockItemConfiguration->getMinQty() >= 0) {
            return true;
        }else{
            return $proceed($sku, $stockId);
        }

    }
}

My suggestion is to merge two conditions classes below into only one class:

Magento\InventorySales\Model\IsProductSalableForRequestedQtyCondition\BackOrderCondition

Magento\InventorySales\Model\IsProductSalableForRequestedQtyCondition\IsAnySourceItemInStockCondition

… But anyway

Leave a Reply

Your email address will not be published. Required fields are marked *