Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

After searching around, here is another solution

public function collect(Mage_Sales_Model_Quote_Address $address) {
    parent::collect($address);

    //Pay attention to this code
    $items = $this->_getAddressItems($address);
    if (!count($items)) {
        return $this; //this makes only address type shipping to come through
    }

    //Do whatever you want here to add discount or fee...

    return $this;
}

By doing this, the discount or fee will only added to the shipping address, and it will count once. So we even don't need to add the if ($address->getAddressType() == 'shipping') { in the fetch function.

Is it possible that you are adding in your own layout xml code for a shopping cart block? If you are, there is a solid chance that block is being called twice (one from the base code, and again for your code -- even if you are just extending it), thus duplicating the price total. If that is the case, you will need to remove (destructively with the <remove> tag) the base layout xml for that block, and things should then fall into place and work.

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