Magento 1.9 – Safely Updating Product Stock Quantity

deadlockinventorymagento-1.9module

There is a problem that got me confused about updating the stock quantity in a safe way. A simple scenario, suppose I have 10 of product X in warehouse and there is zero orders so, also in Magento inventory I have 10 pieces. Suppose that I received another 10 pieces, and when I opened the product inventory to change 10 to 20, some customer placed and order and then I pressed the submit button. As a result Magento inventory will show that I have 20 pieces while I actually have 19.

I tried to write a module to update the product programmatically. But this solution may reduce the risk, because it will use the value + what I want to add. So it adding not replacing. But also there is a risk.

A second thought is to do it in the database level by preforming a SQL UPDATE STATEMENT, but I found another risk of doing it, I need to update more than one row in a table and more than one table. The data may be inconsistent.

Is there a way to use the lock method, like locking the product until the update occur, or another work around ?

Edit one:

After I tested Magento with this test case: I have 6 pieces, I opened the product inventory then changed the 6 with 7 without pressing the submit button. Then I ordered the 6 of them. Then I pressed submit in the product page, Magento shows that I have 1 in stock not seven which is correct. But is it guaranteed? And can I have an explanation how Magento handle it?

Best Answer

This is the default Magento behaviour when you update the stock quantity from backend admin. In the admin product form if you look over the html, for the stock quantity input, you will actually find two inputs:

<input type="hidden" id="original_inventory_qty" name="product[stock_data][original_inventory_qty]" value="6">
<input type="text" class="input-text required-entry validate-number" id="inventory_qty" name="product[stock_data][qty]" value="6">

So when you submit the form after changing the quantity text input to 7 you will actually send two variables to Magento:

product[stock_data][original_inventory_qty] = 6 and product[stock_data][qty] = 7.

If you look into the observer that handles the product stock update Mage_CatalogInventory_Model_Observer under the _prepareItemForSave($item, $product) method you will find:

    $originalQty = $product->getData('stock_data/original_inventory_qty');
    if (strlen($originalQty)>0) {
        $item->setQtyCorrection($item->getQty()-$originalQty);
    }

So Magento will check each time when you submit an original quantity and only apply a quantity correction and not just update the quantity to the one you've set.

Then the resource model that handles the save, Mage_CatalogInventory_Model_Resource_Stock_Item, will check the quantity correction in the _prepareDataForTable(Varien_Object $object, $table) method:

    $data = parent::_prepareDataForTable($object, $table);
    if (!$object->isObjectNew() && $object->getQtyCorrection()) {
        $qty = abs($object->getQtyCorrection());
        if ($object->getQtyCorrection() < 0) {
            $data['qty'] = new Zend_Db_Expr('qty-' . $qty);
        } else {
            $data['qty'] = new Zend_Db_Expr('qty+' . $object->getQtyCorrection());
        }
    }
    return $data;

So you don't need to worry about changing the stock quantity from the admin backend because Magento will apply the price correction by default.

You can also do this programmatically, but make sure you use the models available in the CatalogInventory module for loading and saving the stock.

Updating directly by performing an SQL statement while a customer is placing an order would not be a good idea.

Related Topic