59

I want to add a product to cart programmatically. Also, I want to change the product price when added to cart.

Suppose, my product's price is $100. I wanted to change it to $90 when added to cart.

I added product to cart. However, I am unable to change the product price.

Is it possible?

Here is the code to add product to cart:-

$cart = Mage::getSingleton('checkout/cart');

try {   
    $cart->addProduct($product, array('qty' => 1));
    $cart->save();
}
catch (Exception $ex) {
    echo $ex->getMessage();
}
Logan Capaldo
  • 39,555
  • 5
  • 63
  • 78
Mukesh Chapagain
  • 25,063
  • 15
  • 119
  • 120
  • I was able to change product prices with the instructions from http://stackoverflow.com/questions/9721583/changing-the-price-in-quote-while-adding-product-to-cart-magento –  Jul 13 '12 at 13:35

6 Answers6

62

After digging a bit into Magento's core code, I found that you need to use $item->getProduct()->setIsSuperMode(true) in order to make $item->setCustomPrice() and $item->setOriginalPrice() work.

Here is some sample code you can use within an Observer that listens for the checkout_cart_product_add_after or checkout_cart_update_items_after events. The code is logically the same except checkout_cart_product_add_after is called for only one item and checkout_cart_update_items_after is called for all items in the cart. This code is separated/duplicated into 2 methods only as an example.

Event: checkout_cart_product_add_after

/**
 * @param Varien_Event_Observer $observer
 */
public function applyDiscount(Varien_Event_Observer $observer)
{
    /* @var $item Mage_Sales_Model_Quote_Item */
    $item = $observer->getQuoteItem();
    if ($item->getParentItem()) {
        $item = $item->getParentItem();
    }

    // Discounted 25% off
    $percentDiscount = 0.25; 

    // This makes sure the discount isn't applied over and over when refreshing
    $specialPrice = $item->getOriginalPrice() - ($item->getOriginalPrice() * $percentDiscount);

    // Make sure we don't have a negative
    if ($specialPrice > 0) {
        $item->setCustomPrice($specialPrice);
        $item->setOriginalCustomPrice($specialPrice);
        $item->getProduct()->setIsSuperMode(true);
    }
}

Event: checkout_cart_update_items_after

/**
 * @param Varien_Event_Observer $observer
 */
public function applyDiscounts(Varien_Event_Observer $observer)
{
    foreach ($observer->getCart()->getQuote()->getAllVisibleItems() as $item /* @var $item Mage_Sales_Model_Quote_Item */) {
         if ($item->getParentItem()) {
             $item = $item->getParentItem();
         }

         // Discounted 25% off
         $percentDiscount = 0.25; 

         // This makes sure the discount isn't applied over and over when refreshing
         $specialPrice = $item->getOriginalPrice() - ($item->getOriginalPrice() * $percentDiscount);

         // Make sure we don't have a negative
         if ($specialPrice > 0) {
             $item->setCustomPrice($specialPrice);
             $item->setOriginalCustomPrice($specialPrice);
             $item->getProduct()->setIsSuperMode(true);
         }
    }
}
leek
  • 11,803
  • 8
  • 45
  • 61
interimpulso
  • 729
  • 6
  • 3
  • This works only on cart update. How to achieve this effect when product is added to cart. Please help. – Arvind Bhardwaj Feb 08 '12 at 15:17
  • @Arvind07: Use the same listener but for the event `checkout_cart_product_add_after`, I've updated the answer to reflect both events. – leek Feb 28 '12 at 00:20
  • For some reason this isn't working Magento Enterprise 1.11 or 1.6CE. Any thoughts? – philwinkle Apr 10 '12 at 04:29
  • @leek is it possible for this custom priced to be set for just one specific user(based on cookie/other suggestions/registered user. – CodeGuru Apr 13 '13 at 18:35
  • $item->getOriginalPrice() does not return anything here on Magento CE 1.8. Any alternatives? – Michael Krupp Jan 22 '14 at 10:47
  • @keks you can use `$originalPrice = $item->getProduct()->getPrice();` for simple product type. – Rahul Dadhich Aug 04 '15 at 10:40
  • I think the ideal code would handle negative numbers by changing `$specialPrice` to 0, because as is, customer will not receive any discount if the discount is too large, which may upset customers expecting a discount. – Goose Oct 30 '15 at 14:16
  • turns out this answer doesn't work, but I cant remove the up vote – user3338098 Nov 19 '15 at 15:00
  • @interimpulso: your solution doesn't work for bundle product it updates the product price but the total price remains the same. Do you know how to fix that. Thanks in advance! – Akshay Jindal Jul 22 '16 at 09:03
8

Magento have changed the way the prices are calculated in the cart which makes it very difficult to do this in v1.4 onwards. If you do set the price using an Observer or other device, it will almost certainly be overwritten back to the catalog price.

Effectively, you need to use Shopping Cart rules to implement this.

Jonathan Day
  • 18,519
  • 10
  • 84
  • 137
7

It is possible to set a customer specific price of a quote item. Hence, something like this should do it:

$quoteItem = $quote->addProduct($product, $qty);
$quoteItem->setCustomPrice($price);
// we need this since Magento 1.4
$quoteItem->setOriginalCustomPrice($price);
$quote->save();

Hope this helps...

Simon
  • 4,103
  • 7
  • 28
  • 53
  • @Simon , possible if i can set a customized price for a specific customer who visit the website based on cookie/user(after they have done clicking on a link)? – CodeGuru Apr 13 '13 at 18:38
  • @RainbowHat Sure, should be possible. Please ask a new question for further questions. – Simon Apr 14 '13 at 22:01
4

Jonathan's answer is likely the best for most situations. But some customers might not like how shopping cart discounts are displayed in the cart. I recently did a project (with Magento 1.3.3) where the customer didn't like how the each line item still showed the full price as well as the subtotal, with a Discount line below the subtotal - he wanted to see the price of each item discounted, and the subtotal show the discounted price as well. He really didn't like having the Discount line after the Subtotal line.

Anyway, if you find yourself in the same boat, one approach is to override the getCalculationPrice() and getBaseCalculationPrice() methods in Mage_Sales_Model_Quote_Address_Item and Mage_Sales_Model_Quote_Item. I know that it isn't always pretty to override, much better to use events, but in this case I couldn't get events to work seamlessly on both the frontend and backend. Not sure if this approach will work in Magento 1.4+.

shaune
  • 2,510
  • 1
  • 31
  • 36
4

If I have to share my solution that I made on the base of Simon then I have managed to rewrite model class save function of quote.

public function save()
{

    $this->getQuote()->getBillingAddress();
    $this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
    $this->getQuote()->collectTotals();
    //$this->getQuote()->save();

    foreach($this->getQuote()->getAllItems() as $item) {             
          $productId = $item->getProductId();
          $product = Mage::getModel('catalog/product')->load($productId);
          if($product->getAttributeText('is_dummy') == 'Yes') {
            $price = 2;
            $item->setCustomPrice($price);
            // we need this since Magento 1.4
            $item->setOriginalCustomPrice($price);
          }
    }  
       $this->getQuote()->save();   
    $this->getCheckoutSession()->setQuoteId($this->getQuote()->getId());
    /**
     * Cart save usually called after chenges with cart items.
     */
    Mage::dispatchEvent('checkout_cart_save_after', array('cart'=>$this));
    return $this;
}
McDowell
  • 107,573
  • 31
  • 204
  • 267
Deepak Bhatta
  • 474
  • 4
  • 16
3

I had the same issue and i am not a developer. What i did was added a new price attribute in magento backend called "site price". On the product page this showed the higher price $100. the actual price of the item was $90. so when the shopper adds it to cart they will see the actual price of the item, but on the product page they see the custom attribute price of $100

if all your prices on the product page are a set % higher then the real price just multiply your product price by the 1+percent. So if you want to add 10% to all your prices do price*1.1 This will display your price as 10% higher but when the shopper adds to cart they will see the real price.

knowzero
  • 78
  • 8