Presentation of Dr. Nikolai Krambrock at Developers Paradise 2014
Magento allows tier prices for products and prices for individual options. However, tier prices for individual options are not supported. Tier prices for individual options are needed when selling promotional items or textiles with custom imprints. As an example, these are prices for pens with custom printings or engravings:
Price from | 0 | 50 | 100 |
€/item | 0,45 € | 0,39 € | 0,37 € |
+ Laser engraving | 5,00 € | 0,19 € | 0,15 € |
+ Screen printing | 4,50 € | 0,17 € | 0,13 € |
+ Pad printing | 4,00 € | 0,16 € | 0,12 € |
The price for the pen is € 0.45, € 0.39, € 0.37, € 0.35 or € 0.27, depending on the quantity ordered. The cost of the imprint should also be dependent on the quantity as well. This is not doable with Magento standard.
Ways of implementing tier prices for custom options
I went through three different options realizing tier prices for custom options. The last option is the best, from my point of view. I will describe it in detail later, focussing on the way we solved it in a customer project. I tried the following options:
Option | Advantages | Disadvantages |
Realize the surcharges with Cart Price Rules | No changes to the system (except maybe observers in the backend) | The discounts are only displayed in checkout in one sum |
Simple Configurable Products / Better Configurable Products | Good presentation and usage of a ready-to-use module meeting the requirements | For each attribute configuration a simple product must be created; deep impact on the standard system through many rewrites |
Generating additional individual options with prices | Good presentation and only little intervention in the base system | Backend contains many additional custom options – this is inconvenient for manual maintenance |
Displaying the surcharges on basket price rules
Realizing surcharges with basket price rules is the most elegant option if the products are imported with an import interface from an erp-system. In this case you can generate basket price rules, during or at the end of the import, which deliver discounts on each position. However, there is a major drawback: The discounts on the products are shown as one sum in the checkout. Therefore this option will only be useful in rare cases.
Simple Configurable Product / Better Configurable Products
The simplest solution from the developer’s perspective is the use of Simple Configurable Product (http://www.magentocommerce.com/magento-connect/simple-configurable-products.html) or Better Configurable Products (http://www.magentocommerce.com/magento-connect/better-configurable-products.html). I have tested Better Configurable Products only, as this was available for Magento 1.7 at the time of development. For each variant of the product, for example laser engraving, screen printing and pad printing, an additional simple product is added. Better Configurable Product makes sure that the tier price is taken from the simple product. However, with many products and many variants, it will quickly become confusing. If you can choose between small, medium and big printing on your pen, as well as having red, green and blue pens, the result will include 27 simple products, instead of three. All these simple products must be assigned to a configurable product. Furthermore, all 27 products have their own stock. Additionally both of the extensions use numerous rewrites that change the very core of the Magento system.
Generating additional individual options with prices
Having checked the options above, we decided to realize this option in a customer project. The basic idea is simple: An individual option only allows one surcharge, when 5 are needed- one for each tier price. So I add 5 individual options with different prices. The advantage of using this solution are moderate changes to the system while displaying the prices for the products in a reasonable way. The solution works with two observers – and additional rewrites of blocks for better visual appearance. Once passed the checkout, Magento just works with standard custom options. Therefore, it is very unlikely to experience problems in the later steps – e.g. invoice, shipment, credit memo and export to an erp-system. The disadvantages are additional options in the backend that are somewhat disturbing when maintaining the products by hand.
Submitting tier prices for individual options
The module we developed requires entering of tier prices and individual options, in the backend. Finally, the prices of the individual options for each tier price are entered in the newly generated options. We start by creating the tier price for one product:As the second step, we set the Printing type as an individual option:
When you save it, the following table of individual options will be generated. In this table, the tier prices can be entered for the original individual options:
Under the title “preis-lasergravur-100”, the price for Lasergravur with a minimum order of 100 pens is set. The rest of the generated fields must be set as well. When all these fields have been filled in, the result is expected to be in the checkout. For example, 120 ordered pens with Lasergravur will have a price of 0,37€ + 0,15€ for a total of 0.52€ per piece:
Development of Tier Prices for custom options
The main work in the module is performed by two observers. The first observer generates the individual options in the backend. The second observer chooses the correct option for changes in your shopping cart. The simplified config.xml looks like this:
<config> <modules> <C4B_Configurableprices> <version>0.0.1</version> </C4B_Configurableprices> </modules> <global> <events> <catalog_product_prepare_save> <observers> <c4b_configurableprices_catalog_product_observer> <type>singleton</type> <class>C4B_Configurableprices_Model_Catalog_Product_Option</class> <method>updateProductCustomOptions</method> </c4b_configurableprices_catalog_product_observer> </observers> </catalog_product_prepare_save> <checkout_cart_save_before> <observers> <c4b_configurableprices_cart_observer> <type>singleton</type> <class>C4B_Configurableprices_Model_Checkout_Observer</class> <method>applyConfigurablePrices</method> </c4b_configurableprices_cart_observer> </observers> </checkout_cart_save_before> </events> </global> </config>
Observer related to saving the products in the backend
When a product is saved in the backend, the method “updateProductCustomOptions” of the class C4B_Configurableprices_Model_Catalog_Product_Option is executed. This ensures that the additional individual options are created. When the additional individual options have already been created, they will not be overwritten – the already entered prices of these additional individual options should not be removed. This is the simplified method:
public function updateProductCustomOptions($observer) { /* @var $product Mage_Catalog_Model_Product */ $product = $observer['product']; $newOptionList = $this->_getNewOptionsList($product); foreach($product->getOptions() as $option) { foreach($option->getValues() as $value) { $key = array_search(strtolower(trim($value->getSku())), $newOptionList); if($key === false) { $this->_deleteOptionValue($product, $option, $value->getSku()); } else { unset($newOptionList[$key]); } } } foreach($newOptionList as $newOptionValue) { $this->addNewOptionValue($product, 0, $newOptionValue); } }
First, the _getNewOptionsList method determines all values of the generated individual options that a product should have, for example preis-lasergravur-100, and saves them in the array newOptionList. After that, the method goes through all the options and their values for the current product. No need for more options to be deleted, when they are deleted from the existing newOptionList. The remaining options are created in connection with the addNewOptionValue method.
Observer related to the changes in the basket of goods
The method applyConfigurablePrices of the class C4B_Configurableprices_Model_Checkout_Observer is called before the cart is saved. For every original custom option the method selects the generated custom option that belongs to the right tier. This is the simplified method:
public function applyConfigurablePrices($observer) { $items = Mage::getSingleton('checkout/session')->getQuote()->getAllItems(); foreach($items as $item) { $itemQty = $this->_getQuantityBoundary($item); $options_ids = $this->_getNotGeneratedCustomOptions($item); foreach ($options_ids as $optionId) { $valueId = $item->getOptionByCode('option_' . $optionId)->getValue(); $productOption = $item->getProduct()->getOptionById($optionId); $optionTitle = $productOption->getTitle(); $valueTitle = $productOption->getValueById($valueId)->getTitle(); $option = $this->_getOptionByTitle($item->getProduct(), self::PREFIX . $optionTitle); $valueSku = self::PREFIX . $optionTitle . "-" . $valueTitle . "-" . $itemQty; $this->_addOrUpdateOptionValue($item, 'option_' . $option->getId(), $this->_getOptionValueIdBySku($option,$valueSku)); $options_ids .= strlen($options_ids) == 0 ? $option->getId() : "," . $option->getId(); } $this->_addOrUpdateOptionValue($item, 'option_ids', $options_ids); } }
In this method, all positions of the basket are being processed. The method _getQuantityBoundary returns the quantity limit, e.g. 100, when 120 items are in the cart. The method _getNotGeneratedCustomOptions returns the original custom options selected by the customer. „laser engraving“ is an example for an original custom option, while „award-laser-engraved-100“, on the other hand, would not be in the list. The method gets the original option for every line in the cart and constructs the name of the generated option (e.g. „award-laser-engraved-100“). This generated custom option is selected and leads to the surcharge.
Conclusion
Tier prices for custom options are surprisingly complicated to create in Magento. On top of that, there are options that look fine in the first place, but do not work at the end of the day. The above presented approach was implemented for a customer and has been put into practice, working fine. It combines relatively little changes to the Magento system with a good visual appearance. If you want our module as a sample for your own development, please request a copy at https://www.code4business.de/kontakt-impressum/ free of charge. Be advised, however, that implementing the module for your project will require in-depth Magento and programming knowledge. I am looking forward for discussion, suggestions and other modules that you propose.
File for Download
Get the presentation of Dr. Nikolai Krambrock at Developers Paradise on 13.1.2014 in Kaprun here
Hello!
I would love to have the code for this if possible. Please email with it when you have the chance!
Thanks!
Thanks for the interest! I just send it to you via e-mail.
Hello Nikolai,
I’d be happy to test, just to make sure it suits to our needs.
Please tell me if it’s possible, kind regards,
Christophe
I don’t have your e-mail-address. As soon as you send it to me through the contact form I’ll send you the files.
Hi
I really need this code
Can you send to my email?
Thank you
I added the code to my website
Depending on not working
Give me a complete code?
Thank you
Hello, I would love to have the code. Please email me if it’s possible.
Thanks
Hello, great job, is a great help in developing a magento store, would appreciate a copy of the code, I’ve sent an email to it.
Thank you very much for sharing such valuable information.
regards
i need code can u send me. second i want that custom option by default increase in the price can we just over ride with tire price of custom option with your code. please send me your code via email thannks
do any knows how to configure this? its giving me a hard time,
Hello!
I would love to have the code for this if possible. Please email with it when you have the chance!
Thanks!
Thanks for the interest! I have just sent it to you via e-mail.
Hi Nikolai, very interesting article, it’s exactly what I’m trying to build. There wouldn’t be by any chance a video recording of your talk? 🙂
I would also love to receive the code.
Thanks a lot!
We’ll send you the source code. Unfortunately there is no video recording of the presenation.
Hi Nikolai,
Nice approach for custom option tier pricing.
I would like to receive the source code also :).
Thanks in advance!
Hi,
I am also trying to create this functionality.
Please can you share this code with me in my email.
Many thanks.
A Kumar
Hi,
I’m trying to add this as well.
Would it be possible to get a copy of the code as well?
Yoni R
Hello!
I would love to have the code for this if possible. Please email with it when you have the chance!
Thanks!
Hello, i want to apply this on my website, I would love to receive the code.
Thank You!
Thank your your interest! Unfortunately you didn´t leave your email adress, so I can´t send you the code.