22

I have products set up identically (as far as I can tell) and they were all imported with a universal CSV template.

  • Configurable price is 29.99
  • Associated Simple Product Short Sleeve is 29.99
  • Associated Simple Product Long Sleeve is 39.99

An invoice recently billed a long sleeve product (ZTWS-SBLS-XL) that has a price of 39.99 with the configurable product price of 29.99. How can I force the simple product price to override the configurable product price? Both products below are set up identically with their parent configurable product and as simple products.

Invoice:

Item             Sku             Qty    Subtotal
Item one         ZLOB-SBLS-XL    1      $39.99
Item Two         ZTWS-SBLS-XL    1      $29.99

EDIT: Still working on resolving this. What would cause Magento to prefer the simple product price over the configurable product price or the associated product attribute price?

1

6 Answers 6

19

When you create a configurable product it doesn't matter what's the price of simple products -- these prices are ignored completely. So if you want to sell a simple product A which has price $29.99 and a simple product B ($39.99) then you must create a configurable product, set its price to $29.99 and open Associated product tab. Add products you want to associate with this configurable product. After adding them a block named Super product attributes configuration appears which contains options and price differences. Leave product A price empty and put 10 (+$10) to product B price field and voila: different simple product have different price.

There's actually an extension that allows you to use simple product prices instead of price differences, but it's kind of tricky to set up. Since it's free extension, I hope nobody complains about me pasting its link here:

https://github.com/organicinternet/magento-configurable-simple

4
  • You helped me understand my problem. I have updated my pricing scheme so that the products are set to a price of 29.99. From associated products we tack on $10 to long sleeve attributes and $2 for >=2x attributes. What is interesting is that this works for some products while it does not work on other configurable products. Commented Jun 2, 2014 at 18:59
  • For the products that it does not work on, magento prefers simple product price over the configurable price whether set on the product itself or in the associated products attributes price. Commented Jun 2, 2014 at 19:32
  • 5
    The extension is crap and buggy. Commented Jun 8, 2015 at 22:18
  • Can i get help regard configurable products magento.stackexchange.com/q/291238/57334 @Pronto
    – zus
    Commented Oct 9, 2019 at 7:13
17

So, I use the code below in combination with an extension like organic internet simple configurable products.

The code below is meant for the cart/checkout process, essentially, it's an update to the configurable price model that passes price calculation to a simple product in the event the product has been added to the cart --- this solution DOES NOT display pricing on the product page itself (however there are many extensions that do that already).

Update app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php (ideally you use an extension or local override in app/code/local)

Update the method: getFinalPrice, change to

public function getFinalPrice($qty=null, $product)
{
    //Start edit
    $selectedAttributes = array();
    if ($product->getCustomOption('attributes')) {
        $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
    }
    //End edit
    if (sizeof($selectedAttributes)) return $this->getSimpleProductPrice($qty, $product);

    if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) {
        return $product->getCalculatedFinalPrice();
    }

    $basePrice = $this->getBasePrice($product, $qty);
    $finalPrice = $basePrice;
    $product->setFinalPrice($finalPrice);
    Mage::dispatchEvent('catalog_product_get_final_price', array('product' => $product, 'qty' => $qty));
    $finalPrice = $product->getData('final_price');

    $finalPrice += $this->getTotalConfigurableItemsPrice($product, $finalPrice);
    $finalPrice += $this->_applyOptionsPrice($product, $qty, $basePrice) - $basePrice;
    $finalPrice = max(0, $finalPrice);

    $product->setFinalPrice($finalPrice);
    return $finalPrice;
}

Then add this function right below getFinalPrice:

public function getSimpleProductPrice($qty=null, $product)
    {
        $cfgId = $product->getId();
        $product->getTypeInstance(true)
            ->setStoreFilter($product->getStore(), $product);
        $attributes = $product->getTypeInstance(true)
            ->getConfigurableAttributes($product);
        $selectedAttributes = array();
        if ($product->getCustomOption('attributes')) {
            $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
        }
        $db = Mage::getSingleton('core/resource')->getConnection('core_read');
        $dbMeta = Mage::getSingleton('core/resource');
        $sql = <<<SQL
SELECT main_table.entity_id FROM {$dbMeta->getTableName('catalog/product')} `main_table` INNER JOIN
{$dbMeta->getTableName('catalog/product_super_link')} `sl` ON sl.parent_id = {$cfgId}
SQL;
        foreach($selectedAttributes as $attributeId => $optionId) {
            $alias = "a{$attributeId}";
            $sql .= ' INNER JOIN ' . $dbMeta->getTableName('catalog/product') . "_int" . " $alias ON $alias.entity_id = main_table.entity_id AND $alias.attribute_id = $attributeId AND $alias.value = $optionId AND $alias.entity_id = sl.product_id";
        }
        $id = $db->fetchOne($sql);
        return Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty);
    }

You can see, in the event the user has "customized" the product (IE, selected configurable options) we determine the associated simple product and pass control to its pricing model, otherwise if the product isn't "customized" (IE, we're browsing on the product page) we proceed as normal

2
  • this answer is genius, bravo!
    – pixiemedia
    Commented Dec 12, 2015 at 13:00
  • @pixiemedia this seems works perfectly on BCP extension which had extract issue, but before move the changes to live site i want to know anyone found any issue when it use in long term Commented Apr 17, 2020 at 16:54
5

Using Magento Version 1.9.2.2

May be slightly better solution, use 'Observer' approach instead of hacking the core or even overriding the default Model Price class i.e. app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php

All you have to do is to use Alan's code within your newly created Observer the only difference is instead of returning

Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty);

Replace it with the following:

$fp = Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty);
return $product->setFinalPrice($fp);

Follow this Observer.php

class YourFolderinLOCAL_YourModulename_Model_Observer 
{

     public function simpleProductPrice(Varien_Event_Observer $observer) {
        $event   = $observer->getEvent();
        $product = $event->getProduct();
        $qty     = $event->getQty();
        //Mage::log($observer, null, 'confPricing.log');
        // process percentage discounts only for simple products


            $selectedAttributes = array();
            if ($product->getCustomOption('attributes')) {
                Mage::log('yes-----', null, 'confPricing.log');
                $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
            }

            if (sizeof($selectedAttributes)) return $this->getSimpleProductPrice($qty, $product);



    }


    public function getSimpleProductPrice($qty=null, $product)
    {

        $cfgId = $product->getId();
        $product->getTypeInstance(true)
            ->setStoreFilter($product->getStore(), $product);
        $attributes = $product->getTypeInstance(true)
            ->getConfigurableAttributes($product);
        $selectedAttributes = array();
        if ($product->getCustomOption('attributes')) {
            $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
        }
        $db = Mage::getSingleton('core/resource')->getConnection('core_read');
        $dbMeta = Mage::getSingleton('core/resource');
        $sql = <<<SQL
SELECT main_table.entity_id FROM {$dbMeta->getTableName('catalog/product')} `main_table` INNER JOIN
{$dbMeta->getTableName('catalog/product_super_link')} `sl` ON sl.parent_id = {$cfgId}
SQL;
        foreach($selectedAttributes as $attributeId => $optionId) {
            $alias = "a{$attributeId}";
            $sql .= ' INNER JOIN ' . $dbMeta->getTableName('catalog/product') . "_int" . " $alias ON $alias.entity_id = main_table.entity_id AND $alias.attribute_id = $attributeId AND $alias.value = $optionId AND $alias.entity_id = sl.product_id";
        }
        $id = $db->fetchOne($sql);
        //Mage::log(Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty), null, 'confPricing.log');
        //return 
        $fp = Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty);
        return $product->setFinalPrice($fp);
    }


}

Config.xml

<?xml version="1.0"?>
<config> 
 <modules>
        <YourFolderinLOCAL_YourModulename>
            <version>0.0.1</version>
        </YourFolderinLOCAL_YourModulename>
    </modules>
    <global>
        <models>
            <YourFolderinLOCALYourModulename><!-- Al lovwercase in my case -->
                <class>Your_Model</class><!-- not needed in my case -->
            </YourFolderinLOCALYourModulename>
        </models>

    </global>
    <frontend>
    <events>
            <catalog_product_get_final_price>
                <observers>
                    <YourFolderinLOCAL_YourModulename_model_observer>
                        <type>singleton</type>
                        <class> YourFolderinLOCAL_YourModulename_Model_Observer</class>
                        <method>simpleProductPrice</method>
                    </YourFolderinLOCAL_YourModulenameg_model_observer>
                </observers>
            </catalog_product_get_final_price>

        </events>
        </frontend>
</config>

Hope it solves the problem.. :)

0
3

Kindly follow the below steps to change the super attribute price

First Use observers "catalog_product_get_final_price". Make observers like this :

Open your module config.xml and use below code :

<events>
    <catalog_product_get_final_price>
        <observers>
            <Setblue_Banner_Model_Observer>
                <type>singleton</type>
                <class>Setblue_Banner_Model_Observer</class>
                <method>getFinalPrice</method>
            </Setblue_Banner_Model_Observer>
        </observers>
    </catalog_product_get_final_price>
</events>

Now make the Observer.php file in model and past below code

<?php
class Setblue_Banner_Model_Observer
{

 public function getFinalPrice(Varien_Event_Observer $observer) {

  $event   = $observer->getEvent();
        $product = $event->getProduct();
        $qty     = $event->getQty();

  $selectedAttributes = array();
  if ($product->getCustomOption('attributes')) {
   Mage::log('yes-----', null, 'confPricing.log');
   $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
  }

  if (sizeof($selectedAttributes)) return $this->getSimpleProductPrice($qty, $product);

    }

 public function getSimpleProductPrice($qty=null, $product)
    {

  $cfgId = $product->getId();
        $product->getTypeInstance(true)
            ->setStoreFilter($product->getStore(), $product);
        $attributes = $product->getTypeInstance(true)
            ->getConfigurableAttributes($product);
        $selectedAttributes = array();
        if ($product->getCustomOption('attributes')) {
            $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
        }
        $db = Mage::getSingleton('core/resource')->getConnection('core_read');
        $dbMeta = Mage::getSingleton('core/resource');
        $sql = <<<SQL
SELECT main_table.entity_id FROM {$dbMeta->getTableName('catalog/product')} `main_table` INNER JOIN
{$dbMeta->getTableName('catalog/product_super_link')} `sl` ON sl.parent_id = {$cfgId}
SQL;
        foreach($selectedAttributes as $attributeId => $optionId) {
            $alias = "a{$attributeId}";
            $sql .= ' INNER JOIN ' . $dbMeta->getTableName('catalog/product') . "_int" . " $alias ON $alias.entity_id = main_table.entity_id AND $alias.attribute_id = $attributeId AND $alias.value = $optionId AND $alias.entity_id = sl.product_id";
        }
        $id = $db->fetchOne($sql);
        //Mage::log(Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty), null, 'confPricing.log');
        //return
        $fp = Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty);
        return $product->setFinalPrice($fp);
 }

}

?>

Now open app/design/frontend/default/yourtheme/template/catalog/product/view/type/options/configurable.phtml and paste below code anywhere in file

<ul class="productIds" style="display:none;">
    <?php
        $configurableProduct = Mage::getModel('catalog/product')->load($_product->getId());
        $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null,$configurableProduct);
        foreach($childProducts as $child) {
            $_productObj = Mage::getModel('catalog/product')->load($child->getId());
            ?>
            <li id='simple_<?php echo $child->getId(); ?>'><?php echo Mage::helper('core')->currency($_productObj->getFinalPrice()); ?></li>
        <?php   
        }
    ?>
</ul>

Now open js/varien/configurable.js and change reloadPrice function as below or you can replace this whole function aswell

reloadPrice: function(){
    if (this.config.disablePriceReload) {
        return;
    }
    var price    = 0;
    var oldPrice = 0;
    for(var i=this.settings.length-1;i>=0;i--){
        var selected = this.settings[i].options[this.settings[i].selectedIndex];
        if(selected.config){
            price    += parseFloat(selected.config.price);
            oldPrice += parseFloat(selected.config.oldPrice);
        }
    }

    /* Edit Code By Chandresh Rana*/

     //optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice});
     optionsPrice.reload();

     var existingProducts = new Object();
     for(var i=this.settings.length-1;i>=0;i--)
     {
         var selected = this.settings[i].options[this.settings[i].selectedIndex];
         if(selected.config)
         {
            for(var iproducts=0;iproducts<selected.config.products.length;iproducts++)
            {
                var usedAsKey = selected.config.products[iproducts]+"";
                if(existingProducts[usedAsKey]==undefined)
                {
                    existingProducts[usedAsKey]=1;
                }
                else
                {
                    existingProducts[usedAsKey]=existingProducts[usedAsKey]+1;
                }
             }
         }
     }

     for (var keyValue in existingProducts)
     {
        for ( var keyValueInner in existingProducts)
         {
            if(Number(existingProducts[keyValueInner])<Number(existingProducts[keyValue]))
            {
                delete existingProducts[keyValueInner];
            }
         }
     }

     var sizeOfExistingProducts=0;
     var currentSimpleProductId = "";
     for ( var keyValue in existingProducts)
     {
        currentSimpleProductId = keyValue;
        sizeOfExistingProducts=sizeOfExistingProducts+1
     }

     if(sizeOfExistingProducts==1)
     {
        if($('product-price-'+this.config.productId)){
            $('product-price-'+this.config.productId).innerHTML = jQuery("#simple_"+currentSimpleProductId).html();
        }

     }
    // End Code By Chandresh Rana

    return price;

    if($('product-price-'+this.config.productId)){
        $('product-price-'+this.config.productId).innerHTML = price;
    }
    this.reloadOldPrice();
},

Code Taken from: http://chandreshrana.blogspot.in/2016/03/set-simple-product-price-instead-of.html

1
2

If the simple products are of different price but are set-up against the configurable product without a price setting, either fixed or percentage, then the price of the configurable product will be taken. No matter which simple products are bought their price does not appears to be taken into account.

To update this simply go into the parent product in the admin section, then under the tab Associated Products you can update the price of each child product to add an additional price onto the parents products price.

5
  • Hi David, I have tried this. My current effort consist of setting the configurable product price to $0.00 and from the Associated products section I am trying to set a fixed priced of $29.99 on short sleeve attributes and $39.99 on long sleeve shirts. For whatever reason, there is still a single configurable product (long sleeve) that wants to charge $29.99 despite the fixed price AND the price being set within the simple product itself. Thank you for your response. Commented May 19, 2014 at 12:41
  • @user1812580 can you see this product in the admin or simply in the front end? Commented May 19, 2014 at 19:40
  • I can see it as a separate simple product associated with the configurable product. Commented May 20, 2014 at 10:41
  • Hi David, I have updated the pricing scheme as stated in my response to @Pronto. Hopefully that will help you help me? Commented Jun 2, 2014 at 19:31
  • @DavidManners I've tried updating my pricing via the Super Attributes Config section on the configurable product. However, the pricing only updates on the TOP price-info box (Where sku, product name etc are) when you click on the variation. Any tips on how to get the lower price box to update too? Commented Aug 9, 2016 at 20:06
2

I'm also having same issue and I fixed by using below code. It will work in admin side as well if you order from admin (for telephonic order)

Observe this event,

sales_quote_item_set_product 

and add below code in your Observer.php

public function loadQuote(Varien_Event_Observer $observer)
            {

                $event      = $observer->getEvent();
                $quote_item = $event->getQuoteItem();
                $storeId    = $quote_item->getStoreId();
                $item       = $observer->getQuoteItem();
                $product    = $observer->getProduct();
                $sku        = $product->getSku();
                $productDetails     =  Mage::getModel('catalog/product')
                            ->setStoreId($storeId)
                            ->loadByAttribute('sku',$sku);

                $price      = $productDetails->getPrice();
                $sprice     = $productDetails->getFinalPrice();

                $item->setOriginalCustomPrice($sprice);
                $item->setOriginalPrice($price);

            }

It will get the associated product price and saved in quote.

1
  • +1 for $item->setOriginalCustomPrice($sprice); and $item->setOriginalPrice($price);, that allows multiple configurable items that point to same product, in cart, with different prices.
    – Niloct
    Commented Aug 19, 2015 at 19:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.