0

I have got a custom extension, to track stock movements. So, keep a record of when x amount stock is added for a given product and/or when x amount of stock is removed.

However, Even if I don't edit a products stock level and hit save in admin, it will still add an entry for it in the history table. How can I get it to work so it will only add an entry if there is a change to the stock level?

I tried wrapping the saveStockItemAfter function into an if statement that checked if stock status was changed via $stockItem->getStockStastusChanged(). But, this returns null so the if statement is failing. How can I check if the stock level was adjusted in any way?

My extensions Config.xml:

<?xml version="1.0"?>
<config>
    <modules>
        <JR_StockHistory>
            <version>1.0.0</version>
        </JR_StockHistory>
    </modules>
    <adminhtml>
        <translate>
            <modules>
                <JR_StockHistory>
                    <files>
                        <default>JR_StockHistory.csv</default>
                    </files>
                </JR_StockHistory>
            </modules>
        </translate>
    </adminhtml>
    <global>
        <resources>
            <jr_stockhistory_setup>
                <setup>
                    <module>JR_StockHistory</module>
                </setup>
            </jr_stockhistory_setup>
        </resources>
        <blocks>
            <jr_stockhistory>
                <class>JR_StockHistory_Block</class>
            </jr_stockhistory>
        </blocks>
        <helpers>
            <jr_stockhistory>
                <class>JR_StockHistory_Helper</class>
            </jr_stockhistory>
        </helpers>
        <models>
            <jr_stockhistory>
                <class>JR_StockHistory_Model</class>
                <resourceModel>jr_stockhistory_resource</resourceModel>
            </jr_stockhistory>
            <jr_stockhistory_resource>
                <class>JR_StockHistory_Model_Resource</class>
                <entities>
                    <stock_history>
                        <table>cataloginventory_stock_history</table>
                    </stock_history>
                </entities>
            </jr_stockhistory_resource>
            <cataloginventory>
                <rewrite>
                    <stock>JR_StockHistory_Model_CatalogInventory_Stock</stock>
                </rewrite>
            </cataloginventory>
        </models>
        <events>
            <checkout_submit_all_after>
                <observers>
                    <stock_history>
                        <class>jr_stockhistory/stock_observer</class>
                        <method>checkoutAllSubmitAfter</method>
                    </stock_history>
                </observers>
            </checkout_submit_all_after>
            <cataloginventory_stock_item_save_after>
                <observers>
                    <stock_history>
                        <type>singleton</type>
                        <class>jr_stockhistory/stock_observer</class>
                        <method>saveStockItemAfter</method>
                    </stock_history>
                </observers>
            </cataloginventory_stock_item_save_after>
            <cataloginventory_stock_revert_products_sale>
                <observers>
                    <stock_history>
                        <class>jr_stockhistory/stock_observer</class>
                        <method>stockRevertProductsSale</method>
                    </stock_history>
                </observers>
            </cataloginventory_stock_revert_products_sale>
            <catalog_product_import_finish_before>
                <observers>
                    <stock_history>
                        <class>jr_stockhistory/stock_observer</class>
                        <method>catalogProductImportFinishBefore</method>
                    </stock_history>
                </observers>
            </catalog_product_import_finish_before>
            <controller_action_layout_render_before_adminhtml_catalog_product_edit>
                <observers>
                    <stock_history>
                        <class>jr_stockhistory/stock_observer</class>
                        <method>addStockHistoryTab</method>
                    </stock_history>
                </observers>
            </controller_action_layout_render_before_adminhtml_catalog_product_edit>
            <sales_order_item_cancel>
                <observers>
                    <inventory><type>disabled</type></inventory>
                    <stock_history>
                        <class>jr_stockhistory/stock_observer</class>
                        <method>cancelOrderItem</method>
                    </stock_history>
                </observers>
            </sales_order_item_cancel>
        </events>
    </global>
</config>

My Model/Stock/Observer.php file:

class JR_StockHistory_Model_Stock_Observer
{
    public function addStockHistoryTab()
    {
        $layout = Mage::getSingleton('core/layout');
        $layout->getBlock('product_tabs')
            ->addTab('stock_history', array(
                'after' => 'inventory',
                'label' => Mage::helper('jr_stockhistory')->__('Stock History'),
                'content' => $layout->createBlock('jr_stockhistory/adminhtml_stock_history_grid')->toHtml(),
            ));
    }

    public function cancelOrderItem($observer)
    {
        $item = $observer->getEvent()->getItem();

        $children = $item->getChildrenItems();
        $qty = $item->getQtyOrdered() - max($item->getQtyShipped(), $item->getQtyInvoiced()) - $item->getQtyCanceled();

        if ($item->getId() && ($productId = $item->getProductId()) && empty($children) && $qty) {
            Mage::getSingleton('cataloginventory/stock')->backItemQty($productId, $qty);
            $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($item->getProductId());
            $this->insertStockHistory($stockItem, sprintf(
                'Product restocked after order cancellation (order: %s)',
                $item->getOrder()->getIncrementId())
            );
        }

        return $this;
    }

    public function catalogProductImportFinishBefore($observer)
    {
        $adapter = $observer->getEvent()->getAdapter();
        Mage_ImportExport_Model_Import::getDataSourceModel()->getIterator()->rewind();
        $model = Mage::getModel('catalog/product');
        $skus = array();
        while ($bunch = $adapter->getNextBunch()) {
            foreach ($bunch as $rowData) {
                if (null !== $rowData['sku']) {
                    $skus[] = $rowData['sku'];
                }
            }
        }

        if (!empty($skus)) {
            $resource = Mage::getResourceModel('jr_stockhistory/stock_history');
            $productIds = $resource->getProductsIdBySku($skus);
            if (!empty($productIds)) {
                $stock = Mage::getSingleton('cataloginventory/stock');
                $stocks = Mage::getResourceModel('cataloginventory/stock')->getProductsStock($stock, $productIds);
                $stocksHistory = array();
                $datetime = Varien_Date::formatDate(time());
                foreach ($stocks as $stockData) {
                    $stocksHistory[] = array(
                        'item_id'     => $stockData['item_id'],
                        'user'        => $this->_getUsername(),
                        'user_id'     => $this->_getUserId(),
                        'qty'         => $stockData['qty'],
                        'is_in_stock' => (int) $stockData['is_in_stock'],
                        'message'     => 'Product import',
                        'created_at'  => $datetime,
                    );
                }

                if (!empty($stocksHistory)) {
                    $resource->insertStocksHistory($stocksHistory);
                }
            }
        }
    }

    public function checkoutAllSubmitAfter($observer)
    {
        if ($observer->getEvent()->hasOrders()) {
            $orders = $observer->getEvent()->getOrders();
        } else {
            $orders = array($observer->getEvent()->getOrder());
        }
        $stockItems = array();
        foreach ($orders as $order) {
            foreach ($order->getAllItems() as $orderItem) {
                if ($orderItem->getQtyOrdered()) {
                    $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($orderItem->getProductId());
                    if (!isset($stockItems[$stockItem->getId()])) {
                        $stockItems[$stockItem->getId()] = array(
                            'item'   => $stockItem,
                            'orders' => array($order->getIncrementId()),
                        );
                    } else {
                        $stockItems[$stockItem->getId()]['orders'][] = $order->getIncrementId();
                    }
                }
            }
        }

        if (!empty($stockItems)) {
            foreach ($stockItems as $data) {
                $this->insertStockHistory($stockItem, sprintf(
                    'Product ordered (order%s: %s)',
                    count($data['orders']) > 1 ? 's' : '',
                    implode(', ', $data['orders'])
                ));
            }
        }
    }

    public function insertStockHistory(Mage_CatalogInventory_Model_Stock_Item $stockItem, $message = '')
    {
        Mage::getModel('jr_stockhistory/stock_history')
            ->setItemId($stockItem->getId())
            ->setUser($this->_getUsername())
            ->setUserId($this->_getUserId())
            ->setQty($stockItem->getQty())
            ->setIsInStock((int) $stockItem->getIsInStock())
            ->setMessage($message)
            ->save();
        Mage::getModel('catalog/product')->load($stockItem->getProductId())->cleanCache();
    }

    public function saveStockItemAfter($observer)
{
    $stockItem = $observer->getEvent()->getItem();
    if (! $stockItem->getStockStatusChangedAutomaticallyFlag()) {
       if($stockItem->getStockStastusChanged()){
        if (! $message = $stockItem->getSaveHistoryMessage()) {
            if (Mage::getSingleton('api/session')->getSessionId()) {
                $message = Mage::helper('jr_stockhistory')->__('Stock saved from Magento API');
            } else {
                $message = Mage::helper('jr_stockhistory')->__('Stock saved manually');
            }
        }
        $this->insertStockHistory($stockItem, $message);
        }
    }
}


    public function stockRevertProductsSale($observer)
    {
        $items = $observer->getEvent()->getItems();
        foreach ($items as $productId => $item) {
            $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
            if ($stockItem->getId()) {
                $message = 'Product restocked';
                if ($creditMemo = Mage::registry('current_creditmemo')) {
                    $message = sprintf('Product restocked after credit memo creation (credit memo: %s)', $creditMemo->getIncrementId());
                }
                $this->insertStockHistory($stockItem, $message);
            }
        }
    }

    protected function _getUserId()
    {
        $userId = null;
        if (Mage::getSingleton('admin/session')->isLoggedIn()) {
            $userId = Mage::getSingleton('admin/session')->getUser()->getId();
        }

        return $userId;
    }

    protected function _getUsername()
    {
        $username = '-';
        if (Mage::getSingleton('api/session')->isLoggedIn()) {
            $username = Mage::getSingleton('api/session')->getUser()->getUsername();
        } elseif (Mage::getSingleton('admin/session')->isLoggedIn()) {
            $username = Mage::getSingleton('admin/session')->getUser()->getUsername();
        }

        return $username;
    }
}
0

The solution was to change $stockItem->getStockStastusChanged() to instead check for stock change via:

(int)$stockItem->getData('qty') != (int)$stockItem->getOrigData('qty')

Which checks if quantity value in the current data array is not equal to the original data array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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