Magento – Magento2: Configurable product showing out of stock child products

associated-productsconfigurable-productmagento2out-of-stockstock-status

I'm facing issue that configurable products showing out of stock associated products even if the backend setting "Display Out of Stock Products" at Configuration->Catalog->Inventory->Stock Options is set to "No".

Does anyone knows the fix for this?

Best Answer

I've fixed this issue by overriding the below file in our custom module: \Magento\ConfigurableProduct\Helper\Data.php

Below are the complete steps:

1) Add below statement in your module's 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\ConfigurableProduct\Helper\Data" type="YOUR_COMPANY\MODULE_NAME\Helper\ConfigurableProduct\Data" />
</config>

2) Create a file Data.php at YOUR_COMPANY\MODULE_NAME\Helper\ConfigurableProduct and put below code in it

    <?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace YOUR_COMPANY\MODULE_NAME\Helper\ConfigurableProduct;

use Magento\Catalog\Model\Product;

/**
 * Class Data
 * Helper class for getting options
 *
 */
class Data extends \Magento\ConfigurableProduct\Helper\Data
{
    /**
     * Catalog Image Helper
     *
     * @var \Magento\Catalog\Helper\Image
     */
    protected $imageHelper;
    protected $_productloader;  
    protected $stockRegistry;  
    protected $_storeManager;

    /**
     * @param \Magento\Catalog\Helper\Image $imageHelper
     */
    public function __construct(
        \Magento\Catalog\Helper\Image $imageHelper,
        \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
        \Magento\Catalog\Model\ProductFactory $_productloader,
        \Magento\Store\Model\StoreManagerInterface $storeManager        
        )
    {
        $this->imageHelper = $imageHelper;
        $this->stockRegistry = $stockRegistry;
        $this->_productloader = $_productloader;
        $this->_storeManager = $storeManager;
        parent::__construct($imageHelper);
    }

    /**
     * Get Options for Configurable Product Options
     *
     * @param \Magento\Catalog\Model\Product $currentProduct
     * @param array $allowedProducts
     * @return array
     */
    public function getOptions($currentProduct, $allowedProducts)
    {

        $options = [];
        foreach ($allowedProducts as $product) {
            $productId = $product->getId();

            $websiteId = $this->getCurrentWebsiteId();
            if ($websiteId == 2) {
                $product = $this->getLoadProduct($productId);
                $stockitem = $this->stockRegistry->getStockItem($product->getId(), $product->getStore()->getWebsiteId());
                if($stockitem->getQty() <= 0 || $stockitem->getIsInStock() != 1) continue;
            }

            $images = $this->getGalleryImages($product);
            if ($images) {
                foreach ($images as $image) {
                    $options['images'][$productId][] =
                        [
                            'thumb' => $image->getData('small_image_url'),
                            'img' => $image->getData('medium_image_url'),
                            'full' => $image->getData('large_image_url'),
                            'caption' => $image->getLabel(),
                            'position' => $image->getPosition(),
                            'isMain' => $image->getFile() == $product->getImage(),
                        ];
                }
            }
            foreach ($this->getAllowAttributes($currentProduct) as $attribute) {
                $productAttribute = $attribute->getProductAttribute();
                $productAttributeId = $productAttribute->getId();
                $attributeValue = $product->getData($productAttribute->getAttributeCode());

                $options[$productAttributeId][$attributeValue][] = $productId;
                $options['index'][$productId][$productAttributeId] = $attributeValue;
            }
        }
        return $options;
    }

    public function getLoadProduct($id)
    {
        return $this->_productloader->create()->load($id);
    }

    public function getCurrentWebsiteId(){
        return $this->_storeManager->getStore()->getWebsiteId();
    }


    }

I've added condition for website_id as I want to hide out of stock options for 2nd website only. You can remove that condition.

Flush the cache and check any configurable product having out of stock associated products in it.

Thanks!

Related Topic