1. Magento Inventory Tables:
Magento uses several tables to manage stocks. Table cataloginventory_stock is used to manage stock names. Table cataloginventory_stock_item has the relationship between product and stock name. You can check table cataloginventory_stock_status to know the product's stock status. Here i have a question: Can magento index process help stock cases as well?
2.Apply stock status to product collection using event hook;
<catalog_product_collection_load_after>
<observers>
<inventory>
<class>cataloginventory/observer</class>
<method>addStockStatusToCollection</method>
</inventory>
</observers>
</catalog_product_collection_load_after>
public function addStockStatusToCollection($observer)
{
$productCollection = $observer->getEvent()->getCollection();
if ($productCollection->hasFlag('require_stock_items')) {
Mage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection);
} else {
Mage::getModel('cataloginventory/stock_status')->addStockStatusToProducts($productCollection);
}
return $this;
}
public function addStockStatusToProducts($productCollection, $websiteId = null, $stockId = null)
{
if ($stockId === null) {
$stockId = Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID;
}
if ($websiteId === null) {
$websiteId = Mage::app()->getStore()->getWebsiteId();
if ((int)$websiteId == 0 && $productCollection->getStoreId()) {
$websiteId = Mage::app()->getStore($productCollection->getStoreId())->getWebsiteId();
}
}
$productIds = array();
foreach ($productCollection as $product) {
$productIds[] = $product->getId();
}
if (!empty($productIds)) {
$stockStatuses = $this->_getResource()->getProductStatus($productIds, $websiteId, $stockId);
foreach ($stockStatuses as $productId => $status) {
if ($product = $productCollection->getItemById($productId)) {
$product->setIsSalable($status);
}
}
}
/* back compatible stock item */
foreach ($productCollection as $product) {
$object = new Varien_Object(array('is_in_stock' => $product->getData('is_salable')));
$product->setStockItem($object);
}
return $this;
}
public function getProductStatus($productIds, $websiteId, $stockId = 1)
{
if (!is_array($productIds)) {
$productIds = array($productIds);
}
$select = $this->_getReadAdapter()->select()
->from($this->getMainTable(), array('product_id', 'stock_status'))
->where('product_id IN(?)', $productIds)
->where('stock_id=?', $stockId)
->where('website_id=?', $websiteId);
return $this->_getReadAdapter()->fetchPairs($select);
}
3. Specific case for group product:
In class Mage_CatalogInventory_Model_Mysql4_Indexer_Stock_Grouped, let me put our minds on following method:
protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = false)
{
$adapter = $this->_getWriteAdapter();
$idxTable = $usePrimaryTable ? $this->getMainTable() : $this->getIdxTable();
$select = $adapter->select()
->from(array('e' => $this->getTable('catalog/product')), array('entity_id'));
$this->_addWebsiteJoinToSelect($select, true);
$this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id');
$select->columns('cw.website_id')
->join(
array('cis' => $this->getTable('cataloginventory/stock')),
'',
array('stock_id'))
->joinLeft(
array('cisi' => $this->getTable('cataloginventory/stock_item')),
'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id',
array())
->joinLeft(
array('l' => $this->getTable('catalog/product_link')),
'e.entity_id = l.product_id AND l.link_type_id=' . Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED,
array())
->joinLeft(
array('le' => $this->getTable('catalog/product')),
'le.entity_id = l.linked_product_id',
array())
->joinLeft(
array('i' => $idxTable),
'i.product_id = l.linked_product_id AND cw.website_id = i.website_id AND cis.stock_id = i.stock_id',
array())
->columns(array('qty' => new Zend_Db_Expr('0')))
->where('cw.website_id != 0')
->where('e.type_id = ?', $this->getTypeId())
->group(array('e.entity_id', 'cw.website_id', 'cis.stock_id'));
// add limitation of status
$psExpr = $this->_addAttributeToSelect($select, 'status', 'e.entity_id', 'cs.store_id');
$psCond = $adapter->quoteInto($psExpr . '=?', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
if ($this->_isManageStock()) {
$statusExpr = new Zend_Db_Expr('IF(cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 0,'
. ' 1, cisi.is_in_stock)');
} else {
$statusExpr = new Zend_Db_Expr('IF(cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 1,'
. 'cisi.is_in_stock, 1)');
}
$stockStatusExpr = new Zend_Db_Expr("LEAST(MAX(IF({$psCond} AND le.required_options = 0, i.stock_status, 0))"
. ", {$statusExpr})");
$select->columns(array(
'status' => $stockStatusExpr
));
if (!is_null($entityIds)) {
$select->where('e.entity_id IN(?)', $entityIds);
}
return $select;
}