When I create a bundled or grouped product in Magento 2.4, the product stock status stays In Stock even if one of child items are Out of Stock. A grouped/bundled product only marks out of stock is all of the child items are out of stock. If any of the child products are Out of Stock I would like the Grouped/Bundled product to change to Out of Stock too as we do not want to sell incomplete bundles. Is this the default Magento behaviour and is there any way to change it?
2 Answers
Yes this is the default behavious of Bundle or grouped.
You need to create a script and run cron to disable such products( not recommended as per SEO ) If disable is not an option for you then you need to do some customization,
I have done this for Grouped products. What you want to do is update the stock table.
Add this to your module's 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">
<type name="Magento\InventoryGroupedProductIndexer\Indexer\SelectBuilder">
<plugin name="namespace_grouped_product_stock_is_salable_logic" type="NameSpace\ModuleName\Plugin\InventoryGroupedProductIndexer\Indexer\SelectBuilderAfterPlugin" sortOrder="1" disabled="false"/>
</type>
</config>
And this is your class:
<?php
declare(strict_types=1);
namespace NameSpace\ModuleName\Plugin\InventoryGroupedProductIndexer\Indexer;
use Magento\Framework\DB\Select;
use Magento\InventoryGroupedProductIndexer\Indexer\SelectBuilder;
class SelectBuilderAfterPlugin
{
/**
* @param SelectBuilder $subject
* @param Select $return
* @param int $stockId
* @return Select
* @throws \Zend_Db_Select_Exception
*/
public function afterExecute(SelectBuilder $subject, Select $return, int $stockId): Select
{
$columns = $return->getPart(Select::COLUMNS);
if (is_array($columns) && count($columns)) {
foreach ($columns as &$columnEntry) {
list($correlationName, $column, $alias) = $columnEntry;
if ($correlationName == 'child_stock' && $column instanceof \Zend_Db_Expr) {
$expressionString = str_replace(["SUM", "MAX"], "MIN", $column->__toString());
$column = new \Zend_Db_Expr($expressionString);
$columnEntry = [$correlationName, $column, $alias];
}
}
$return->setPart(Select::COLUMNS, $columns);
}
return $return;
}
}
For Bundled Products, I haven't done it but if you make every option as required then I believe it will not allow to sell if any of the required option goes out of stock.