Magento - Dynamically change discount cost in cart

odd_duck picture odd_duck · Jun 19, 2014 · Viewed 11.8k times · Source

In my magento store how can i go about changing the discount total in my shopping cart dynamically?

I'm able to access and get the current discount with this code:

<?php
$quote = Mage::getSingleton('checkout/cart')->getQuote();
$totals =  $quote->getTotals(); 
$discount = $totals["discount"]->getValue();
?>

I have a button in my shopping cart that when pressed should add an extra £5 onto the discount value, updating the total cost etc at the same time.

Answer

huzefam picture huzefam · Jun 21, 2014

There is an event in magento,

sales_quote_collect_totals_after

This is fired whenever your total is calculated, what you can do is set a flag in session on click on the button to apply discount, and in this above event's observer method, check if it is set then apply discount.

In your config.xml

<global>
 <events>
   <sales_quote_collect_totals_after>
     <observers>
       <class>Custom_Module_Model_Observer</class>
       <method>collectTotals</method>
     </observers>
   </sales_quote_collect_totals_after>
 </events>
</global>

Make a Observer.php in

Custom
  /Module
    /Model
      /Observer.php

Make a function in Observer.php

public function collectTotals(Varien_Event_Observer $observer)
{
       $quote=$observer->getEvent()->getQuote();
       $quoteid=$quote->getId();
    //check condition here if need to apply Discount
        if($disocuntApply) $discountAmount =5;

     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().', Amount Waived');
             $address->setBaseDiscountAmount(-($address->getBaseDiscountAmount()-$discountAmount));
             }else {
             $address->setDiscountAmount(-($discountAmount));
             $address->setDiscountDescription('Amount Waived');
             $address->setBaseDiscountAmount(-($discountAmount));
             }
             $address->save();
            }//end: if
           } //end: foreach
           //echo $quote->getGrandTotal();

          foreach($quote->getAllItems() as $item){
                         //We apply discount amount based on the ratio between the GrandTotal and the RowTotal
                         $rat=$item->getPriceInclTax()/$total;
                         $ratdisc=$discountAmount*$rat;
                         $item->setDiscountAmount(($item->getDiscountAmount()+$ratdisc) * $item->getQty());
                         $item->setBaseDiscountAmount(($item->getBaseDiscountAmount()+$ratdisc) * $item->getQty())->save();

                       }


                    }

            }
         }

collectTotals function will be called, whenever the quote totals is updated, so there is no need to call it explicitly.

Check for how it works here.

Setting magento session variables, check here.

hope it helps!