0

When a product is viewed I need to go to an external system (using a web service), query the actual stock values and update them in magento before displaying the page. This is for a configurable product so I need to handle all the associated simple products.

I've implemented an event observer capturing the catalog_controller_product_init_before event and the Observer.php module has

public function loadBeforeProductObserve(Varien_Event_Observer $observer)   {
    $event = $observer->getEvent();
    $x = $event['controller_action'];
    $id = $x->getRequest()->getParam('id');
    $product = Mage::getModel('catalog/product')->load($id);

    $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null,$product);

    foreach($childProducts as $child) {
        $stock = $child->getData("stock_item");

        if ($stock->getData("qty") == 0) {
            $stock->addData(array("qty"=>27, 'is_in_stock' => 1));
            //$stock->save();
        }
    }
}

Clearly this is running just to test the process in that it simply identifies any products with 0 stock and sets them to have 27 items.

My actual code is littered with print statements so I can see that it's finding all the right things and displaying the new values after the addData command (I've also tried setData) shows the values to be there.

When I try activating the save() function, the system fails and I get a 404 error for the page.

Without doing the save the product display is showing details as though the zero stock items are still zero and, indeed, capturing the catalog_controller_product_init_after event shows the value to be unchanged.

So what am I doing wrong? What things could I be doing better? How do I save the new stock value so that it will be used for the product display?

2 Answers 2

1

I just tried your exact code (with save enabled) on my Magento installation and it just works without modification.

There has to be another issue at your machine when it gives a 404 - maybe the product is disabled automatically (i.e. getting status attribute 0) as it was out of stock?

In addition, I refactored your code to avoid usages of array access ['controller_action'], addData and getData. It is best practice to use the magic methods instead.

Moreover, using the event catalog_controller_product_init passes a loaded product instance in its parameters so you don't have to do the loading yourself.

<events>
    <catalog_controller_product_init>
        <observers>
            <stackday>
                <class>stackday/observer</class>
                <method>updateInventoryOnProduct</method>
                <type>singleton</type>
            </stackday>
        </observers>
    </catalog_controller_product_init>
</events>

Observer:

/**
 * Update inventory on product.
 * 
 * @param Varien_Event_Observer $observer Observer.
 *
 * @throws Exception
 * 
 * @return void
 */
public function updateInventoryOnProduct(Varien_Event_Observer $observer)
{
    /** @var Mage_Catalog_Model_Product $product */
    $product = $observer->getProduct();

    if ($product->getTypeId() != Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
        return;
    }

    $childProducts = Mage::getModel('catalog/product_type_configurable')
        ->getUsedProducts(null, $product);

    foreach ($childProducts as $child) {
        /** @var Mage_Catalog_Model_Product $child */

        /** @var Mage_CatalogInventory_Model_Stock_Item $stock */
        $stock = $child->getStockItem();

        if ($stock->getQty() == 0) {
            $stock->setQty(27);
            $stock->setIsInStock(1);
            $stock->save();
        }
    }
}

But even with this code, the product may be displayed as Out of Stock - as there is an indexer in play here. You would have to run cataloginventory_stock indexer programmatically after updating stock item.

2
  • This looks like a good answer and I'll investigate further. My thinking with using the '_before' event was that I'd need to make the changes as early in the process as possible but maybe that's not the case. It certainly means that I have to pick out the data I need in a more complex manner. I clearly need to track down why I get a 404 error when I activate the save function. That seems very strange! How can I run an indexer programmatically? Or do I just need to go and find what I need in shell/indexer.php?
    – Ken
    Feb 16, 2015 at 10:17
  • This code does seem to work and doesn't give the 404 error however, although the stock is updated in magento, it doesn't show its effect on the page, i.e. the product still shows as out of stock. The backend doesn't show as any index needs updating. I tried reloading the page by setting header location to $_SERVER['REQUEST_URI'] but that didn't seem to work for some reason, although refreshing the page manually does. Using the above code and merging it with my original code using the catalog_controller_product_init_before event, however does seem to do exactly what I want :-)
    – Ken
    Feb 16, 2015 at 11:05
1

The following code, attached to the catalog_controller_product_init_before event seems to do what is required...

public function loadBeforeProductObserve(Varien_Event_Observer $observer)   {

    $event = $observer->getEvent();
    $x = $event['controller_action'];
    $id = $x->getRequest()->getParam('id');
    $product = Mage::getModel('catalog/product')->load($id);

    $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null,$product);

    foreach($childProducts as $child) {
        $stock = $child->getData("stock_item");

        if ($stock->getQty() == 0) {
            $stock->setQty(27);
            $stock->setIsInStock(1);
            $stock->save();
        }
    }
}

This is just the bare bones of the functionality and doesn't include the check that it IS a configurable product as suggested by Jan Papenbrock in his very helpful reply. It does, however, update the stock and make that updated value available on the product page.

1
  • Glad you got it figured out! Feb 17, 2015 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.