Inventaränderung erkennen

18

Ich muss feststellen, wann sich der Lagerbestand eines Produkts ändert. Ich hatte einige Erfolge mit dem cataloginventory_stock_item_save_afterEreignis, das ausgelöst wird, wenn das Inventar im Backend geändert wird oder wenn eine Bestellung im Frontend (über Paypal) storniert wird, aber nicht ausgelöst wird, wenn ein Produkt über das Frontend gekauft wird.

Ich betrete das cataloginventory_stock_item_save_afterEvent wie folgt:

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

Muss ich ein anderes Ereignis verwenden, um die Inventaränderung zu erfassen, wenn ein Kunde etwas kauft, oder stimmt etwas nicht mit der Art und Weise überein, wie ich mich in das Ereignis eingebunden habe?

gregdev
quelle

Antworten:

26

Es ist schon einige Zeit her, dass ich etwas dafür baue. Ich musste mehreren Beobachtern zuhören, da sie nicht alle durch das Speichern des Kataloginventars behandelt wurden. Ich muss folgenden Code verwenden:

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

Und im Beobachter der folgende Code:

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

Hoffe das ist ein bisschen was du suchst.

Vladimir Kerkhoff
quelle
Als ich dies so benutzte, verursachte es einen 500-Server-Fehler, als das Stornieren und Aufgeben von Bestellungen nicht funktionierte. Ich musste die Bedingung if ($ this-> isEnabled ()) aus den Funktionen löschen, damit dies funktioniert. Gibt es einen Grund, warum dies der Fall ist? Liegt es daran, dass ich den Singleton-Typ verwende? Vielen Dank
Moustafa Elqabbany
5

Sie können keine Ereignisse verwenden, die sich auf das Lagerartikelmodell beziehen, da Magento mithilfe einer optimierten SQL-Abfrage den Lagerbestand für alle bestellten Artikel gleichzeitig unter Umgehung des Modells verringert.

Ich löste dieses Problem mit einer Umschreibung, in der Mage_CatalogInventory_Model_Stockich ein zusätzliches Ereignis hinzufügte:

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

Dann kann der Beobachter für cataloginventory_stock_item_correct_qty_afterso aussehen:

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

    }

Ich empfehle, keine umfangreichen Verarbeitungsvorgänge oder zusätzlichen Datenbankaufrufe (die erforderlich sind, um beispielsweise festzustellen, ob das Produkt nicht vorrätig ist) durchzuführen, sondern die Produkte einer Warteschlange hinzuzufügen, die von einem Cronjob verarbeitet wird, um die zusätzliche Ladezeit für das zu minimieren Benutzer.

Fabian Schmengler
quelle
$stockItem->canSubtractQty()arbeitet nicht im beobachter noch gibt $stockItem->getId().. irgendwelche tipps? Scheint, ich kann nicht auf die Methoden zugreifen
snh_nl
Fabian, was ist der Zweck, hier benutzerdefinierte Ereignisse hinzuzufügen, da Sie die Funktion mit der überschriebenen Funktion selbst hinzufügen können? ist das nur zu entkoppeln? Bitte führen.
Magento Learner
@MagentoLearner Ja, es hat mir die Wiederverwendung und das Hinzufügen verschiedener Funktionen erleichtert. Technisch könnte man stattdessen auch eine private Methode einführen
Fabian Schmengler
Dies kann das Umschreiben einer Core-Klasse beinhalten, ist aber immer noch die umfassendste Lösung. Manchmal musst du einfach deine eigenen Events für M1: P
Brian