Ok, I created custom Total class for adding the special discount, and everything seems to work fine except, for some reason I can't find, my total is calculated twice! That results in double amount of discount, and incorrect grand total. Now, this happens on cart page and on checkout pages...BUT...when I complete the order the total is fine, calculated only once, and grand total is fine.
That is strange, it's like collect method is called twice for cart pages, but only once when finishing the order, but I can' track down where all this happens, and why.
To skip the junk code, I'll paste only important
<sales>
<quote>
<totals>
<mydiscount>
<class>ucon_mydiscount/total_mydiscount</class>
<before>subtotal</before>
</mydiscount>
</totals>
</quote>
</sales>
and the collector's methods
public function collect(Mage_Sales_Model_Quote_Address $address)
{
parent::collect($address);
$quote = $address->getQuote();
$quoteId = $quote->getEntityId();
$items = $quote->getAllItems();
if (!count($items)) {
return $this;
}
$discount = 0;
$productId = 2556;
foreach($items as $item)
{
if($item->getProduct()->getId() == $productId)
{
$qty = $item->getQty();
$totalPrice = round(($item->getRowTotal()+$item->getTaxAmount()),2);
//discount 10%
$discount = round($totalPrice * 0.1,2);
$discount = 0 - $discount;
}
}
if($discount == 0)
return $this;
$this->_setAmount($discount);
$this->_setBaseAmount($discount);
return $this;
}
and fetcher
public function fetch(Mage_Sales_Model_Quote_Address $address)
{
$amount = $address->getMydiscountAmount();
if ($amount != 0) {
$title = Mage::helper('ucon_mydiscount')->__('My discount');
$address->addTotal(array(
'code' => $this->getCode(),
'title' => $title,
'value' => $amount
));
}
return $this;
}
edit: One more thing I find very strange - I'm doing the setValue in my collect method, not the addValue, so even if the method is called twice, it shouldn't be double value, it should simply set it twice to the correct value.
Could the problem be that a total object belongs to an address object and Magento orders typically have TWO addresses - one for shipping and one for billing?
Your total will therefore be called to run twice - once with the billing address and once with the shipping address and the amount is totalled per-address. You can try checking which address you've been handed and only applying a value to one of them like this;
public function collect(Mage_Sales_Model_Quote_Address $address) {
$this->_setAddress($address);
$this->_setAmount(0);
$this->_setBaseAmount(0);
if ($address->getAddressType() == 'shipping') {
//only apply an actual value to the shipping address
//... Do your calculation here as above ...
}
return $this;
}
You will also have to do something similar in the fetch method as well...
public function fetch(Mage_Sales_Model_Quote_Address $address) {
$amount = $address->getMydiscountAmount();
if ($amount != 0 && $address->getAddressType() == 'shipping') {
$title = Mage::helper('ucon_mydiscount')->__('My discount');
$address->addTotal(array(
'code' => $this->getCode(),
'title' => $title,
'value' => $amount
));
}
return $this;
}
I'll admit that collect
function could be prettier, but hopefully you get the idea anyway.
Try that and see if your totals add up correctly on the frontend and the admin area.