Deteksi perubahan inventaris

18

Saya perlu mendeteksi kapan tingkat persediaan suatu produk berubah. Saya sudah cukup sukses menggunakan cataloginventory_stock_item_save_afteracara yang dipicu saat inventaris diubah di backend, atau ketika pesanan dibatalkan di frontend (via Paypal), tetapi tidak dipicu ketika produk dibeli dari frontend.

Saya mengaitkan ke cataloginventory_stock_item_save_afteracara seperti ini:

<global>
    <events>
        <cataloginventory_stock_item_save_after>
            <observers>
                <cataloginventory_stock_item_save_after_handler>
                    <type>model</type>
                    <class>stockchange/observer</class>
                    <method>stockChange</method>
                </cataloginventory_stock_item_save_after_handler>
            </observers>
        </cataloginventory_stock_item_save_after>
    </events>

<?php
class FashionBunker_StockChange_Model_Observer {
    public function stockChange(Varien_Event_Observer $observer) {

Apakah saya perlu menggunakan acara lain untuk menangkap perubahan inventaris ketika pelanggan membeli sesuatu, atau ada sesuatu yang salah dengan cara saya terhubung ke acara tersebut?

gregdev
sumber

Jawaban:

26

Sudah beberapa waktu yang lalu saya membangun sesuatu untuk ini, saya harus mendengarkan banyak pengamat karena mereka di mana tidak semua ditangani oleh penyimpanan katalog katalog, saya harus mengikuti kode:

    <events>
        <cataloginventory_stock_item_save_commit_after>
            <observers>
                <genmato_stockupdate>
                    <class>genmato_stockupdate/observer</class>
                    <method>catalogInventorySave</method>
                </genmato_stockupdate>
            </observers>
        </cataloginventory_stock_item_save_commit_after>
        <sales_model_service_quote_submit_before>
            <observers>
                <genmato_stockupdate>
                    <class>genmato_stockupdate/observer</class>
                    <method>subtractQuoteInventory</method>
                </genmato_stockupdate>
            </observers>
        </sales_model_service_quote_submit_before>
        <sales_model_service_quote_submit_failure>
            <observers>
                <genmato_stockupdate>
                    <class>genmato_stockupdate/observer</class>
                    <method>revertQuoteInventory</method>
                </genmato_stockupdate>
            </observers>
        </sales_model_service_quote_submit_failure>
        <sales_order_item_cancel>
            <observers>
                <genmato_stockupdate>
                    <class>genmato_stockupdate/observer</class>
                    <method>cancelOrderItem</method>
                </genmato_stockupdate>
            </observers>
        </sales_order_item_cancel>
        <sales_order_creditmemo_save_after>
            <observers>
                <genmato_stockupdate>
                    <class>genmato_stockupdate/observer</class>
                    <method>refundOrderInventory</method>
                </genmato_stockupdate>
            </observers>
        </sales_order_creditmemo_save_after>
    </events>

Dan di pengamat kode berikut:

public function catalogInventorySave(Varien_Event_Observer $observer)
{
    if ($this->isEnabled()) {
        $event = $observer->getEvent();
        $_item = $event->getItem();

        if ((int)$_item->getData('qty') != (int)$_item->getOrigData('qty')) {
            $params = array();
            $params['product_id'] = $_item->getProductId();
            $params['qty'] = $_item->getQty();
            $params['qty_change'] = $_item->getQty() - $_item->getOrigData('qty');
        }
    }
}

public function subtractQuoteInventory(Varien_Event_Observer $observer)
{
    if ($this->isEnabled()) {
        $quote = $observer->getEvent()->getQuote();
        foreach ($quote->getAllItems() as $item) {
            $params = array();
            $params['product_id'] = $item->getProductId();
            $params['sku'] = $item->getSku();
            $params['qty'] = $item->getProduct()->getStockItem()->getQty();
            $params['qty_change'] = ($item->getTotalQty() * -1);
        }
    }
}

public function revertQuoteInventory(Varien_Event_Observer $observer)
{
    if ($this->isEnabled()) {
        $quote = $observer->getEvent()->getQuote();
        foreach ($quote->getAllItems() as $item) {
            $params = array();
            $params['product_id'] = $item->getProductId();
            $params['sku'] = $item->getSku();
            $params['qty'] = $item->getProduct()->getStockItem()->getQty();
            $params['qty_change'] = ($item->getTotalQty());
        }
    }
}

public function cancelOrderItem(Varien_Event_Observer $observer)
{
    if ($this->isEnabled()) {
        $item = $observer->getEvent()->getItem();
        $qty = $item->getQtyOrdered() - max($item->getQtyShipped(), $item->getQtyInvoiced()) - $item->getQtyCanceled();
        $params = array();
        $params['product_id'] = $item->getProductId();
        $params['sku'] = $item->getSku();
        $params['qty'] = $item->getProduct()->getStockItem()->getQty();
        $params['qty_change'] = $qty;
    }
}

public function refundOrderInventory(Varien_Event_Observer $observer)
{
    if ($this->isEnabled()) {
        $creditmemo = $observer->getEvent()->getCreditmemo();
        foreach ($creditmemo->getAllItems() as $item) {
            $params = array();
            $params['product_id'] = $item->getProductId();
            $params['sku'] = $item->getSku();
            $params['qty'] = $item->getProduct()->getStockItem()->getQty();
            $params['qty_change'] = ($item->getQty());
       }
    }
}

Semoga ini sedikit yang Anda cari.

Vladimir Kerkhoff
sumber
Ketika saya menggunakan ini apa adanya, itu menghasilkan kesalahan 500 server ketika membatalkan pesanan dan menempatkan pesanan tidak berfungsi. Saya harus menghapus kondisi if ($ this-> isEnabled ()) dari fungsi agar ini berfungsi. Adakah alasan mengapa hal ini terjadi? Apakah karena saya menggunakan tipe singleton? Terima kasih
Moustafa Elqabbany
5

Anda tidak dapat menggunakan peristiwa apa pun yang terkait dengan model item persediaan, karena Magento menggunakan kueri SQL yang dioptimalkan untuk mengurangi stok untuk semua item yang dipesan sekaligus, melewati model.

Saya memecahkan ini dengan menulis ulang di Mage_CatalogInventory_Model_Stockmana saya menambahkan acara tambahan:

<?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;
    }
}

Maka pengamat untuk cataloginventory_stock_item_correct_qty_afterdapat terlihat seperti ini:

    /**
     * @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

    }

Saya sarankan untuk tidak melakukan pemrosesan berat atau panggilan database tambahan (yang diperlukan untuk mendeteksi jika produk kehabisan stok misalnya), tetapi untuk menambahkan produk ke antrian yang diproses oleh cronjob, untuk meminimalkan waktu muat tambahan untuk pengguna.

Fabian Schmengler
sumber
$stockItem->canSubtractQty()tidak bekerja di pengamat juga $stockItem->getId().. ada tips? Sepertinya saya tidak dapat mengakses metode
snh_nl
Fabian, apa tujuan menambahkan acara khusus di sini karena Anda dapat menambahkan fitur dengan fungsi yang ditimpa itu sendiri? apakah ini hanya untuk memisahkan? Mohon panduannya.
Magento Learner
@ MagentoLearner ya, itu memudahkan saya untuk menggunakan kembali dan menambahkan fitur yang berbeda. Secara teknis Anda juga bisa memperkenalkan metode pribadi sebagai gantinya
Fabian Schmengler
Ini mungkin melibatkan penulisan ulang kelas inti, tetapi masih merupakan solusi paling lengkap di sini. Kadang-kadang Anda hanya perlu menambahkan acara Anda sendiri di M1: P
Brian