How to Add Setup Pricing to a Product

Last modified by JMarkMurphy on Wed, May 12, 2010 09:28
Source|Old Revisions  

This is an old revision of the document!


This article applies directly to Magento version 1.1.3, I have not validated it for any other version. If you have information pertaining to other versions of Magento, please leave a comment at the bottom of the page. This has been tested and works in Magento 1.4.


The goal of this extension is to create a pricing structure that allows tier pricing for large quantity ordering, but also provides for a setup fee that is not dependent on the quantity ordered to be included in the price of the product. The final pricing formula would look something like this:

final price = (price * quantity) + setup fee

Custom options with prices do not work in this model because they are included in the unit price of the product. I will use a price type attribute named setup_fee to hold the setup fee for the product. If the attribute does not exist for the product, then it is not displayed on the cart, and is not included in the total price. BTW, in my real-world requirements I had two such fees, and created an attribute for each one.


It is important to recognize that names are case sensitive. There is a direct correlation between the name of the attribute you create to hold your setup fee, and the getter that you will be using to retrieve the value from the product. The attribute name should be all lower case with underscores between the words. This will associate automatically with a getter named using the attribute name in CamelCase without underscores, and prefixed with “get”. I will use the attribute setup_fee in this article. The product attribute setup_fee can be retrieved from a product object using getSetupFee(). Notice the correlation between the attribute name and the getter name.

Create a New Module

The goal here is to create a new module that can be used to provide the desired pricing function without changing the core Magento code. Throughout this example I will be using the local code pool with a namespace of Company. The module name will be MyModule, and the base Magento directory will be /Magento.

To create the new module we will add the following directories to our Magento install:


In addition we will need to notify Magento of this new module by creating the following file:


  1. <?xml version="1.0" encoding="UTF-8"?>
  3. <config>
  4.     <modules>
  5.         <Company_MyModule>
  6.             <active>true</active>
  7.             <codePool>local</codePool>
  8.         </Company_MyModule>
  9.     </modules>
  10. </config>

Edit config.xml

config.xml describes the module structure to Magento and, in this example, handles the rewrites necessary to tell Magento where our extended classes are, and which classes they replace. Create this file:


  1. <?xml version="1.0" encoding="UTF-8"?>
  3. <config>
  5.     <modules>
  6.         <Company_MyModule>
  7.             <version>0.1.0</version>
  8.         </Company_MyModule>
  9.     </modules>
  11.     <global>
  12.         <blocks>
  13.             <checkout>
  14.                 <rewrite>
  15.                     <cart_item_renderer>Company_MyModule_Block_Cart_Item_Renderer</cart_item_renderer>
  16.                 </rewrite>
  17.             </checkout>
  18.         </blocks>   
  20.         <models>
  21.           <!-- may not need this here since the only model class is a rewrite -->
  22.             <mymodule>
  23.                 <class>Company_MyModule_Model</class>
  24.             </mymodule>
  25.           <!-- definately need this! -->
  26.             <sales>
  27.                 <rewrite>
  28.                     <quote_item>Company_MyModule_Model_Quote_Item</quote_item>
  29.                 </rewrite>
  30.             </sales>
  31.         </models>
  32.     </global>
  34. </config>

Extend the Renderer

I want the setup price to display in the cart with each item. If I have more than one attribute I want to display here, I will add additional methods like getSetupFee(). This class simply provides an easy way to get at these values from the templates. Since I am only using simple items, I am just going to update the default item renderer. Add the following file:


  1. <?php
  3. class Company_MyModule_Block_Cart_Item_Renderer extends Mage_Checkout_Block_Cart_Item_Renderer
  4. {
  5.     public function getLoadedProduct()
  6.     {
  7.         return $this->getProduct()->load($this->getProduct()->getId());
  8.     }
  10.     public function getSetupFee()
  11.     {
  12.         return $this->getLoadedProduct()->getSetupFee();
  13.     }
  14. }

Extend the Sales/Model/Quote/Item.php

I want the setup fee to be added to the row amount without multiplying by the quantity. So I want to override calcRowTotal(). Create the following file:


  1. <?php
  3. class Company_MyModule_Model_Quote_Item extends Mage_Sales_Model_Quote_Item
  4. {
  5.     public function calcRowTotal()
  6.     {
  7.         parent::calcRowTotal();
  8.         $product = $this->getProduct();
  9.         $product->load($product->getId());
  11.         // This is where I add the Setup Fee, more than one fee can be added
  12.         // here if necessary
  13.         $baseTotal = $this->getBaseRowTotal() + $product->getSetupFee();
  15.         $total = $this->getStore()->convertPrice($baseTotal);
  16.         $this->setRowTotal($this->getStore()->roundPrice($total));
  17.         $this->setBaseRowTotal($this->getStore()->roundPrice($baseTotal));
  18.         return $this;
  19.     }
  20. }

Modify Templates

The Item Renderers appear in two places in the template files, one for the Shopping Cart (/Magento/app/design/frontend/default/default/template/checkout/cart/item/default.phtml), and the other for the checkout review stage (/Magento/app/design/frontend/default/default/template/checkout/onepage/review/item.phtml). We are going to have to update both of these template files. Fortunately the change is the same, and goes in about the same place, in each file.

NOTE: If you are using a custome theme, you need to make these changes to
your theme rather than the default.
For example:

Make the following changes to:


  1. <?php $_item = $this->getItem()?>
  2. <tr>
  3.     <td class="a-center"><a href="<?php echo $this->getDeleteUrl() ?>"><img src="<?php echo $this->getSkinUrl('images/btn_trash.gif') ?>" width="16" height="16" alt="<?php echo $this->__('Remove item')?>" title="<?php echo $this->__('Remove item')?>" /></a></td>
  4.     <td><a href="<?php echo $this->getProductUrl() ?>"><img src="<?php echo $this->getProductThumbnail()->resize(75); ?>" width="75" alt="<?php echo $this->htmlEscape($this->getProductName()) ?>" title="<?php echo $this->htmlEscape($this->getProductName()) ?>" /></a></td>
  5.     <td>
  6.         <h3 class="product-name"><a href="<?php echo $this->getProductUrl() ?>"><?php echo $this->getProductName() ?></a></h3>
  7.         <?php if ($_options = $this->getOptionList()):?>
  8.         <dl class="item-options">
  9.             <?php foreach ($_options as $_option) : ?>
  10.             <?php $_formatedOptionValue = $this->getFormatedOptionValue($_option['value']) ?>
  11.             <dt><?php echo $this->htmlEscape($_option['label']) ?></dt>
  12.             <dd<?php if (isset($_formatedOptionValue['full_view'])): ?> class="truncated"<?php endif; ?>><?php echo $_formatedOptionValue['value'] ?>
  13.                 <?php if (isset($_formatedOptionValue['full_view'])): ?>
  14.                 <div class="truncated_full_value">
  15.                     <dl class="item-options">
  16.                         <dt><?php echo $this->htmlEscape($_option['label']) ?></dt>
  17.                         <dd><?php echo $_formatedOptionValue['full_view'] ?></dd>
  18.                     </dl>
  19.                 </div>
  20.                 <?php endif; ?>
  21.             </dd>
  22.             <?php endforeach; ?>
  23.         </dl>
  24.         <?php endif;?>
  25. <!-- Code to display Setup Fee starts here -->
  26.         <?php if ($setup_fee = $this->getSetupFee()) : ?>
  27.         <dl class="item-options">
  28.                <dt>Setup Fees</dt>
  29.                <dd><?php if ($setup_fee): ?>Setup Fee Name - <?php echo $this->helper('checkout')->formatPrice($setup_fee) ?><?php endif; ?></dd>
  30.              <!-- if you have additional setup Fees, they can be put here as <dd> list entries -->
  31.         </dl>
  32.         <?php endif; ?>
  33. <!-- Code to display setup Fee ends here -->
  34.         <?php if ($messages = $this->getMessages()): ?>
  35.         <?php foreach ($messages as $message): ?>
  36.             <p class="item-msg <?php echo $message['type'] ?>">* <?php echo $message['text'] ?></p>
  37.         <?php endforeach; ?>
  38.         <?php endif; ?>
  39.     </td>
  40.     <?php if ($this->helper('wishlist')->isAllowInCart()) : ?>
  41.    ...

The changes to the second template file are similar. Change:


  1. <?php $_item = $this->getItem()?>
  2. <tr>
  3.     <td><h4 class="product-name"><?php echo $this->htmlEscape($this->getProductName()) ?></h4>
  4.         <?php if ($_options = $this->getOptionList()):?>
  5.         <dl class="item-options">
  6.             <?php foreach ($_options as $_option) : ?>
  7.             <?php $_formatedOptionValue = $this->getFormatedOptionValue($_option['value']) ?>
  8.             <dt><?php echo $this->htmlEscape($_option['label']) ?></dt>
  9.             <dd<?php if (isset($_formatedOptionValue['full_view'])): ?> class="truncated"<?php endif; ?>><?php echo $_formatedOptionValue['value'] ?>
  10.                 <?php if (isset($_formatedOptionValue['full_view'])): ?>
  11.                 <div class="truncated_full_value">
  12.                     <dl class="item-options">
  13.                         <dt><?php echo $this->htmlEscape($_option['label']) ?></dt>
  14.                         <dd><?php echo $_formatedOptionValue['full_view'] ?></dd>
  15.                     </dl>
  16.                 </div>
  17.                 <?php endif; ?>
  18.             </dd>
  19.             <?php endforeach; ?>
  20.         </dl>
  21.         <?php endif;?>
  22. <!-- Code to display Setup Fee starts here -->
  23.         <?php if ($setup_fee = $this->getSetupFee()) : ?>
  24.         <dl class="item-options">
  25.                <dt>Setup Fees</dt>
  26.                <dd><?php if ($setup_fee): ?>Setup Fee Name - <?php echo $this->helper('checkout')->formatPrice($setup_fee) ?><?php endif; ?></dd>
  27.         </dl>
  28.         <?php endif; ?>
  29. <!-- Code to display setup Fee ends here -->
  30.     </td>
  31.     <?php if ($this->helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()): ?>
  32.     <td class="a-right"><?php echo $this->helper('checkout')->formatPrice($_item->getCalculationPrice()) ?></td>
  33.     <?php endif; ?>
  34.   ...