No puede usar ningún evento relacionado con el modelo de artículo de stock, porque Magento utiliza una consulta SQL optimizada para disminuir el stock de todos los artículos pedidos a la vez, sin pasar por el modelo.
Resolví esto con una reescritura de Mage_CatalogInventory_Model_Stock
donde agregué un evento adicional:
<?php
/**
* Add events to observe stock qty change
*
* @author Fabian Schmengler
*
*/
class SGH_ShippingExpress_Model_CatalogInventory_Stock
extends Mage_CatalogInventory_Model_Stock
{
const EVENT_CORRECT_STOCK_ITEMS_QTY_BEFORE = 'cataloginventory_stock_item_correct_qty_before';
const EVENT_CORRECT_STOCK_ITEMS_QTY_AFTER = 'cataloginventory_stock_item_correct_qty_after';
/**
* (non-PHPdoc)
* @see Mage_CatalogInventory_Model_Stock::registerProductsSale()
*/
public function registerProductsSale($items)
{
Mage::dispatchEvent(self::EVENT_CORRECT_STOCK_ITEMS_QTY_BEFORE, array(
'stock' => $this,
'items_obj' => (object)array('items' => &$items),
'operator' => '-'
));
$result = parent::registerProductsSale($items);
Mage::dispatchEvent(self::EVENT_CORRECT_STOCK_ITEMS_QTY_AFTER, array(
'stock' => $this,
'items' => $items,
'fullsave_items' => $result,
'operator' => '-'
));
return $result;
}
/**
* (non-PHPdoc)
* @see Mage_CatalogInventory_Model_Stock::revertProductsSale()
*/
public function revertProductsSale($items)
{
Mage::dispatchEvent(self::EVENT_CORRECT_STOCK_ITEMS_QTY_BEFORE, array(
'stock' => $this,
'items_obj' => (object)array('items' => &$items),
'operator' => '+'
));
$result = parent::revertProductsSale($items);
Mage::dispatchEvent(self::EVENT_CORRECT_STOCK_ITEMS_QTY_AFTER, array(
'stock' => $this,
'items' => $items,
'fullsave_items' => $result,
'operator' => '+'
));
return $result;
}
}
Entonces el observador cataloginventory_stock_item_correct_qty_after
puede verse así:
/**
* @var $items array array($productId => array('qty'=>$qty, 'item'=>$stockItem))
*/
$items = $observer->getItems();
foreach ($items as $productId => $item) {
$stockItem = $item['item'];
$product = $stockItem->getProduct();
// Do anything you need with $stockItem and $product here
}
Recomiendo no realizar un procesamiento pesado o llamadas adicionales a la base de datos (que son necesarias para detectar si el producto está agotado, por ejemplo), sino agregar los productos a una cola que es procesada por un cronjob, para minimizar el tiempo de carga adicional para el usuario.