4

I am running an observer on Magento 1.9 on the following event:

sales_quote_merge_after

This event occurs when a guest customer with items in their cart logs into their account. When doing this the quote item IDs are dropped from the current session and the products are re-added with new IDs. What I need to know (using an observer or otherwise), is what each quote item ID was before, and what it has changed into.

I have tried countless observers on the Mage_Sale_Model_Quote::addItem method, but Magento does not return the new quote item ID on any method I have seen.

In the observer above I have managed to make it pass the original quote and new quote into the observer, but there's no way of matching the quote item IDs.

I have tried adding the original quote item ID as an option to the quote item which works, but as soon as the merge is carried out the options are wiped!

$item->addOption(array(
                'code' => 'original_quote_item_id',
                'product' => $item->getProduct()->getId(),
                'value' => $item->getId()
            ));

I'm left perplexed on where to try next - any advice or suggestions would be greatly appreciated!

1
  • have you tried with getOrigData('quote_item_id')? Nov 12, 2014 at 14:30

3 Answers 3

4

So based on what you said I have now got a solution that I belive works 100% of the time and matched the items nicely.

When merging there are 3 things that can happen.

  1. When the item is in both quotes it's qty is merged into the logged in customers item.
  2. When the item is in the guest quote but not the logged in customer quote a new item is cloned into the logged in customer quote, and the item_id is added at some later time (that I couldn't pin point)
  3. The item is in just the logged in customer quote nothing changes.

Because the for the first two possibilitys the item is in both the quotes I used the compare function to find when the items matched and populated the newIds and OriginalIds at that point.

We can then say if there was no match this item was not in the guest quote so just use the newId as there was no originalId.

protected $_source;

/**
 * @param Varien_Event_Observer $observer
 * @return Training_Merge_Model_Observer
 */
public function salesQuoteMergeAfter(Varien_Event_Observer $observer)
{
    $this->_source = $observer->getEvent()->getSource();
}

public function controllerFrontSendResponseAfter(Varien_Event_Observer $observer){
    if($this->_source) {
        $newOldArray = array();

        //Quote = Customer Quote
        //Source = Guest Quote
        $quote = Mage::getSingleton('checkout/session')->getQuote();
        $source = $this->_source;

        foreach ($source->getAllVisibleItems() as $item) {
            foreach ($quote->getAllItems() as $quoteItem) {
                if ($quoteItem->compare($item)) {

                    $newId = $quoteItem->getData('item_id');
                    $originalId = $item->getData('item_id');

                    $newOldArray[] = array(
                        "newId" => $newId,
                        "originalId" => $originalId
                    );

                    $quoteItem->setIsMatch(1);

                }
            }
        }

        //If there was no match so far then it's a new item and there was
        //no similar item in the old quote, we can therefore just take the
        //newId and set the original to null
        foreach ($quote->getAllItems() as $quoteItem) {
            if (!$quoteItem->getIsMatch()) {
                $newId = $quoteItem->getData('item_id');

                $newOldArray[] = array(
                    "newId" => $newId,
                    "originalId" => null
                );

            }
        }
    }


    return $this;
}
1
  • My work is to restrict few prod.with only one qty in cart. Your solution worked for me. EE 1.14.2.1. during cart merge. Thank you.
    – Franc
    Dec 17, 2015 at 12:07
1

Maybe you should observe also the sales_quote_merge_before event.
use the same observer class, but a different method, and declare your observer class to be a singleton.
Then, you can remember the ids from the quote before the merging is done.
in the sales_quote_merge_after get again all the item ids in the cart and calculate the difference. You should get the newly added item ids.

1
  • I've just given this a test drive and it turns out that the quote object in sales_quote_merge_after still doesn't have any record of the newly added item IDs - this is insane!
    – Adam Moss
    Nov 12, 2014 at 14:23
0

Okay, in the end it's not perfect but I used two events:

sales_quote_merge_before - in the observer I grabbed the old quote items

public function setOldQuoteIntoSession($observer)
{
    $this->_source = $observer->getEvent()->getSource();
}

controller_front_send_response_after - in the observer I grabbed the new quote items. This is one of the last events fired and at this stage the quote is updated saved.

public function updateQuoteItems($observer)
{
    if (isset($this->_source))
    {
        $oldQuote = $this->_source;
        $newQuote = Mage::getSingleton('checkout/session')->getQuote();

        // do code
    }
}

It's not perfect because I can't 100% match the old IDs with the new IDs - I'm literally doing it based on the product ID set against each quote item. I've exhausted every other possibility.

Magento, if you read this can please explain why we have to wait so long before we get quote IDs back from added items? I know we need to wait for setCartWasUpdated(true), but there must be something we can do.

1
  • Hello @Adam Moss, I am facing same issue, I want to update quote_id and quote_item_id in my custom table when customer login. From your answer I don't get how to integrate it to my code. How to compare oldItem and NewItem ? please reply. Jan 30, 2017 at 12:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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