4

I have to show out of stock products only in certain categories by hiding them in all other categories.

used below plugin to implement, that is not working.

Vendor/Module/etc/di.xml

<type name="Magento\Catalog\Model\Layer">
    <plugin name="Vendor_Module_Layer" type="Vendor\Module\Plugin\CatalogInventoryLayer" sortOrder="10" disabled="false"  />
</type>

Then

Vendor/Module/Plugin/CatalogInventoryLayer.php

<?php

namespace Vendor\Module\Plugin;

use Magento\Catalog\Model\Layer as CatalogLayer;
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;

class CatalogInventoryLayer {
protected $_logger;
public function __construct( 
    \Psr\Log\LoggerInterface $logger
    ){
        $this->_logger = $logger;
    }
public function aroundPrepareProductCollection(CatalogLayer $subject, \Closure $proceed, $collection)
{
    $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/customlog.log');
    $logger = new \Zend\Log\Logger();
    $logger->addWriter($writer);        
    $categoryId = $subject->getCurrentCategory()->getId();      
    $proceed($collection);
    if ($categoryId == 4){
        $collection->getSelect()->joinLeft(
                 ['_inventory_table' => 'cataloginventory_stock_item'], 
                 "_inventory_table.product_id = e.entity_id", ['is_in_stock']
        );
        $collection->addFieldToFilter('is_in_stock',array('eq'=>'0'));

    }       

    return $this;
    }
  }

Update:

Vendor/Module/etc/di.xml

<type name="Magento\CatalogInventory\Helper\Stock">
  <plugin name="Vendor_Extension_Stock_Helper" type="Vendor\Extension\Plugin\Helper\Stock" sortOrder="10" disabled="false"  />
</type>

Vendor/Module/Plugin/Helper/Stock.php

<?php 
namespace Vendor\Module\Plugin\Helper;
use Magento\CatalogInventory\Model\ResourceModel\Stock\StatusFactory;
class Stock
{    
private $logger;
protected $_registry;
protected $request;
protected $stockStatusResource;
protected $stockStatusFactory;
public function __construct(
    \Psr\Log\LoggerInterface $logger,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\App\Request\Http $request,
    StatusFactory $stockStatusFactory
) {
    $this->logger = $logger;
    $this->_registry = $registry;
    $this->request = $request;
    $this->stockStatusFactory  = $stockStatusFactory;
}
public function aroundAddIsInStockFilterToCollection(\Magento\CatalogInventory\Helper\Stock $subject, \Closure $proceed, $collection)
{
    try{
        $category = $this->_registry->registry('current_category');//get current category
        $currentPage = $this->request->getFullActionName(); //catalogsearch_result_index
        if(!is_null($category) && $currentPage!= 'catalogsearch_result_index')
        {
            $stockFlag = 'has_stock_status_filter';
            $categoryId = $category->getId();                   
            $parentCategoryId =  $category->getParentCategory()->getId();               
            if($categoryId == 10 || $parentCategoryId == 10)
            {
            $resource = $this->getStockStatusResource();                
                $resource->addStockDataToCollection(
                        $collection,
                        false
                ); 
            }
            $collection->setFlag($stockFlag, true);
        } 
        return $this;
    }catch(\Exception $e){
        return $e->getMessage();
        $this->logger->info('--exception--'.$e->getMessage());
    }
}

public function getStockStatusResource(){
    if (empty($this->stockStatusResource)) {
        $this->stockStatusResource = $this->stockStatusFactory->create();
    }
    return $this->stockStatusResource;
   }
}

I have to display them only when we visit some specific categories by hiding them in all other categories

The updated code is working in category page, but search result page out of stock from other categories also visible,

Is there any way to show only out of stock products which belongs to category id '10'.

Can anyone please check and update me if there is any other way to implement the above functionality. Thanks!!

  • What's your magento version? – Rohan Hapani Feb 14 at 11:09
  • @RohanHapani, its 2.3.2 – Manjunath Feb 14 at 11:15
4
+50

To do above things, you need to do this things.

  1. Vendor\Extension\etc\di.xml
<type name="Magento\CatalogInventory\Helper\Stock">
    <plugin name="Vendor_Extension_Stock_Helper" type="Vendor\Extension\Plugin\Helper\Stock" sortOrder="10" disabled="false"  />
</type>
  1. Create the Helper File with arround plugin.

Vendor\Extension\Plugin\Helper\Stock.php

<?php
namespace Vendor\Extension\Plugin\Helper;

class Stock
{    
    public function aroundAddIsInStockFilterToCollection(\Magento\CatalogInventory\Helper\Stock $subject, \Closure $proceed, $collection)
    {
       // Do your Logic Here
        return $returnValue;
    }
}
|improve this answer|||||
  • hi @Dhiren, this has issue with the count in layer navigation – Manjunath Feb 25 at 8:11
  • but the search result page still out of stock products showing for all. – Manjunath Feb 25 at 15:47
2

You should extend the original function ( Magento\CatalogInventory\Model\ProductCollectionStockCondition::apply() ) which is checking the stock configuration.

"Display out of stock products" config in store > Config > catalog > inventory.

You can use preference to extend that apply() function and add additional condition like that.

from:
$this->stockHelper->addIsInStockFilterToCollection($collection);

to:
if(in_array(category_id, ur_list_of_ids))
$this->stockHelper->addIsInStockFilterToCollection($collection);

In this way, you can enable out of stock products in some of the category only.

|improve this answer|||||
  • it is not so clear, can you update me as answer please, I have to set Display out of stock products as "yes" in admin? – Manjunath Feb 6 at 11:51
  • yes, you have to set it as "yes" and extend the original class file which is adding filter based on your config. you can add your category condition in your extended class. – Thamo Feb 6 at 11:57
  • if set to yes, the out of stock products will display in all the cats, how can we avoid that – Manjunath Feb 6 at 12:03
  • could you update me working code please.. – Manjunath Feb 7 at 6:29
  • @Manjunath - I dont have working code now. but given the suggestion based on my previous experience. – Thamo Feb 13 at 7:23
1

You can display **ONLY Out Of Stock products for particular category page**, first, you need to set configuration for Display Out of Stock Products, Go to Stores > Configuration > Catalog > Inventory > Stock Options->Display Out of Stock Products set as Yes, because for category page and product page product is not visible or not in collection if it's set as No, I'm not sure why Out Of Stock products is not available in Collection without "Display Out of Stock Products" configuration.

But for display Out Of Stock products for a particular category, you can change aroundPrepareProductCollection() as per below or replace your plugin file, I have checked it displays only Out Of Stock product only on the Category page.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Vendor\Module\Plugin;

use Magento\Catalog\Model\Layer as CatalogLayer;

class CatalogInventoryLayer
{
    public function aroundPrepareProductCollection(CatalogLayer $subject, \Closure $proceed, $collection)
    {
        $categoryId = $subject->getCurrentCategory()->getId();
        $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/OutOfStock_Product.log');
        $logger = new \Zend\Log\Logger();
        $logger->addWriter($writer);

        //Get Out Of Stock Products
        $collection->addFieldToSelect('*')
            ->setFlag('has_stock_status_filter', true)
            ->joinField('stock_item', 'cataloginventory_stock_item', 'is_in_stock', 'product_id=entity_id', 'is_in_stock=0');
        $collection->addCategoriesFilter(['eq' => $categoryId]); // Current category filter, it's not require, because PrepareProductCollection() automatically apply filter for current category. 

        $logger->info(print_r($collection->getData(), true));

        return $collection;
    }
}

Out of stock products of Bags category, you can see in screenshots.

enter image description here

enter image description here

I hope it will helpful for you.

|improve this answer|||||
  • hi @rohit, thanks for the answer, but where u are checking the condition in your answer for particular category? I think u missed it, pls double check once – Manjunath Feb 25 at 7:11
  • this is not working, getting exception Column not found: 1054 Unknown column 'e.min_price' in 'field list', – jafar pinjar Feb 25 at 8:35
  • Hello @Manjunath, No, I have not missed, because category filter is not require here, because PrepareProductCollection() is call for current category page, and in "vendor/magento/module-catalog/Model/Layer.php" file you can check "prepareProductCollection()" function, we just need to pass collection, it'll automatically apply CURRENT CATEGORY FILTER, I have tested above code it's working fine. – Mahesh Dave Feb 25 at 9:11
  • "vendor/magento/module-catalog/Model/Layer.php" public function prepareProductCollection($collection) { $this->collectionFilter->filter($collection, $this->getCurrentCategory()); return $this; } If you still apply filter then please check my updated answer. – Mahesh Dave Feb 25 at 9:11
  • Hello @jafarpinjar, I have tested above code, it's working fine for me. – Mahesh Dave Feb 25 at 9:11

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.