Magento 1.9 – Fix Programmatically Applied Discount Not Working with Currency Switcher

cartmagento-1.9shopping-cart-price-rules

I am applying custom discount to cart which should be applied if cart validates the shopping cart price rule, working fine discount getting applied.

But I just enabled the currency switcher and tested it on my custom applied discount and its not working with it,

ex : if base currency is dollar and I apply a $5 discount to cart where cart total is $90, so 90 – 5 = $85

works fine.

but when I switch the curreny to Euro cart total changes to €80.66 (standard currecy conversion) same should be done with custom discount but for discount only symbol changes to but value remain 5 and discount becomes €5, so value is 80.66 – 5 = €75.66

this is how I am applying discount to cart, please look at the code & suggest me how to do it correctly

config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Namespace_Modulename>
            <version>1.0.10</version>
        </Namespace_Modulename>
    </modules>
       <global>
      <events>
            <sales_quote_collect_totals_after>
              <observers>
                  <namespace>
                    <type>singleton</type>
                    <class>Namespace_Modulename_Model_Observer</class>
                    <method>setDiscount</method>
                  </namespace>
              </observers>
           </sales_quote_collect_totals_after>             
      </events>
  </global>

Observer.php

class Namespace_Modulename_Model_Observer
{
   public function setDiscount($observer)
   {
     $quote         =  $observer->getEvent()->getQuote();
     $quoteid       =  $quote->getId();
     $discountAmount=  10;

     if($quoteid) {

       if($discountAmount>0) {

         $total=$quote->getBaseSubtotal();
         $quote->setSubtotal(0);
         $quote->setBaseSubtotal(0);
         $quote->setSubtotalWithDiscount(0);
         $quote->setBaseSubtotalWithDiscount(0);
         $quote->setGrandTotal(0);
         $quote->setBaseGrandTotal(0);
         $canAddItems = $quote->isVirtual()? ('billing') : ('shipping'); 

         foreach ($quote->getAllAddresses() as $address) {

           $address->setSubtotal(0);
           $address->setBaseSubtotal(0);
           $address->setGrandTotal(0);
           $address->setBaseGrandTotal(0);
           address->collectTotals();
           $quote->setSubtotal((float) $quote->getSubtotal() + $address->getSubtotal());
           $quote->setBaseSubtotal((float) $quote->getBaseSubtotal() + $address->getBaseSubtotal());
           $quote->setSubtotalWithDiscount((float) $quote->getSubtotalWithDiscount() + $address->getSubtotalWithDiscount());
           $quote->setBaseSubtotalWithDiscount((float) $quote->getBaseSubtotalWithDiscount() + $address->getBaseSubtotalWithDiscount());
           $quote->setGrandTotal((float) $quote->getGrandTotal() + $address->getGrandTotal());
           $quote->setBaseGrandTotal((float) $quote->getBaseGrandTotal() + $address->getBaseGrandTotal());
           $quote ->save();
           $quote->setGrandTotal($quote->getBaseSubtotal()-$discountAmount)
                 ->setBaseGrandTotal($quote->getBaseSubtotal()-$discountAmount)
                 ->setSubtotalWithDiscount($quote->getBaseSubtotal()-$discountAmount)
                 ->setBaseSubtotalWithDiscount($quote->getBaseSubtotal()-$discountAmount)
                 ->save(); 


                if($address->getAddressType()==$canAddItems) {
                   $address->setSubtotalWithDiscount((float)$address->getSubtotalWithDiscount()-$discountAmount);
                   $address->setGrandTotal((float) $address->getGrandTotal()-$discountAmount);
                   $address->setBaseSubtotalWithDiscount((float)$address->getBaseSubtotalWithDiscount()-$discountAmount);
                   $address->setBaseGrandTotal((float)$address->getBaseGrandTotal()-$discountAmount);
                if($address->getDiscountDescription()){
                $address->setDiscountAmount(-($address->getDiscountAmount()-$discountAmount));
                     $address->setDiscountDescription($address->getDiscountDescription().', Custom Discount');
                $address->setBaseDiscountAmount(-($address->getBaseDiscountAmount()-$discountAmount));
                }else {
                    $address->setDiscountAmount(-($discountAmount));
                    $address->setDiscountDescription('Custom Discount');
                    $address->setBaseDiscountAmount(-($discountAmount));
                }
                $address->save();
           }//end: if
        } //end: foreach

        foreach($quote->getAllItems() as $item){
             $rat=$item->getPriceInclTax()/$total;
             $ratdisc=$discountAmount*$rat;
             $item->setDiscountAmount(($item->getDiscountAmount()+$ratdisc) * $item->getQty());
             $item->setBaseDiscountAmount(($item->getBaseDiscountAmount()+$ratdisc) * $item->getQty())->save();
        }
        }
    }
 }
}

Best Answer

Issue solved, magento stores base discount amount & also current discount amount, base discount amount for base currency & current for current selected currency.

So update the code to :

class Namespace_Modulename_Model_Observer
{

  public function setDiscount($observer)
  {
    $quote         =  $observer->getEvent()->getQuote();
    $quoteid       =  $quote->getId();
    $discountAmount=  10;

    if($quoteid) {
        if( $discountAmount > 0 ) {

            $total        = $quote->getBaseSubtotal();
            $currenttotal = $quote->getSubtotal();

            $quote  ->setSubtotal(0);
            $quote  ->setBaseSubtotal(0);
            $quote  ->setSubtotalWithDiscount(0);
            $quote  ->setBaseSubtotalWithDiscount(0);
            $quote  ->setGrandTotal(0);
            $quote  ->setBaseGrandTotal(0);

            $canAddItems = $quote->isVirtual() ? ('billing') : ('shipping');

            foreach ($quote->getAllAddresses() as $address) {

                if($address->getAddressType() == $canAddItems) {

                    $address    ->setSubtotalWithDiscount(      (float) $address    ->getSubtotalWithDiscount() -       $this->convertCurrency($discountAmount));
                    $address    ->setGrandTotal(                (float) $address    ->getGrandTotal()   -               $this->convertCurrency($discountAmount));
                    $address    ->setBaseSubtotalWithDiscount(  (float) $address    ->getBaseSubtotalWithDiscount() -   $discountAmount);
                    $address    ->setBaseGrandTotal(            (float) $address    ->getBaseGrandTotal()   -           $discountAmount);
                    $address    ->setSubtotalInclTax(           (float) $address    ->getSubtotalInclTax()     -        $this->convertCurrency($discountAmount));
                    $address    ->setBaseSubtotalTotalInclTax(  (float) $address    ->getBaseSubtotalTotalInclTax()   - $discountAmount);


                    if($address->getDiscountDescription()){
                        $address->setDiscountAmount(-($address->getDiscountAmount()-$this->convertCurrency($discountAmount)));
                        $address->setDiscountDescription($address->getDiscountDescription().$this->__(', + Custom Discount'));
                        $address->setBaseDiscountAmount(-($address->getBaseDiscountAmount()-$discountAmount));
                    } else {
                        $address->setDiscountAmount(-($address->getBaseDiscountAmount()-$this->convertCurrency($discountAmount)));
                        //$address->setDiscountDescription($this->__('Custom Discount'));
                        $address->setDiscountDescription($address->getDiscountDescription().$this->__(' + Custom Discount'));
                        $address->setBaseDiscountAmount(-($discountAmount));
                    }
                    $address->save();

                    $quote  ->setSubtotal(      (float) $quote  ->getSubtotal()     + $address  ->getSubtotal());
                    $quote  ->setBaseSubtotal(  (float) $quote  ->getBaseSubtotal() + $address  ->getBaseSubtotal());

                    $quote  ->setBaseSubtotal(  (float) $quote  ->getBaseSubtotal() + $address  ->getBaseSubtotal());
                    $quote  ->setSubtotalWithDiscount(
                        (float) $quote  ->getSubtotalWithDiscount() + $address  ->getSubtotalWithDiscount()
                    );
                    $quote->setBaseSubtotalWithDiscount(
                        (float) $quote  ->getBaseSubtotalWithDiscount() + $address  ->getBaseSubtotalWithDiscount()
                    );
                    $quote  ->setGrandTotal(     (float) $quote ->getGrandTotal()     + $address    ->getGrandTotal());
                    $quote  ->setBaseGrandTotal( (float) $quote ->getBaseGrandTotal() + $address    ->getBaseGrandTotal());
                    $quote   ->save();

                    $quote  ->setGrandTotal(              $quote->getBaseSubtotal() -    $this->convertCurrency($discountAmount))
                            ->setBaseGrandTotal(          $quote->getBaseSubtotal() -    $discountAmount)
                            ->setSubtotalWithDiscount(    $quote->getBaseSubtotal() -    $this->convertCurrency($discountAmount))
                            ->setBaseSubtotalWithDiscount($quote->getBaseSubtotal() -    $discountAmount)
                            ->save();
                }//end: if
            } //end: foreach

            foreach(    $quote->getAllItems() as $item  ){
               //We apply discount amount based on the ratio between the GrandTotal and the RowTotal
               $rat             =   $item   ->getPriceInclTax() /   $total;
               $curRat          =   $item   ->getPriceInclTax() /   $currenttotal;
               $ratdisc         =   $discountAmount   *  $rat;
               $curRatDisc      =   $discountAmount   *  $curRat;

               $item  ->setDiscountAmount(    ($item  ->getDiscountAmount()    +   $ratdisc) * $item  ->getQty());
               $item  ->setBaseDiscountAmount(($item  ->getBaseDiscountAmount()+   $curRatDisc) * $item  ->getQty())->save();
            }
        }
    }
}

public function convertCurrency($amount)
{
    $baseCurrencyCode = Mage::app()->getStore()->getBaseCurrencyCode();
    $currentCurrencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();

    if ($baseCurrencyCode != $currentCurrencyCode) {
        $amount = Mage::helper('directory')->currencyConvert($amount, $baseCurrencyCode, $currentCurrencyCode);    
    }  

    return $amount; 
}
}
Related Topic