1

I've been trying all sort of things with no luck in order to do the following: I have a bundle product with options items. Based on customer input on the bundle product page, I need to get the cheapest item selected, change its price and set it to $0 (free). So basically, the customer selects 3 options and get the cheapest for free.

Any help?

I Update my question with what I did so far :

In config.xml added Observer :

<observers>
    <checkout_cart_product_add_after>
        <class>site/observer</class>
        <method>cartProductAddAfter</method>
    </checkout_cart_product_add_after>
</observers>

In Observer.php Added function as follow :

public function cartProductAddAfter($observer)
{
    $event = $observer->getEvent();
    $item = $event->getQuoteItem();
    $cart_items = Mage::getSingleton('checkout/session')->getQuote()->getAllVisibleItems();
    $product_id = 436; //bundle product id we are interested in
    $bundled_product = Mage::getModel('catalog/product')->load($product_id);
    $selectionCollection = $bundled_product->getTypeInstance(true)->getSelectionsCollection($bundled_product->getTypeInstance(true)->getOptionsIds($bundled_product), $bundled_product);
    $bundled_items_sku = array();
    foreach( $cart_items as $items ){
        if($items->getProductType() != 'bundle'){
            $pro_id=$items->getProductId();
            $pro_sku=$items->getSku();
            foreach ($selectionCollection as $option):
                $bundled_items_sku = Mage::getModel('catalog/product')->load($pro_id)->getSku();
                $data = Mage::getModel('catalog/product')->loadByAttribute('sku', $bundled_items_sku);
                $prices []= Mage::helper('tax')->getPrice($data, $data->getFinalPrice(), true);
            endforeach;
        }
    }
    $updateAmount = min($prices); //get the lowest selected price value
    //adding custom with original price
    $finalPrice = $productPrice - $updateAmount;
    //Zend_Debug::dump(min($prices));
    //exit;
    if($finalPrice){
        $item->setCustomPrice($finalPrice);
        $item->setOriginalCustomPrice($finalPrice);
        $item->getProduct()->setIsSuperMode(true);
    }
    Mage::log('Entered Data '.$finalPrice, null, '3rdlowestfree.log');
    //Mage::getSingleton('core/session')->addSuccess($finalPrice);
    //return $this;
}

This works, the product is added to the cart with the cheapest selected option amount deducted from the cart total bundle product price. However, on the cart page, I have a strange behavior: the bundle product price is not right but the grand total of the order is correct. It seems there are some tax calculations wrong somewhere in the cart lines items.

Help appreciated ;-)

Modified function as follow :

        public function cartProductAddAfter($observer)
    {
                $event = $observer->getEvent();
                $item = $event->getQuoteItem();
                // $cart_items = Mage::getSingleton('checkout/session')->getQuote()->getAllVisibleItems();
                $product_id = 436; //bundle product id we are interested in (local)
                $bundle_option = Mage::app ()->getRequest ()->getParam('bundle_option');
                $bundle_option_array = call_user_func_array('array_merge', $bundle_option);
                $bundle_option_price_array = array();
                $product = new Mage_Catalog_Model_Product();
                $product->load($product_id);
                $price=0;
                $updateAmount =0;
                $prices=array();
                $selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection($product->getTypeInstance(true)->getOptionsIds($product), $product);
                foreach($selectionCollection as $option) 
                {
                if (in_array($option->getSelectionId(), $bundle_option_array)){
                $price += $option->price; //Bundle total regular price as selected by user
                $prices[]= $option->price; //all customer selected options prices
                }
                }
                $lowestprice = min($prices); //min option selected price by customer
                $updateAmount = (float)($price-$lowestprice);
                // Zend_Debug::dump(array($updateAmount));
                // Zend_Debug::dump(array($lowestprice));
                // Zend_Debug::dump($price);
                // exit;
    if($updateAmount>0){
        $item->setCustomPrice($updateAmount);
                $item->setOriginalCustomPrice($updateAmount);
                $item->setOriginalSpecialPrice($updateAmount);
        $item->getProduct()->setIsSuperMode(true);
                // $item->save();
    }
        Mage::log('Entered Data '.$price.' - '.$updateAmount.' - '.$lowestprice.'', null, '3rdlowestfree.log');

        // Mage::getSingleton('core/session')->addSuccess($updateAmount);
        return $this;

All good Except the price result in the cart is systematically double of what it should be. Example : options selected 29+22+18 = 69, with applied modification should be 51. Bundle product price in cart is 102 ... like the new price is applied twice. Qty items is 1 as expected and logs show proper amounts applied.

:-(

Here's another update :

$event = $observer->getEvent();
$item = $event->getQuoteItem();
$data =  $item->getBuyRequest()->getData();
if(isset($data['mybundleproduct'])):
$mybundleproduct = $data['mybundleproduct'];
$bundle_option = Mage::app ()->getRequest ()->getParam('bundle_option');
$bundle_option_array = call_user_func_array('array_merge', $bundle_option);
$product = new Mage_Catalog_Model_Product();
$product->load($mybundleproduct);
$selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection($product->getTypeInstance(true)->getOptionsIds($product), $product);
foreach($selectionCollection as $option) 
{
if (in_array($option->getSelectionId(), $bundle_option_array)){
// $price += $option->price; //Bundle total regular price as selected by user
$itemId[] = $option->getSelectionId(); //added to be able to update cheapest selection
$itemPrice[] = $option->getPrice(); //added to be able to update cheapest selection
$price = $option->price; //Bundle total regular price as selected by user
$prices[]= $option->price; //all customer selected options prices
}
}
$lowestprice = min($prices); //min option selected price by customer to be deducted from base price
$updateAmount = ($price-$lowestprice);

//addition to retrieve each item option id and price into an array
foreach($itemId as $key=>$val){ // Loop though array
    $val2 = $prices[$key]; // Get the values from the other arrays
    $result[] = array( //Save result in third array
      'option_id' => $val,
      'price' => $val2,
    );
  }
    array_multisort(array_column($result, 'price'), SORT_ASC,$result);//sort the cheapest option price found in array
    $cheapestOption = $result[0]["price"];//get cheapest option price value
    $cheapestId = $result[0]["option_id"];//get cheapest option id
    foreach($selectionCollection as $options) {
        if($options->getSelectionId() == $cheapestId):
            $unserialized = unserialize($cheapestOption);
            $NewPrice = 0; // zero PRICE
            $unserialized['price'] = number_format($NewPrice, 2, '.', ',');
            // $options->setSelectionValuePrice($unserialized['price']); // ? or $options->setSelectionPriceValue($unserialized['price']) ?
            $options->getSelectionId()->setPrice($unserialized['price']); // ? or $options->setSelectionPriceValue($unserialized['price']) ?
        endif;
    }
//end addition

$item->setBundleOptionsData($options); 
$item->setBundleSelectionsData($options);
$item->setAffectBundleProductSelections(true);
$item->setCustomPrice($updateAmount);
$item->setOriginalCustomPrice($updateAmount);
$item->setOriginalSpecialPrice($updateAmount);
$item->setCanSaveCustomOptions(true);
$item->setCanSaveBundleSelections(true);
$item->getProduct()->setIsSuperMode(true);
// Mage::getSingleton('checkout/cart')->save();
// $item->save();
// Mage::log('Entered Data '.$price.' - '.$updateAmount.' - '.$lowestprice.'', null, '3rdlowestfree.log');
endif;
            // Mage::getSingleton('core/session')->addSuccess($updateAmount);
            return $this;

This gives me the correct total price so like my previous example : 18+22+29-18 = 52. However the next issue I have is in the cart the options displayed are still with the old value which is totally confusing so I need to change the cheapest option price to zero when adding it to the cart.

So I added the following :

//addition to retrieve each item option id and price into an array
foreach($itemId as $key=>$val){ // Loop though array
    $val2 = $prices[$key]; // Get the values from the other arrays
    $result[] = array( //Save result in third array
      'option_id' => $val,
      'price' => $val2,
    );
  }
    array_multisort(array_column($result, 'price'), SORT_ASC,$result);//sort the cheapest option price found in array
    $cheapestOption = $result[0]["price"];//get cheapest option price value
    $cheapestId = $result[0]["option_id"];//get cheapest option id
    foreach($selectionCollection as $options) {
        if($options->getSelectionId() == $cheapestId):
            $unserialized = unserialize($cheapestOption);
            $NewPrice = 0; // zero PRICE
            $unserialized['price'] = number_format($NewPrice, 2, '.', ',');
            // $options->setSelectionValuePrice($unserialized['price']); // ? or $options->setSelectionPriceValue($unserialized['price']) ?
            $options->getSelectionId()->setPrice($unserialized['price']); // ? or $options->setSelectionPriceValue($unserialized['price']) ?
        endif;
    }
//end addition

And at the end finally :

$item->setBundleOptionsData($options); 
$item->setBundleSelectionsData($options);
$item->setAffectBundleProductSelections(true);
$item->setCustomPrice($updateAmount);
$item->setOriginalCustomPrice($updateAmount);
$item->setOriginalSpecialPrice($updateAmount);
$item->setCanSaveCustomOptions(true);
$item->setCanSaveBundleSelections(true);
$item->getProduct()->setIsSuperMode(true);

But I can't get the option price to get saved. Anyone has an idea ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.