Question

I have a configurable products with few sizes, let's say : 123, 160, M, S, L, XL

When I put products M and S on qty 0, which means it is out of stock, then sizes disappear form the swatches option.

I was expected to see also out of stock products with a special class and to be non clickable, but out of stock products disappear.

I found a solution and I will post my answer. Maybe that will help someone.

Was it helpful?

Solution

To solve this issue:

Step 1

I installed this module( for some other versions of magento maybe this will work without step 2)

https://github.com/mjankiewicz/MagentoConfigurableProduct

Step 2

Create a module with:

etc/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">
    <preference for="Magento\Swatches\Block\Product\Renderer\Configurable" type="Vendor\Namespace\Block\Outstock" />
</config>

then create Block/Outstock.php

<?php 

namespace vendor\namespace\Block;

class Outstock extends \Magento\Swatches\Block\Product\Renderer\Configurable
{

   public function getAllowProducts()
    {
        if (!$this->hasAllowProducts()){
             $skipSaleableCheck = 1;
             $products = $skipSaleableCheck ?
             $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null) :
                $this->getProduct()->getTypeInstance()->getSalableUsedProducts($this->getProduct(), null);
            $this->setAllowProducts($products);
        }
        return $this->getData('allow_products');
    }
}

After this run

php bin/magento setup:upgrade 

php bin/magento cache:clean

php bin/magento cache:flush

Of course that you can combine those 2 modules. You can take /Helper/Data.php form the first module JanSoft_ConfigurableProduct and put this into the second module, or the oposite.

OTHER TIPS

You can also override the plugin to display the swatches as well as dropdown option if product is out of stock.

1)etc/di/xml.

<type name="Magento\ConfigurableProduct\Plugin\Model\ResourceModel\Attribute\InStockOptionSelectBuilder">
        <plugin name="Magento_ConfigurableProduct_Plugin_Model_ResourceModel_InStockOptionSelectBuilder"
                type="Vendor\Mymodule\Plugin\Attribute\InStockOptionSelector"/>
    </type>

2)Plugin\Attribute

namespace Vendor\Mymodule\Plugin\Attribute;

use Magento\CatalogInventory\Model\ResourceModel\Stock\Status;
use Magento\ConfigurableProduct\Model\ResourceModel\Attribute\OptionSelectBuilderInterface;
use Magento\Framework\DB\Select;

class InStockOptionSelector extends \Magento\ConfigurableProduct\Plugin\Model\ResourceModel\Attribute\InStockOptionSelectBuilder
{
    private $stockStatusResource;

    public function __construct(Status $stockStatusResource)
    {
        parent::__construct($stockStatusResource);
    }

    /**
     * @param OptionSelectBuilderInterface $subject
     * @param Select $select
     * @return Select
     */
    public function afterGetSelect(OptionSelectBuilderInterface $subject, Select $select)
    {

        return $select;
    }
}

3) override block in di.xml

<preference for="Magento\ConfigurableProduct\Block\Product\View\Type\Configurable" type="Vendor\Mymodule\Block\Product\View\Type\Configurable"/>

4)Configurable.php

namespace Vendor\Mymodule\Block\Product\View\Type;

use Magento\ConfigurableProduct\Model\ConfigurableAttributeData;
use Magento\Customer\Helper\Session\CurrentCustomer;
use Magento\Customer\Model\Session;
use Magento\Framework\Locale\Format;
use Magento\Framework\Pricing\PriceCurrencyInterface;

class Configurable extends \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable
{
    public function __construct(\Magento\Catalog\Block\Product\Context $context, \Magento\Framework\Stdlib\ArrayUtils $arrayUtils, \Magento\Framework\Json\EncoderInterface $jsonEncoder, \Magento\ConfigurableProduct\Helper\Data $helper, \Magento\Catalog\Helper\Product $catalogProduct, CurrentCustomer $currentCustomer, PriceCurrencyInterface $priceCurrency, ConfigurableAttributeData $configurableAttributeData, array $data = [], $localeFormat = null, $customerSession = null)
    {
        parent::__construct($context, $arrayUtils, $jsonEncoder, $helper, $catalogProduct, $currentCustomer, $priceCurrency, $configurableAttributeData, $data, $localeFormat, $customerSession);
    }

    public function getAllowProducts()
    {
        if (!$this->hasAllowProducts()) {
            $products = [];
            $skipSaleableCheck = $this->catalogProduct->getSkipSaleableCheck();
            $allProducts = $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null);
            foreach ($allProducts as $product) {
                if ($product->isSaleable() || $skipSaleableCheck == 1) {
                    $products[] = $product;
                }
            }
            $this->setAllowProducts($products);
        }
        return $this->getData('allow_products');
    }

}

Hope so it will help .

Add into di.xml

 <type name="Magento\ConfigurableProduct\Model\Product\Type\Configurable">
        <plugin name="Vendor_Module::disable-stock-filter" type="Vendor\Module\Plugins\ConfigurableProduct\Model\Product\Type\Configurable"/>
 </type>

create file Configurable.php

namespace Vendor\Module\Plugins\ConfigurableProduct\Model\Product\Type;

use Magento\ConfigurableProduct\Model\Product\Type\Configurable as NativeConfigurable;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection;

class Configurable
{ 
    public function afterGetUsedProductCollection(NativeConfigurable $subject, $collection)
    {
        $collection->setFlag('has_stock_status_filter', true);

        return $collection;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top