Magento 1.9.3.8 Execute only when there is a change for the Stock Level
-
18-01-2021 - |
質問
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;
}
}
解決
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.