Create registration.php and module.xml file for creating a module.
For Collection of product generate from Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection file. We need to create a plugin for load() function. we need to set our custom condition for out of stock product to beforeLoad() function.
Create a di.xml file,
Path, app/code/Grazitti/OutOfStock/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">
<!-- out of stock product at end of list -->
<type name="Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection">
<plugin name="Grazitti_OutOfStock::OutofstockEnd" type="Grazitti\OutOfStock\Plugin\Product\ProductList\Toolbar"/>
</type>
</config>
Need to override Stock.php file from Magento\CatalogInventory\Helper\Stock class.
Create Toolbar.php file, File Path, app/code/Grazitti/OutOfStock/Plugin/Product/ProductList/Toolbar.php
<?php
/**
* @author Pankaj Sharma
* @package Grazitti_OutOfStock
*/
namespace Grazitti\OutOfStock\Plugin\Product\ProductList;
class Toolbar
{
/**
* @param \Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection $subject
* @param bool $printQuery
* @param bool $logQuery
* @return array
*/
public function beforeLoad(\Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection $subject, $printQuery = false, $logQuery = false)
{
$orderBy = $subject->getSelect()->getPart(\Zend_Db_Select::ORDER);
$outOfStockOrderBy = array('is_salable DESC');
/* reset default product collection filter */
$subject->getSelect()->reset(\Zend_Db_Select::ORDER);
$subject->getSelect()->order($outOfStockOrderBy);
return [$printQuery, $logQuery];
}
}
Clear Cache and check in the front end. I hope it will work for you.