Magento Quote totals must be collected before this operation

Error kali ini cukup unik, namun bagaimana menyelesaikanya.
350  
       

Error kali ini cukup unik, namun bagaimana menyelesaikanya. Berikut ini adalah kutipan dari tipan nya.
his bug took 5 days to quash (solution below). Can you believe that? Not for want of research and inspection. I checked everywhere to find solutions to this bug.

I’m grateful to the Magento developers for not hearing cries for help from store owners everywhere. They have inspired me to write. Given the lack of viable solutions in the wild this should be a popular post.

What’s up doc? The symptoms

The Quote Totals bug, as it shall be named, shows its ugly head at the Magento cart’s checkout page when the Process Payment button is pressed. When the button is pressed, the shopper is directed back to the shopping cart with no indication of what’s happened. That’s right, there’s rarely ever a frontend error message to tell customers that their transaction has failed.

In some cases, the transaction will process successfully but the lack of a payment success message makes customers trundle through the checkout again and again and again until they finally give up then later realize they’ve bought the same item 1000 times over. This gives great surprise to store owners who then have to dig deeply into their morality brain and decide whether to run with the money or refund it.

With logging enabled in the Magento configs, you will see an error message in your exception.log that looks similar to this:

PHP

2013-08-30T01:26:15+00:00 ERR (3): 
exception 'Exception' with message 'Quote totals must be collected before this operation.' in /home/directory/public_html/app/code/core/Mage/Sales/Model/Quote.php:1793
Stack trace:
#0 /home/directory/public_html/app/code/core/Mage/Sales/Model/Service/Quote.php(326): Mage_Sales_Model_Quote->prepareRecurringPaymentProfiles()
#1 /home/directory/public_html/app/code/core/Mage/Sales/Model/Service/Quote.php(223): Mage_Sales_Model_Service_Quote->_submitRecurringPaymentProfiles()
#2 /home/directory/public_html/app/code/core/Mage/Sales/Model/Service/Quote.php(238): Mage_Sales_Model_Service_Quote->submitNominalItems()
#3 /home/directory/public_html/app/code/core/Mage/Checkout/Model/Type/Onepage.php(774): Mage_Sales_Model_Service_Quote->submitAll()
#4 /home/directory/public_html/app/code/core/Mage/Checkout/controllers/OnepageController.php(511): Mage_Checkout_Model_Type_Onepage->saveOrder()
#5 /home/directory/public_html/app/code/core/Mage/Core/Controller/Varien/Action.php(419): Mage_Checkout_OnepageController->saveOrderAction()
#6 /home/directory/public_html/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(250): Mage_Core_Controller_Varien_Action->dispatch('saveOrder')
#7 /home/directory/public_html/app/code/core/Mage/Core/Controller/Varien/Front.php(176): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#8 /home/directory/public_html/app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch()
#9 /home/directory/public_html/app/Mage.php(683): Mage_Core_Model_App->run(Array)
#10 /home/directory/public_html/index.php(89): Mage::run('', 'store')
#11 {main}
2013-08-30T01:26:15+00:00 ERR (3): 
exception 'Exception' with message 'Quote totals must be collected before this operation.' in /home/directory/public_html/app/code/core/Mage/Sales/Model/Quote.php:1793
Stack trace:
#0 /home/directory/public_html/app/code/core/Mage/Sales/Model/Service/Quote.php(326): Mage_Sales_Model_Quote->prepareRecurringPaymentProfiles()
#1 /home/directory/public_html/app/code/core/Mage/Sales/Model/Service/Quote.php(223): Mage_Sales_Model_Service_Quote->_submitRecurringPaymentProfiles()
#2 /home/directory/public_html/app/code/core/Mage/Sales/Model/Service/Quote.php(238): Mage_Sales_Model_Service_Quote->submitNominalItems()
#3 /home/directory/public_html/app/code/core/Mage/Checkout/Model/Type/Onepage.php(774): Mage_Sales_Model_Service_Quote->submitAll()
#4 /home/directory/public_html/app/code/core/Mage/Checkout/controllers/OnepageController.php(511): Mage_Checkout_Model_Type_Onepage->saveOrder()
#5 /home/directory/public_html/app/code/core/Mage/Core/Controller/Varien/Action.php(419): Mage_Checkout_OnepageController->saveOrderAction()
#6 /home/directory/public_html/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(250): Mage_Core_Controller_Varien_Action->dispatch('saveOrder')
#7 /home/directory/public_html/app/code/core/Mage/Core/Controller/Varien/Front.php(176): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#8 /home/directory/public_html/app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch()
#9 /home/directory/public_html/app/Mage.php(683): Mage_Core_Model_App->run(Array)
#10 /home/directory/public_html/index.php(89): Mage::run('', 'store')
#11 {main}

Logging can be enabled in Dashboard > Configuration > Developer > Log Settings.

The log files are found in /public_html/var/log/. The exception log is at /public_html/var/log/exception.log

Give me the meds! What’s the solution?

I’ve seen people beg, cry, shout, plead and pray for help with this bug. The Magento team has shown its proclivity for torturing store owners with its silence that says ‘Don’t ask us, we don’t know the answer and if we did we’d make you pay extortionately to get it’.

The error is thrown out by the file Quote.php. There are several possible causes:

The default core Quote.php file shipped with Magento has been overwritten by a badly written module. This default file is stored at /app/code/core/Mage/Sales/Model/Service/Quote.php.
An out of date, badly written or corrupt version of Quote.php is installed by a module somewhere below the directory /app/code/local/Mage/Sales/… If present, this module specific version would be used in place of the core version.
The server is not configured correctly for Magento to work.
Solution 1: fix Quote.php

When the problem starts after a module installation, after a theme installation or after a software upgrade then Magento is using a corrupt or incompatible Quote.php file. Either remove the broken module or correct the file with these steps:

Browse for Quote.php in /app/code/core/Mage/Sales/Model/Service/Quote.php
Backup the file
Open the file for editing and find the block of code that looks similar to the block of code shown below. This code is for the function prepareRecurringPaymentProfiles(). The code below is the correct code for this function. Replace the existing code with the correct code as is it is shown below here.
Browse for Quote.php stored anywhere under /app/code/local/Mage/Sales/.
Edit every instances of Quote.php that you find to replace the bad prepareRecurringPaymentProfiles function with the correct code shown below here.
Test your payment process again then check for new exception errors.
Correct prepareRecurringPaymentProfiles function

PHP

/**
* Create recurring payment profiles basing on the current items
*
* @return array
*/
public function prepareRecurringPaymentProfiles()
{
if (!$this->getTotalsCollectedFlag()) {
// Whoops! Make sure nominal totals must be calculated here.
throw new Exception('Quote totals must be collected before this operation.');
}

$result = array();
foreach ($this->getAllVisibleItems() as $item) {
$product = $item->getProduct();
if (is_object($product) && ($product->isRecurring())
&& $profile = Mage::getModel('sales/recurring_profile')->importProduct($product)
) {
$profile->importQuote($this);
$profile->importQuoteItem($item);
$result[] = $profile;
}
}
return $result;
}
/**
* Create recurring payment profiles basing on the current items
*
* @return array
*/
public function prepareRecurringPaymentProfiles()
{
if (!$this->getTotalsCollectedFlag()) {
// Whoops! Make sure nominal totals must be calculated here.
throw new Exception('Quote totals must be collected before this operation.');
}

$result = array();
foreach ($this->getAllVisibleItems() as $item) {
$product = $item->getProduct();
if (is_object($product) && ($product->isRecurring())
&& $profile = Mage::getModel('sales/recurring_profile')->importProduct($product)
) {
$profile->importQuote($this);
$profile->importQuoteItem($item);
$result[] = $profile;
}
}
return $result;
}

Solution 2: configure the server

When the problem starts overnight without any software updates being made to the site, without any new modules being installed and without any changes to the site’s configuration then you have a server to fix. Your host might have changed the configuration of your server or your server might have developed a fault in one of its Apache modules:

The fault could be caused by mod_fcgid. Check or have your host check that mod_fcgid is installed, enabled and fully functional. Check for time-outs too. You might need to change the FcgidIOTimeout value.
The fault could be caused by FastCGI being used. Switch to using SuPHP as the PHP handler.
The fault could be caused by mod_soap not being installed or problems with the way SOAP works on your server. Check or get your host to check mod_soap is installed, enabled and functional.
The fault could be caused by new security measures. Speak with your host or server administrator to confirm this.
In the case of the store that took me 5 days to fix, we had moved from Hostgator to Namecheap (yep, we are members of the Hostgator exodus). The new Namecheap server has 2Gb of RAM (8Gb burst) for $203 a year. With a hefty CPU allowance and 40 concurrent processes allowance. We knew we had more than enough server power to run our shopping cart.

I was going crazy working out the cause of the ‘Quote totals must be collected before this operation‘ error. I even reinstalled the Magento core files.

We migrated a few weeks back but only recently discovered the checkout error. Server migration was not at the top of our list of possible causes (though it should have been). We eventually tracked the fault to FastCGI. The guys at Namecheap migrated us to a ‘new’ new server that uses SuPHP instead of FastCGI. After 5 sleepless nights and 5 crazy days, the problem was finally solved by the switch to SuPHP. Our shopping cart now works as it should.

Namecheap is the host I recommend. Good customer service. Fast servers. Good server resource allowance but when using Magento, make sure you’re on an SuPHP server. My affiliate link is here 😉

Know of other solutions and causes to the Quote Totals bug? Let us know below.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>