Question

Whenever you load the cart page in Magento, the following code is run

$cart->init();
$cart->save(); 

One side effect of this is that the prices for any items in the cart are updated if the price of the product has been updated. This actually updates the entry in sales_flat_quote_item. I'm trying to track down where in code the price is updated on each quote item, and where each quote item is saved.

I know the myrid locations it could be set. I'm hoping someone knows where it actually is set. Magento 1.7x branch specifically, although info from all versions is welcome.

Was it helpful?

Solution

From a high level, the code that starts the whole process are lines 464 and 465 of Mage_Checkout_Model_Cart :

 $this->getQuote()->collectTotals();
 $this->getQuote()->save();

The new product price is being set against the quote in Mage_Sales_Model_Quote_Address_Total_Subtotal in the _initItem method. You will see $item->setPrice in the the if / else statement starting at line 104

OTHER TIPS

Dug this one up myself. So there's this

#File: app/code/core/Mage/Sales/Model/Quote.php
foreach ($this->getAllAddresses() as $address) {
    ...
    $address->collectTotals();
    ...
}    

which leads to this

#File: app/code/core/Mage/Sales/Model/Quote/Address.php
public function collectTotals()
{
    Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_before', array($this->_eventObject => $this));
    foreach ($this->getTotalCollector()->getCollectors() as $model) {
        $model->collect($this);            
    }
    Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_after', array($this->_eventObject => $this));
    return $this;
}

The getTotalCollector object returns a sales/quote_address_total_collector object, which loads a series of collector models from global/sales/quote/totals and calls collect on them. The sub-total collector's collect method ultimately calls this

#File: app/code/core/Mage/Sales/Model/Quote/Address/Total/Subtotal.php
protected function _initItem($address, $item)
{
    //...
    if ($quoteItem->getParentItem() && $quoteItem->isChildrenCalculated()) {
        $finalPrice = $quoteItem->getParentItem()->getProduct()->getPriceModel()->getChildFinalPrice(
           $quoteItem->getParentItem()->getProduct(),
           $quoteItem->getParentItem()->getQty(),
           $quoteItem->getProduct(),
           $quoteItem->getQty()
        );
        $item->setPrice($finalPrice)
            ->setBaseOriginalPrice($finalPrice);
        $item->calcRowTotal();
    } else if (!$quoteItem->getParentItem()) {
        $finalPrice = $product->getFinalPrice($quoteItem->getQty());
        $item->setPrice($finalPrice)
            ->setBaseOriginalPrice($finalPrice);
        $item->calcRowTotal();
        $this->_addAmount($item->getRowTotal());
        $this->_addBaseAmount($item->getBaseRowTotal());
        $address->setTotalQty($address->getTotalQty() + $item->getQty());
    }    
    //...
}

and this is where the quote item gets it's price set/rest.

I don't know if this helps you all that much, but if you are trying to do custom price changes on products in the cart, rather than extend and modify core classes, I use an observer sales_quote_save_before. It works great if you are trying to customize pricing (especially when I have products that can be custom length). I have code examples if you want them.

But I am talking to THE Alan Storm here, so you may laugh at my overly simplistic answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top