Виявити зміни запасів


18

Мені потрібно виявляти, коли рівень запасів товару змінюється. Я мав певний успіх у використанні cataloginventory_stock_item_save_afterподії, яка запускається, коли інвентар змінюється в бекенді, або коли замовлення скасовується на фронті (через Paypal), але не спрацьовує, коли продукт купується з фронтену.

Я підключаюся до cataloginventory_stock_item_save_afterподії так:

<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) {

Чи потрібно використовувати іншу подію для фіксації зміни рекламних ресурсів, коли клієнт щось купує, чи щось не так із тим, як я причепився до події?

Відповіді:


26

Час тому, коли я щось будую для цього, мені довелося слухати декількох спостерігачів, оскільки там, де не все обробляється збереженням каталога, я повинен наступний код:

    <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>

А в спостерігачі наступний код:

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());
       }
    }
}

Сподіваюся, це трохи те, що ви шукаєте.


Коли я використав це так, як було, це призвело до помилки на сервері 500 при скасуванні замовлень та розміщенні замовлень. Мені довелося видалити умову if ($ this-> isEnabled ()) з функцій, щоб це працювало. Будь-яка причина, чому це так? Це тому, що я використовую однотонний тип? Спасибі
Мустафа Елькабані

5

Ви не можете використовувати будь-яку подію, пов’язану з моделлю товарних запасів, оскільки Magento використовує оптимізований SQL-запит, щоб зменшити запас для всіх замовлених товарів одночасно, минаючи модель.

Я вирішив це за допомогою перепису, Mage_CatalogInventory_Model_Stockкуди я додав додаткову подію:

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

Тоді спостерігач cataloginventory_stock_item_correct_qty_afterможе виглядати так:

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

    }

Я рекомендую не робити велику обробку чи додаткові дзвінки до бази даних (які необхідні для виявлення, наприклад, товару немає на складі), а додавати продукти до черги, оброблюваної cronjob, щоб мінімізувати додатковий час завантаження для користувач.


$stockItem->canSubtractQty()не працює у спостерігача, а також немає $stockItem->getId()жодних порад? Здається, я не можу отримати доступ до методів
snh_nl

Фабіан, яка мета додавання сюди спеціальних подій, оскільки ви можете додати функцію за допомогою самої переписаної функції? це лише розлучити? Будь ласка, керівництво.
Magento Learner

@MagentoLearner так, мені було легше повторно використовувати та додавати різні функції. Технічно ви можете також ввести приватний метод натомість
Фабіан Шменглер

Це може включати переписування основного класу, але це все-таки найповніше рішення. Іноді потрібно просто додати власні події на M1: P
Брайан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.