Programmatically add product to cart with price change

PhpMagento

Php Problem Overview


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();
}

Php Solutions


Solution 1 - Php

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);
         }
    }
}

Solution 2 - Php

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.

Solution 3 - Php

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...

Solution 4 - Php

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+.

Solution 5 - Php

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;
}

Solution 6 - Php

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMukesh ChapagainView Question on Stackoverflow
Solution 1 - PhpinterimpulsoView Answer on Stackoverflow
Solution 2 - PhpJonathan DayView Answer on Stackoverflow
Solution 3 - PhpSimonView Answer on Stackoverflow
Solution 4 - PhpshauneView Answer on Stackoverflow
Solution 5 - PhpDeepak BhattaView Answer on Stackoverflow
Solution 6 - PhpknowzeroView Answer on Stackoverflow