<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
> <channel><title>EcomDev Magento Developers</title> <atom:link href="http://www.ecomdev.org/feed" rel="self" type="application/rss+xml" /><link>http://www.ecomdev.org</link> <description></description> <lastBuildDate>Fri, 10 May 2013 05:30:45 +0000</lastBuildDate> <language>en-US</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.4.2</generator> <item><title>CheckItOut 1.5.0: Now the fastest checkout extension!</title><link>http://www.ecomdev.org/2013/02/15/checkitout-1-5-0-now-the-fastest-checkout-extension.html</link> <comments>http://www.ecomdev.org/2013/02/15/checkitout-1-5-0-now-the-fastest-checkout-extension.html#comments</comments> <pubDate>Fri, 15 Feb 2013 05:00:14 +0000</pubDate> <dc:creator>Ivan Chepurnyi</dc:creator> <category><![CDATA[Extensions]]></category> <category><![CDATA[News]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=7420</guid> <description><![CDATA[<p>We happy to announce the release of new CheckItOut! extension version 1.5.0. It is our new Major release with great improvements in performance and number of AJAX calls. Also now JS files are better organized and it will be easier for you, as a developer, to customize the extension. New Features: Reorganized architecture of AJAX [...]</p><p>The post <a
href="http://www.ecomdev.org/2013/02/15/checkitout-1-5-0-now-the-fastest-checkout-extension.html">CheckItOut 1.5.0: Now the fastest checkout extension!</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p><a
href="http://shop.ecomdev.org/checkitout.html"><img
class="alignright size-full wp-image-6016" title="CheckItOut" src="http://www.ecomdev.org/wp-content/uploads/2012/02/CheckItOut.png" alt="" /></a>We happy to announce the release of new CheckItOut! extension <a
href="http://shop.ecomdev.org/checkitout.html">version 1.5.0</a>. It is our new Major release with great improvements in performance and number of AJAX calls. Also now JS files are better organized and it will be easier for you, as a developer, to customize the extension.</p><h3>New Features:</h3><ul><li>Reorganized architecture of AJAX communication to get rid of all the redundant calls to server.<br
/> Now amount of requests the same as in core version of one page checkout, in some cases even less requests.</li><li>Implemented indicator of submitting of data, that is shown as bg part of &#8220;Place Order&#8221; button.</li></ul><h3>Improvements:</h3><ul><li>Separated contents of checkitout.js file into different files for not loading redundant JS files.<br
/> In case if you modified checkitout.js file, make diff of original supplied for your versionand place your changes into separate file according to the guidelines in the following article: <a
href="http://www.ecomdev.org/2012/11/29/magento-checkout-extension-ideas-architecture-revealed.html">http://www.ecomdev.org/2012/11/29/magento-checkout-extension-ideas-architecture-revealed.html</a></li><li>Added events for checkout onepage proxy</li><li>Added events for preloaded steps json generation in js block</li></ul><h3>Bug Fixes</h3><ul><li>Save billing address with &#8220;use_for_shipping&#8221; flag was leading to override of totals</li></ul><div>Full list of changes is available in extension package. Just check the RELEASE_NOTES.txt</div><div></div><h1>Demo Installment</h1><p>You can try our new CheckItOut! version on our demo:<br
/> <a
href="http://demo.ecomdev.org">demo.ecomdev.org</a></p><p>You can purchase our new CheckitOut extension <a
href="http://shop.ecomdev.org/checkitout.html">here &gt;</a></p><p>The post <a
href="http://www.ecomdev.org/2013/02/15/checkitout-1-5-0-now-the-fastest-checkout-extension.html">CheckItOut 1.5.0: Now the fastest checkout extension!</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2013/02/15/checkitout-1-5-0-now-the-fastest-checkout-extension.html/feed</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Why Magento Community Needs Own Q&amp;A Website</title><link>http://www.ecomdev.org/2012/12/19/why-magento-community-needs-own-qa-website.html</link> <comments>http://www.ecomdev.org/2012/12/19/why-magento-community-needs-own-qa-website.html#comments</comments> <pubDate>Wed, 19 Dec 2012 13:44:45 +0000</pubDate> <dc:creator>Ivan Chepurnyi</dc:creator> <category><![CDATA[News]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=7387</guid> <description><![CDATA[<p>Today a Magento Q&#38;A website went though commitment phase on http://area51.stackexchange.com/ website. It is very important step for Magento community, since this website gives much more better options to find the right answer than StackOverflow or Magento Answers one. Magento Stack Exchange vs Stackoverflow You may ask why you need just one more Q&#38;A for Magento, [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/12/19/why-magento-community-needs-own-qa-website.html">Why Magento Community Needs Own Q&#038;A Website</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>Today a Magento Q&amp;A website went though <a
href="http://area51.stackexchange.com/proposals/48872/magento?referrer=xvdT9S2_2AX27y6ehRWkiw2" target="_blank">commitment phase</a> on <a
title="Area51" href="http://area51.stackexchange.com/" target="_blank">http://area51.stackexchange.com/</a> website. It is very important step for Magento community, since this website gives much more better options to find the right answer than StackOverflow or Magento Answers one.</p><h2>Magento Stack Exchange vs Stackoverflow</h2><p>You may ask why you need just one more Q&amp;A for Magento, if there is a lot of questions on <a
title="Stackoverflow Magento Tag" href="http://stackoverflow.com/questions/tagged/magento" target="_blank">Stackoverflow</a>? The answer is very simple, it will bring all the questions from technical and non technical people to the single place. I saw a lot of questions was closed as not-a-real-question on StackOverflow, mostly because it doesn&#8217;t have existing code snippet or just a question for architectural advisory.</p><p>So having a separate website on SE platform can resolve issue with non-programmer related questions for Magento topic.</p><h2>Magento Answers</h2><p>Official Magento Answers website is not so popular within the community because of few reasons.First of all because it is not user-friendly. It is very hard to post really nice looking questions or answer. Another reason is the moderation process of the questions &amp; answers, it is not efficient like on Stackoverflow. Stackoverflow is much more better in this case, since it fully managed and powered by community. So why not to use a Magento specific stack-overflow version?</p><h2>Why Now?</h2><p>This project was started 2 years ago by <a
href="http://area51.stackexchange.com/users/27874/vince-pettit" target="_blank">Vince Pettit</a>, but it got its commit phase only today because of  social impact of <a
href="https://twitter.com/benmarks" target="_blank">Ben Marks</a> twitter account. Thanks to these guys for making it happen! And today is your time to make this initiative happen, support this project by signing a commit petition! Do it right now, <a
href="http://area51.stackexchange.com/proposals/48872/magento?referrer=xvdT9S2_2AX27y6ehRWkiw2" target="_blank">click here</a>!</p><p>The post <a
href="http://www.ecomdev.org/2012/12/19/why-magento-community-needs-own-qa-website.html">Why Magento Community Needs Own Q&#038;A Website</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/12/19/why-magento-community-needs-own-qa-website.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Magento Checkout: Shopping Cart Flow</title><link>http://www.ecomdev.org/2012/12/12/magento-checkout-shopping-cart-flow.html</link> <comments>http://www.ecomdev.org/2012/12/12/magento-checkout-shopping-cart-flow.html#comments</comments> <pubDate>Wed, 12 Dec 2012 17:49:32 +0000</pubDate> <dc:creator>Ivan Chepurnyi</dc:creator> <category><![CDATA[How To]]></category> <category><![CDATA[Overview]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=6844</guid> <description><![CDATA[<p>Shopping Cart is a starting point for every customer in the checkout flow. That is why the article about it, is the next one in &#8220;Magento Checkout from A to Z&#8221; series. In this article you will learn what happens during viewing shopping cart page, adding product to cart or changing products&#8217; qty. As well you [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/12/12/magento-checkout-shopping-cart-flow.html">Magento Checkout: Shopping Cart Flow</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>Shopping Cart is a starting point for every customer in the checkout flow. That is why the article about it, is the next one in <strong>&#8220;Magento Checkout from A to Z&#8221;</strong> series. In this article you will learn what happens during viewing shopping cart page, adding product to cart or changing products&#8217; qty. As well you will get familiar with some customizations principles of that functionality. So get some pop-corn, take your favorite drink and have fun! <span
id="more-6844"></span></p><h2>Shopping Cart Processes</h2><p>There are some main processes in the shopping cart that is quite good to know. The following flowcharts and their descriptions will help you.</p><h3>Adding Product to Cart</h3><p>Everything that starts in checkout &#8211; starts from adding product to cart. As soon as customer presses &#8220;Add to Cart&#8221; button &#8211; Magento magic begins, and today this magic secrets will be revealed. Take a lot at the following diagram to see the main processes flow. Just below the diagram see each process description. Click on diagram to view it in the full size. <a
href="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Add-to-Cart-Process.png" target="_blank" rel="lightbox[6844]" title="Magento Add to Cart Process"><img
class="size-medium wp-image-7269 alignright" title="Magento Add to Cart Process" src="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Add-to-Cart-Process-300x195.png" alt="" width="300" height="195" /></a></p><h4>Controller Loads Product</h4><p>This step starts at <em>checkout/cart/add</em> controller action, for which <em>Mage_Checkout_CartController</em> class is responsible. Controller loads product by id passed via product url parameter. If the product is not loaded (not exist, not enabled, etc), then it returns customer to the previous page. Previous page is detected by referrer header or parameter.If it is not possible to detect previous page, customer just gets redirected to cart page. The loaded product with url parameters are passed to cart model method <em>addProduct()</em>.</p><h4>Cart Model Prepares Product Request</h4><p>Cart model is represented by <em>Mage_Checkout_Model_Cart<strong>. </strong></em>Inside of <em>addProduct()</em> method first product model gets checked for assignment to the current website. After the check, from url params, gets created a product request object. The request object just a <em>Varien_Object</em> class instance with url params as data. After creation of the object, requested quantity gets validated for matching minimal qty settings of the product. If qty is lower, it gets corrected automatically. When product and request is prepared, the quote model method <em>addProduct()</em>gets involved.</p><h4>Quote Model Processes Product Request</h4><p>Finally Magento gets to a quote model, but just to pass request to product type model. At this step, in <em>addProduct()</em> method of <em>Mage_Sales_Model_Quote</em> class invoked <em>prepareForCartAdvanced()</em>of product type model.</p><h4>Product Type Model Validation and Processing of Request</h4><p>Depends on the product type, there could be different product type models. These type models are responsible for product type specific logic. For instance simple product is just contains logic for custom options, configurable has special child product selection logic, bundle has multiple children, etc. However all product type models are extended from <em>Mage_Catalog_Model_Product_Type_Abstract </em>class. By the way, before 1.5, there was different method name, that were invoked during add to cart process. In 1.4.x it was <em>prepareForCart()</em>, and starting from 1.5.0 the method was changed to <em>prepareForCartAdvanced()</em> and logic were moved to a protected method <em>_prepareProduct()</em> with 3 parameters<em> </em>The reason of this change is very simple, they introduced third argument and for keeping backward compatibility, they were supposed to create another method and keep <em>prepareForCart()</em> as alias with two arguments. So currently all the logic of processing &amp; validation of product request is in <em>_prepareProduct() </em>protected method and it is different per product type.</p><h5>Simple Products <em>(Mage_Catalog_Model_Product_Type_Simple)</em></h5><p>The first step of the request processing for this product type is validation of custom options. They are get validated by <em>_prepareOptions()</em> method of type model. When options are validated and processed, then it throws an event. The event name depends on type of product processing: <em>catalog_product_type_prepare_full_options</em> or <em>catalog_product_type_prepare_lite_options</em>. Afterwards the product is checked for being added to the cart by grouped parent, in this case additional product options are added. Then <em>_processProduct()</em>method just returns array with a single configured instance of product and special properties set to it (qty, custom options, buy request, etc.).</p><h5>Grouped Products <em>(Mage_Catalog_Model_Product_Type_Grouped)</em></h5><p>Grouped type process is absolutely different from simple product type, however it involves simple products process for child products. Everything starts from retrieving all assigned child products and comparing them to passed child ids in request. If no child products found in request, <em>_prepareProduct()</em> returns string with error message. Otherwise it just invokes <em>_prepareProduct() </em>method of child product type model and adds it to array of configured product instances. When all child products are processed and there is no errors returned, it adds own product instance to the array and returns it.</p><h5>Configurable Product <em>(Mage_Catalog_Model_Product_Type_Configurable)</em></h5><p>The initial process is the same as in simple product and afterwards it checks configured options by finding a correct simple product that matches all the selected values and invokes its <em>_prepareProduct() </em>method. Also if configurable product has custom options, this options partially added to simple product for making it unique in the cart. If no simple product that matches selection is found, it returns string with error text, otherwise array with two items: configurable product itself and its matched child simple product.</p><h5>Bundle Product <em>(Mage_Bundle_Model_Product_Type)</em></h5><p>The initial process as well the same as in simple product. Then all the possible options and their selections gets loaded and each options gets validated. If option is required and at least one selection was not specified in the request, then it returns an error string. Then the selections that were selected are checked for their purchase availability (i.e. <em>isSalable()</em> method is invoked). Later on all the selections are iterated to set selection qty from input or predefined value (if input is empty or customer cannot change it). As well <em>prepareForCart() </em>method gets invoked for each selection product to add its own options. In the end, bundle product model returns bundle product and all its selection products in the array of result.</p><h5>Other Product Types</h5><p>There are also some other product types like <em>Virtual</em> and <em>Downloadable</em>, but their process is the same as in Simple Type Model, just with some additional processes of own options.</p><h4>Quote Model Adds a New Item or Changes Existing One Qty</h4><p>First of all, before creating a new quote item, quote model checks for existence of the product with the same combination of options and product id. For this purpose method <em>getItemByProduct() </em>is used. This method walks though all quote items and calls <em>representProduct()</em> method of quote item model. If method returns true, quote model just updates existing item qty by calling <em>addQty() </em>method. Otherwise creates a new quote item and does the same for it. After qty was changed, quote item dispatches <em>sales_quote_item_qty_set_after </em>event, that is observer by stock module. More about this flow described in <strong>Update Items in Cart</strong> process. When item qty was set, quote model checks for possible errors in added/modified item. If error were found it throws an exception, otherwise it throws <em>sales_quote_product_add_after</em>event.</p><h5>Grouping of Quote Items in Cart</h5><p>I just mentioned <em>representProduct() </em>method, that is very interesting one and it is quite good to know, how it works<em>. B</em>ecause sometimes Magento developer needs to have some custom grouping of the items in cart. Most of developers just rewrite quote item model and override this method. However, there is a small trick you can use. Observe <em>catalog_product_type_prepare_full_options </em>for adding new custom option to your product. And observer code may look like the following:</p><pre class="brush: php; title: ; notranslate">
public function makeMyProductUnique($observer)
{
    if ($observer-&gt;getEvent()-&gt;getBuyRequest()-&gt;getSomeFlagFromRequest()) {
        $product = $observer-&gt;getEvent()-&gt;getProduct();
        $product-&gt;addCustomOption('my_custom_unique_id', 'some_value');
    }
}
</pre><h4>Cart Model Dispatches Add To Cart Event or Throws Exception</h4><p>If everything was fine during adding product to cart, cart model dispatches an event called <em>checkout_cart_product_add_after</em> and sets property into checkout session object with the latest added product id. This property name is <em>last_added_product_id. </em> If there were some error during product add to cart process, cart model throws an exception with error message. If error was returned as string from quote <em>addProduct()</em>method, then it is treated as notice. If it was a caught exception, than it will be treaded as error message. Then later on, in controller layer, the exception thrown by cart model is caught and customer redirected to product page with error or notice shown on top of the page.</p><h4> Controller Saves Cart Model</h4><p>As soon as product is successfully added to cart, controller adds related products via cart model method <em>addProductByIds()</em>. The process of adding related products are almost the same, as all actions described above, except that only simple products without custom options can be added as related by this method. Then <em>save()</em> method of cart model gets invoked.</p><h4>Cart Saves Quote and Collects Totals</h4><p>Inside of  cart model save() method, goes total calculation process, that is invoked by  <em>collectTotals()</em> method of quote model. More about totals calculation, you can read in the next sections of this article. After totals are collected,<em> save()</em>method of quote model gets invoked. During this operation quote models saves all child entities like address, item, payment info, etc.</p><h4>Controller Redirects Customer to Shopping Cart or Product Page</h4><p>When item was successfully added to the shopping bag, there is also thrown an event on controller level, it is called <em>checkout_cart_add_product_complete. </em>You can use this event for custom redirect or building own ajax response for your super-duper ajax based add to cart functionality. It is just a small advice for all that extension makers, who would rather override method, instead of observing an event. But if you haven&#8217;t observed previous event and haven&#8217;t set the property called <em>no_card_redirect</em> to checkout session object, Magento uses own logic for detecting redirect url and adds a success message. Depends on configuration settings, there are two options for redirecting customer back. If config option <em>checkout/cart/redirect_to_cart </em>is set to true, then customer always will be redirected to the cart. Otherwise to the page from which product was added to cart (that is usually a product page).</p><h3>Configure Added Item</h3><p>As you might know, starting from CE 1.5.x it is possible to update configurable, bundle and simple products with custom option from the cart instead of removing old one and inserting new one. Actually Magento does almost the same for you, it removes old quote item if there is a change in options and adds a new one. You can see the difference on the following flowchart. Just click on it to view the flowchart in full size. <a
href="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Configure-Item-Process.png" target="_blank" rel="lightbox[6844]" title="Magento Configure Item Process"><img
class="size-medium wp-image-7288 alignright" title="Magento Configure Item Process" src="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Configure-Item-Process-300x212.png" alt="" width="300" height="212" /></a>The following flowchart do not represent the process of rendering of configure page, since it is very simple &#8211; the same as regular product page, just with set up of selected options. Also this section won&#8217;t be so massive like previous one, it describes only new steps and difference in similar actions.</p><h4>Controller Finds Quote Item</h4><p>Everything starts, when data gets submitted to  <em>checkout/cart/updateItemOptions</em> action. The first thing that controller does, it checks existence of quote item with supplied id in the current quote object. If item doesn&#8217;t exists, it adds an error message and redirects customer to shopping cart. If quote item was found, the process flow is delegated to <em>updateItem() </em>method of cart model.</p><h4>Cart Model Prepares Product Request</h4><div>This process is the same as during adding product to cart, except that method name of quote is called <em>updateItem(). </em></div><div><h4>Quote Model Processes Product Request</h4><div> For processing of product request in <em>updateItem()</em> method of quote model, called another method <em>addProduct()</em>. Calling of this method invokes the same process of validation of request and preparing new quote item as during add to cart process.</div></div><div><h4>Product Type Model Validation and Processing of Request</h4><div>The same as during add to cart process.</div><div><h4>Quote Model Adds a New Item or Changes Existing One Qty</h4><div>The same as during add to cart process.</div></div><h4>Quote Model Checks For a New Quote Item Created and Removes Old Quote Item</h4></div><div>When <em>addProduct()</em> method returns configured quote item, inside of the <em>updateItem()</em> method, performed a check for item id change. E.g. if any option was changed, addProduct() method will return a new item, otherwise it just updates qty.</div><div>If quote item id is not the same as configured item, old one gets removed by calling of <em>removeItem()</em> method of quote model.</div><div><h4>Cart Model Dispatches Update Item Options Event or Throws Exception</h4><p>If there were no errors and item was updated, there is dispatched an event with such a name: <em>checkout_cart_product_update_after</em>. Also cart model sets the same property with latest added product in session, even if it just was updated. The processing of the errors is totally the same as in add to cart flow.</p><div><h4>Controller Saves Cart Model, Cart Saves Quote and Collects Totals</h4><p>Absolutely the same as in add to cart process.</p><h4>Controller Redirects Customer to Shopping Cart</h4><p>This step is very similar as in add to cart, but the name of magic event, that you can use of updating response is different. The event name is <em>checkout_cart_update_item_complete. </em>So it is another nice event for extension developers, who&#8217;d like to implement ajax based item update.</p></div></div><h3>Update Items In The Cart</h3><p>From the name of the process it looks like, that it is also related to updating of item options. But it just changes quantity of the item in the cart. Check the following flow chart and of course descriptions of actions below it. <a
href="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Update-Cart-Items-Process.png" target="_blank" rel="lightbox[6844]" title="Magento Update Cart Items Process"><img
class="size-medium wp-image-7289 alignright" title="Magento Update Cart Items Process" src="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Update-Cart-Items-Process-300x163.png" alt="" width="300" height="163" /></a></p><h4>Controller Normalizes Localized Qty Values</h4><p>Everything starts at <em>checkout/cart/updatePost</em> controller action. There are two action flows, but we are not looking at <em>empty_cart</em> one, since it is very simple. It just removes all items from cart and not so interesting like <em>update_qty. </em> For update_qty action, there is invoked a protected method <em>_updateShoppingCart(), </em>that contains all the logic of updating quote items. First of all it retrieves an associative array of updated items and normalizes qty values according to current locale settings, because Magento supports decimal qty values and not all the countries have dot as decimal mark. So it is required to transform customer input to a correct php decimal representation in string. When qty  values are normalized, controller invokes special suggest qty functionality. It is realized by <em>suggestItemsQty()</em>method in the cart model.</p><h4>Cart Model Updates Qty Array With Suggested Values For Each Quote Item</h4><p>Inside of <em>suggestItemsQty()</em> method cart model walks through all items in the array. If item if the specified id exists and product is set to a quote item and product has quote item assigned, then it method passes qty to a stock item model method <em>suggestQty(). </em>Result returned from the method call gets set to item in array, so it will be used for updating real qty.</p><h4>Stock Item Checks Qty Increments Value</h4><p>When cart model calls suggestQty() method, stock item model performs a check of qty increments options. If qty increments option is specified for a stock item, it checks correctness of value specified for a stock item. It also checks if the value is between min and max values, but it doesn&#8217;t autocorrect it, it just leaves qty as is, to validate it later on by another process. Here are some test cases, to make it easier for you to get this functionality implementation right: If product has qty increments value set to 3, and min sale qty is 3 and max sale qty is 12 then:</p><ul><li>If specified qty equals to 2, then it won&#8217;t be autocorrected</li><li>If specified qty equals to 3, then it won&#8217;t be autocorrected</li><li>If specified qty equals to 4, then it will be autocorrected to 3</li><li>If specified qty equals to 5, then it will be autocorrected to 6</li><li>If specified qty equals to 6, then it won&#8217;t be autocorrected.</li><li>If specified qty equals to 13, then it won&#8217;t be autocorrected</li></ul><h4>Controller Passes Qty Array to Cart Model</h4><p>When suggested qty functionality process was finished, controller takes modified array and invokes updateItems() method of the cart model.</p><h4>Cart Model Modify Qty Process</h4><p>When cart model get array of quote items quantities to update as argument to updateItems(), first of all it dispatches <em>checkout_cart_update_items_before </em>event. It is pity, but you cannot modify array of qty&#8217;s by observing this event, you can only retrieve it. After dispatching of the event, cart model walks through all array rows. If row qty equals or less than 0, quote item associated to the array row gets removed from cart, otherwise it just sets quote item qty. If any item has difference between qty specified by customer and qty that was actually applied (qty increments modifications), then cart model adds notice message to session object, so customer will get notified about autocorrected values. When all items were modified or deleted, there is dispatched another event, that is called <em>checkout_cart_update_items_after</em>.</p><h4>Quote Item Dispatches Qty Change Event</h4><p>After setting of qty by cart model, quote item model dispatches sales_quote_item_qty_set_after event. This event can be observed by you to perform additional check of inventory. BTW, this event is observed by Mage_CatalogInventoy module and on this event Magento performs check of item stock availability.</p><h4>Stock  Qty Change Logic</h4><p>Observer <em>Mage_CatalogInventory_Model_Observer</em> class has specific logic qty change validation of quote item. This logic is realized in <em>checkQuoteItemQty()</em>method. I will not go too much in deep into check activities, just will explain it in general. If quote item qty lower than minimal qty for product or greater than maximum one, it will return an error. If specified qty is not available for item, it also will rise an error.</p><h4>Controller Saves Cart Model, Cart Saves Quote and Collects Totals</h4><p>Absolutely the same as in add to cart process.</p><h4>Controller Redirects Customer to Shopping Cart</h4><p>There is no event for updated items qty, so you cannot modify the request via specific cart controller event, but it is still possible to make a trick by adding observer to controller post dispatch event, that is called <em>controller_action_postdispatch_checkout_cart_updatePost</em>. This event can be used for changing redirect to ajax response, but, of course, it adds a lot of work for you to detect possible errors and updated items from session and quote objects.</p><h3>Remove Item From The Cart</h3><p>Quite simple process, but also have some interesting features that you should know. Just take a look at the flowchart.</p><p><a
href="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Remove-Item-Process.png" target="_blank" rel="lightbox[6844]" title="Magento Remove Item Process"><img
class="size-medium wp-image-7296 alignright" title="Magento Remove Item Process" src="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Remove-Item-Process-300x159.png" alt="" width="300" height="159" /></a></p><p>Even if remove process sounds quite simple, however, there are some special features that might be new for you. Especially it is related to logic with parent-child relations. So lets take a look at every process more in detail.</p><h4>Controller Passes Quote Item Id to Cart Model</h4><p>It starts at <em>checkout/cart/delete</em> action. Controller just retrieves id url parameter and invokes cart model method <em>removeItem()</em>.</p><h4>Cart Model Removes Item from Quote</h4><p>This step is really simple and straightforward. Cart model just calls <em>removeItem()</em> method of quote model.</p><h4>Quote Item Removal Logic</h4><p>When <em>removeItem()</em> method gets invoked, there is a check for item existence. However, if it doesn&#8217;t exists, it won&#8217;t rise an error, it just skips item removal logic.</p><p>If item exists, it marks it as deleted by invoking<em> isDeleted()</em> method with true value as an argument, so when <em>save()</em> method is invoked during quote save process, item record will be removed from the database. After quote item is marked for delete, there is a check for child quote items assigned to it. If so, it iterates over it and marks child items as deleted as well. Also if that is removed is a child item of some parent one, it will mark parent item as well. So if it has child items or is a child item itself, Magento will remove child/parent item as well.</p><p>After item was marked as removed, it dispatches an event that is called <em>sales_quote_remove_item</em>. You can observe it, if you have some special items, that cannot be removed from the cart. Just mark quote item in observer as un-deleted by calling <em>isDeleted()</em> method with first argument value that equals to false.</p><h4>Controller Saves Cart Model, Cart Saves Quote and Collects Totals</h4><p>Absolutely the same as in add to cart process.</p><h4>Controller Redirects Customer to Shopping Cart</h4><p>There is also no special event, like in update quote items qty process. Customer just gets redirected back to shopping cart.</p><h3>View Shopping Cart Page</h3><p>So, have you ever thought what is happing when you are viewing Shopping Cart Page? If no, then it will be a surprise for you, how many checks and processes are performed, when you land to <em>checkout/cart/index</em> page. Curious? Check the following flowchart. <a
href="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Shopping-Cart-Page-View-Process.png" target="_blank" rel="lightbox[6844]" title="Magento Shopping Cart Page View Process"><img
class="alignright size-medium wp-image-7354" title="Magento Shopping Cart Page View Process" src="http://www.ecomdev.org/wp-content/uploads/2012/12/Magento-Shopping-Cart-Page-View-Process-300x177.png" alt="" width="300" height="177" /></a></p><h4>Controller Checks Number of Quote Items</h4><p>When you are viewing the shopping cart page, controller checks number of items in your shopping cart. If you have at least one item, it starts initialization of shopping cart model, otherwise just renders shopping cart page (empty cart template). Shopping cart model is initialized by its <em>init()</em> method invokation.</p><h4>Cart Model Resets Checkout Data</h4><p>When cart model gets initialized, first of all it resets checkout method for Onepage checkout flow. It is done by setting up property <em>checkout_method</em> to empty value for a quote model. Also if there were any steps performed for multiple shipping checkout, e.g. <em>checkout_state</em> property of checkout session object is not equal to<em> Mage_Checkout_Model_Session::CHECKOUT_STATE_BEGIN</em> constant value. In this case all the addresses added to a quote will be removed, also cart model removes payment info instance, since it may affect another checkout type.</p><p>As well, if apparently during initialization process all the items were removed from the quote, cart model will remove all the shipping rates.</p><h4>Controller Saves Cart Model, Cart Saves Quote and Collects Totals</h4><p>Absolutely the same as in add to cart process.</p><h4>Quote Model Validates Minimum Amount</h4><p>When all the totals are recalculated, controller calls quote model method, that is called <em>validateMinimumAmount(). </em>In this method quote model walks though all addresses and invokes method with the same name on them. If any of those methods return false, quote method will return false as well.</p><p>On address model level <em>validateMinimumAmount()</em> method compares configuration value from <em>sales/minimum_order/amount </em>path with amount from address <em>base_subtotal_with_discount</em> property. This property contains subtotal with all discounts.</p><p>If minimum amount is not valid, controller adds notice message to checkout session with minimum required amount for purchase.</p><h4>Controller Adds Quote Messages to Checkout Session</h4><p>When all the initialization and validation are performed, there might by some messages stored in quote model. So controller just retrieves that messages and adds it to checkout session object.</p><h4>Controller Sets Cart Updated Flag</h4><p>You might be curious, why controller sets updated flag, if nothing was updated? There reason is quite simple, as soon as customer came back to shopping cart page from any checkout page and if in another browser tab he has a checkout page, the data on that checkout page gets invalidated, so customer needs to start over the checkout process. So for this purpose this property changed, since with every ajax or regular request every checkout flow checks it and if it equals true, redirects customer to cart.</p><h4>Controllers Renders Shopping Cart Page</h4><p>There is no hidden actions at this step, it is quite straight forward. Controller just loads layout and renders it.</p><h2>What&#8217;s Next?</h2><p>So when you know how main processes work in shopping cart, it is time to dig more into advanced part like totals and addresses. So don&#8217;t forget to check our blog in few weeks! Next time you will get aquatinted with Quote Address, Totals and Price Calculation! Also I am going to reveal some secrets of tax applying process.</p><p>The post <a
href="http://www.ecomdev.org/2012/12/12/magento-checkout-shopping-cart-flow.html">Magento Checkout: Shopping Cart Flow</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/12/12/magento-checkout-shopping-cart-flow.html/feed</wfw:commentRss> <slash:comments>11</slash:comments> </item> <item><title>Our Magento Checkout Extension Ideas &amp; Architecture Revealed</title><link>http://www.ecomdev.org/2012/11/29/magento-checkout-extension-ideas-architecture-revealed.html</link> <comments>http://www.ecomdev.org/2012/11/29/magento-checkout-extension-ideas-architecture-revealed.html#comments</comments> <pubDate>Thu, 29 Nov 2012 09:38:26 +0000</pubDate> <dc:creator>Ivan Chepurnyi</dc:creator> <category><![CDATA[Extensions]]></category> <category><![CDATA[Overview]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=7140</guid> <description><![CDATA[<p>In 2010 when I started development of our Magento checkout module, the main idea was to bring an extension that will be developed for a developer. The origins of the extension, were in my first Magento freelance work on custom project module, in few months after I left Magento company. But actually, today&#8217;s article isn&#8217;t [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/11/29/magento-checkout-extension-ideas-architecture-revealed.html">Our Magento Checkout Extension Ideas &#038; Architecture Revealed</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>In 2010 when I started development of our Magento checkout module, the main idea was to bring an extension that will be developed for a developer. The origins of the extension, were in my first Magento freelance work on custom project module, in few months after I left Magento company. But actually, today&#8217;s article isn&#8217;t about extension history, it is more about some cool features developers would like to know. I am going to reveal some architecture of the extensions and what you can do with it, that you cannot do with the standart checkout.</p><h2>How Magento Checkout Extension Was Built</h2><p>I saw enormous amount checkout extensions on the market, while I was working on different project and my main concern about them is, that they all are realizing absolutely own logic for checkout. 90% of them even don&#8217;t follow MVC design and have mess in the code. Most of them do not use existent Magento models and just copy-paste the logic of data processing in Magento core.</p><p>So one of the main ideas in this extension architecture was to keep logic close to Magento core as it is possible, and luckily the result was achieved. The initial send of extension for code review to other developers made us proud of the work done.</p><h2>How It Works</h2><p>The extension functionality is realized by controller, proxy of checkout model and wrapper blocks for checkout steps in own built layout structure that is easy to modify. Extension can be enabled or disabled for each store view, you can choose different layouts and color schemes. It is very easy to add own steps or hide existent ones. The extension architecture improved flexibility of checkout process customizations itself, some of developers developers even call it Magento checkout framework. So how it become possible?</p><h3>JavaScript Classes</h3><p>First of all idea of using the same JavaScript class names and make them compatible with core OnePage Magento Checkout. All the classes use PrototypeJS OOP implementation, that provides awesome way for overriding existing functionality and building inheritance between classes. It helped me to unify logic between all checkout steps and make them more independent form each other, than in OnePage.</p><p>The base class for all steps is represented by EcomDev.CheckItOut.Step prototype, that is later on used for Payment, ShippingMethod classes. As well Billing and Shipping address steps having also abstract based on this one, it is called EcomDev.CheckItOut.Step.Address.</p><p>So EcomDev.CheckItOut.Step has methods and properties that can be useful for your custom steps or customizations as well:</p><ul><li><strong>Methods</strong><ul><li><strong>initialize(container, saveUrl) </strong>- a constructor, should receive a container html element and url for saving of the data. If you want to add additional parements for your custom step, you just can use inheritance implementation in PrototypeJS:<pre class="brush: jscript; title: ; notranslate">
var YourCustomStep = Class.create(EcomDev.CheckItOut.Step, {
    initialize: function ($super, container) {
       $super(container, 'http://my-save-url.com');
    }
});
</pre><p>As you see in the example above, the saveUrl argument is removed and new $super argument is introduced. $super in this case is automatic argument for prototype to identify the argument in which to pass a super class method, e.g. parent method.</p><p>Constructor contains logic for binding event listeners to form elements and registering step in checkout object.</li><li><strong>isValid()</strong> &#8211; this method invoked each time before auto-submitting data to save url. If it returns false, of course data is not going to be submitted.</li><li><strong>submit() </strong>- it performs validation and send ajax request for saving of the data.</li><li><strong>submitComplete(response) </strong>- receives response on ajax call from submit() method and processes it.</li><li><strong>isLoading(flag),  <strong>isLoading()</strong></strong>- sets or returns is loading flag for step. It is used to notify checkout object about ajax activity at step.</li><li><strong>addCallback(closure)</strong> - adds callback to submit and submitComplete actions. Every callback receives a step as an argument, so you can check is submit completed or not by calling <strong>isLoaded()</strong> method.</li><li><strong>showMask(), hideMask()</strong> &#8211; methods used for showing/hiding loading mask over the method container. The mask div with class name .step-loading should be specified in your step template.</li><li><strong>addRelation(stepCodeOrStepCodes), isRelated(stepObject) </strong>- these methods are used to realize relation between particular checkout steps. For instance payment method is related to shipping method and billing address step changes. So by specifying addRelation() on it, extension will automatically update the payment methods. However, this functionality for payment method is used in conjunction with step hashes, that will be described a bit later in the article.</li><li><strong>getValues()</strong> &#8211; returns all step form element values with element name as object key.</li></ul></li><li><strong>Properties</strong><ul><li><strong>code</strong> &#8211; property specifies the step code, that is unique for within checkout. E.g. shipping_method or review.</li><li><strong>changeInterval</strong> &#8211; interval since keyup or change events for form fields, after which data get&#8217;s validated and submitted. Also data can be only validated or only submitted depends on other properties configuration. Default value is <strong>1200</strong> ms.</li><li><strong>autoSubmit </strong>- used for indicating that checkout step can be automatically submitted. E.g. if equals to false, you will need to call <strong>submit()</strong> method from your code to invoke step data saving. Default value is <strong>true</strong>.</li><li><strong>autoSubmitInvalid </strong>- indicates allowance of submission of not valid data in the form. In CheckItOut is used for address forms to keep data in quote and update shipping rates as soon as possible. Default value is <strong>false. </strong></li><li><strong>ignoreValidationResult </strong>- this property is used to indicate that step isValid method shouldn&#8217;t affect overall checkout process. For instance if coupon code is not entered correctly and has error, it shouldn&#8217;t block customer from proceeding to purchase. Default value is <strong>false.</strong></li><li><strong>loadedHash</strong> &#8211; this property contains hash of the currently loaded step content. Checkout object checks it when related step is saved. If loadedHash property value is NOT the same as in AJAX response, then step is reloaded. If step doesn&#8217;t support this property (i.e. AJAX response doesn&#8217;t have hash info), step will be reloaded with each related step change.</li><li><strong>checkout </strong>-<strong> </strong>this property contains an instance of EcomDev.CheckItOut class to access its methods from step.</li></ul></li></ul><div>So based on the following info you can build own step classes. But there are also another class, that manages all the general checkout logic and controls relations between steps. This class is called EcomDev.CheckItOut. It also has some set of useful methods:</div><ul><li><strong>getStep(stepCode)</strong> &#8211; returns step object by step code.</li><li><strong>isLoading()</strong> &#8211; returns true if at least one step isLoading() method returns true.</li><li><strong>notifyLoading()</strong> &#8211; checks all step objects isLoaded() method and  marks submit buttons as disabled if there any loading process.</li><li><strong>getSubmitButtons()</strong> &#8211; returns array of all buttons on the page that have .btn-checkout class name.</li><li><strong>reloadSteps(stepsArray)</strong> &#8211; reload steps by steps, that are changed. E.g. walks though all the step objects and checks that it is related to passed one in array, then reloads.</li><li><strong>isValid()</strong>  - returns true only if all step objects isValid() method returns true, otherwise false.</li><li><strong>getParameters()</strong> &#8211; returns all form element values for all step objects. Ready to be used in Ajax.Request.</li><li><strong>submit()</strong> &#8211; validates all steps, places order via AJAX request to save order action of one page controller.</li><li><strong>forcedSubmit() </strong>- submits data without checking steps validity,</li><li><strong>submitComplete(response)</strong> &#8211; processes response of save order action.</li><li><strong>showMask(), hideMask()</strong> &#8211; hides shows order place mask (e.g. text &#8220;Submitting your order information&#8221;)</li><li><strong>showOverlay(frontElement), hideOverlay()</strong> &#8211; very helpful for showing your custom popups. Creates transparent overlay under your popup and centers your popup in viewport. Variable frontElement should be an HTMLElement, that has absolute position and defined z-index. Z-Index is mandatory to locate the best position for overlay. Z-Index and absolute position can be defined even in CSS file, since Scritaculous getStyle() modification supports retrieving final applied styles.</li></ul><p>Also don&#8217;t forget, that by using of PrototypeJS you can override classes definition all the time. For instance you want to customize ShippingMethod step class behavior, then this construction will help you:</p><pre class="brush: jscript; title: ; notranslate">
ShippingMethod = Class.create(ShippingMethod, {
       isValid: function ($super) {
              if (someSpecialCondition) { // Some custom logic
                   return false;
              }
              return $super(); // Calling parent isValid method
       }
});
</pre><p>The example above customizes ShippingMethod validation for some special custom condition. The process, that happens there is actually a small trick, that you can do even with customizations of standard OnePage checkout.</p><p>So this PrototypeJS feature gives an awesome way of JS customization without modifying original file. I always recommend to developers including own JS file after checkitout.js and do performing own customizations via <strong>Class.create()</strong>. So when you receive a new version of CheckItOut! you don&#8217;t need to diff files and re-apply your the customizations, you just update main codebase and your customizations just automatically applied.</p><p>Here a list of current checkout step classes that you can customize:</p><ul><li><strong>LoginStep</strong> &#8211; PopUp with login form</li><li><strong>Billing</strong> &#8211; Billing Address Information</li><li><strong>Shipping</strong> &#8211; Shipping Address Information</li><li><strong>ShippingMethod</strong> &#8211; Shipping Method with possible Gift Options selection</li><li><strong>Payment</strong> &#8211; Selection of payment method and entering of payment details if required</li><li><strong>Review</strong> &#8211; Order items, checkout agreements, special actions on order item level</li><li><strong>ConfirmPopUp</strong> - special step for compatibility with some EU regulations</li><li><strong>CouponCode</strong> &#8211; step, that allows entering coupon code right on the checkout page</li></ul><div>Of course there are more classes available, but this is the most used ones.</div><h3>Layout Structure</h3><p>Since CheckItOut! 1.3.0 version, there was introduced a new layout scheme, that allows an easy way to modify step placement or add own ones without rewriting checkout models. As well this layout implementation allows to apply absolutely different CSS color schemes and provides very easy way of its style customization. Now it is the same as with JS files, you don&#8217;t need to modify CSS, you just can include own one and apply your custom styles.</p><p>But before we will go in deep to CSS color schemes, first I will describe layout structure and how it is built.</p><h4>Step Blocks</h4><p>The extension is not rewriting any block, it is even sets only one custom template for review step, all the others are retrieved from core OnePage checkout. This was achieved by detaching original blocks from layout rendering tree and creating own structure of blocks that just retrieves original blocks html.</p><p>All step blocks implement <strong>EcomDev_CheckItOut_Block_Layout_Step_Interface</strong> interface that is used to provide information to its container about the block and how to render it. It has such methods:</p><ul><li><strong>getStepName()</strong> &#8211; returns name of the checkout, that is visible to a customer</li><li><strong>getStepNumber()</strong> &#8211; returns a step number in sequence of all steps presented in layout tree</li><li><strong>getStepContent()</strong> &#8211; returns rendered associated onepage step content</li><li><strong>addClassName($className)</strong> &#8211; adds a CSS class to a block html container</li><li><strong>removeClassName($<strong>className</strong>)</strong> &#8211; removes a CSS class</li><li><strong>getClassName()</strong> &#8211; returns a list of css classes assigned to a block rendered as a string and separated by space</li><li><strong>isVisible()</strong> &#8211; this method returns information about visibility of the step, can be used to hide some steps in checkout, if they are not required. For instance in <strong>EcomDev_CheckItOut_Block_Layout_Step_Login</strong>, <strong>EcomDev_CheckItOut_Block_Layout_Step_Payment </strong>and <strong>EcomDev_CheckItOut_Block_Layout_Step_Shipping_Method</strong> using it to hide itself if customer is logged in, there is no reason to show payment method and shipping method selection accordingly.</li></ul><p>That&#8217;s quite simple interface and you need to implement it if you have a block that can&#8217;t be extended from <strong>EcomDev_CheckItOut_Block_Layout_Step_Abstract</strong> one. This abstract already have all of the them implemented and even more, it can retrieve data from onepage checkout by step code. For instance you can use <strong>EcomDev_CheckItOut_Block_Layout_Step_Address</strong> block retrieves data from onepage checkout blocks.</p><p>Take a look at the following layout XML:</p><pre class="brush: xml; title: ; notranslate">
&lt;block name=&quot;checkout.layout.billing&quot;
       type=&quot;ecomdev_checkitout/layout_step_address&quot;
       template=&quot;ecomdev/checkitout/layout/step/default.phtml&quot;&gt;
    &lt;action method=&quot;setStepCode&quot;&gt;&lt;code&gt;billing&lt;/code&gt;&lt;/action&gt;
    &lt;action method=&quot;setStepNumber&quot;&gt;&lt;number&gt;0&lt;/number&gt;&lt;/action&gt;
    &lt;action method=&quot;initAddress&quot; /&gt;
&lt;/block&gt;
</pre><p>It creates a billing address step in default layout scheme. Method <strong>setStepCode</strong> is called to specify with step content retrieve from onepage checkout. Method <strong>setStepNumber</strong> removes numbering from this step, e.g. it won&#8217;t be counted and the step number won&#8217;t be shown. Method <strong>initAddress</strong> does some secret logic that you can check yourself if you bought an extension :).</p><p>Now let&#8217;s take a look at <strong>ecomdev/checkitout/layout/step/default.phtml</strong>, so you can see how it works:</p><pre class="brush: php; title: ; notranslate">
&lt;?php if ($this-&gt;isVisible()): ?&gt;
&lt;div class=&quot;&lt;?php echo $this-&gt;escapeHtml($this-&gt;getClassName());?&gt; &lt;?php if ($this-&gt;getPositionCode()): ?&gt;&lt;?php echo $this-&gt;escapeHtml($this-&gt;getPositionCode());?&gt;&lt;?php endif;?&gt;&quot; id=&quot;checkout-step-&lt;?php echo $this-&gt;getStepCode();?&gt;&quot;&gt;
    &lt;?php if ($this-&gt;getStepName()): ?&gt;
    &lt;div class=&quot;step-header&quot; id=&quot;checkout-step-&lt;?php echo $this-&gt;getStepCode();?&gt;-header&quot;&gt;
        &lt;?php if($this-&gt;getStepNumber() != 0): ?&gt;&lt;span class=&quot;number&quot;&gt;&lt;?php echo $this-&gt;escapeHtml($this-&gt;getStepNumber()); ?&gt;&lt;/span&gt;&lt;?php endif;?&gt;
        &lt;?php echo $this-&gt;escapeHtml($this-&gt;getStepName()); ?&gt;
    &lt;/div&gt;
    &lt;?php endif; ?&gt;
    &lt;div class=&quot;step-content&quot; id=&quot;checkout-step-&lt;?php echo $this-&gt;getStepCode();?&gt;-content&quot;&gt;&lt;?php echo $this-&gt;getStepContent(); ?&gt;&lt;/div&gt;
    &lt;?php if ($this-&gt;hasLoadingOverlay()):?&gt;
    &lt;div class=&quot;step-loading&quot; style=&quot;display:none;&quot;&gt;&lt;span&gt;&lt;img src=&quot;&lt;?php echo $this-&gt;getSkinUrl('images/opc-ajax-loader.gif') ?&gt;&quot; alt=&quot;&lt;?php echo $this-&gt;__('Loading step data...') ?&gt;&quot; title=&quot;&lt;?php echo $this-&gt;__('Loading step data...') ?&gt;&quot; class=&quot;v-middle&quot; /&gt; &lt;?php echo $this-&gt;__('Loading step data...') ?&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;?php endif;?&gt;
&lt;/div&gt;
&lt;?php endif;?&gt;
</pre><p>As you see, there is no billing address form. Instead of rending form in extension, it renders <strong>checkout/onepage_billing</strong> block and outputs it via <strong>getStepContent</strong> method. So standard Magento checkout step HTML is used.</p><h4>Container Blocks</h4><p>Additionally to standard step blocks, there are container ones. All of them are using EcomDev_CheckItOut_Block_Layout_Step_Container class, that has some nice methods:</p><ul><li><strong>addClassNameForStepCount($className, $stepCount)</strong> &#8211; conditional <strong>addClassName</strong> method implementation. Adds CSS class only if amount of child blocks, that visible and implement <strong>EcomDev_CheckItOut_Block_Layout_Step_Interface</strong> interface, is equal to <strong>$stepCount</strong>.</li><li><strong>removeClassNameForStepCount($className, $stepCount)</strong> &#8211; conditional <strong>removeClassName</strong> method implementation. Has similar logic to the previous method.</li><li><strong>getStepCount()</strong> &#8211; returns number of child blocks, that implement <strong>EcomDev_CheckItOut_Block_Layout_Step_Interface</strong> and are visible</li><li><strong>getStepContent()</strong> &#8211; returns all sorted child blocks HTML, that are visible.</li><li><strong>isVisible()</strong> &#8211; indicates container visibility, determined by number returned by <strong>getStepCount()</strong> method.</li></ul><p>Both these types of blocks building the layout system of CheckItOut! extension. However it is not all layout benefits. There also very flexible system of layout handles.</p><h4>Layout Handles</h4><p>As you know, it is possible to choose in Magento checkout extension configuration the page layout. For instance you can make it two column or just default single step style. This functionality is build in a very easy way. We added a special configuration node where you can specify as many layout handle names, as you wish. The node where you can add custom layout types is the following: <strong>ecomdev/checkitout/layout</strong>. Please take a look at the following XML of two_column layout type:</p><pre class="brush: xml; title: ; notranslate">
&lt;two_columns translate=&quot;label&quot; module=&quot;ecomdev_checkitout&quot;&gt;
    &lt;label&gt;Two Column Layout&lt;/label&gt;
    &lt;handles&gt;
        &lt;default&gt;ecomdev_checkitout_layout_default&lt;/default&gt;
        &lt;custom&gt;ecomdev_checkitout_layout_two_column&lt;/custom&gt;
    &lt;/handles&gt;
&lt;/two_columns&gt;
</pre><p>Node name is an unique code for layout type. Label is for showing name of the layout type to the admin user. Handles node contains layout handles that will be added in the same order as they are specified.</p><p>As you see for two columns design it uses default handle as a base and own custom one as modifier. You are not limited to only two layout handles, you can add as many of them you wish, so you can build layout structures very easily.</p><h2>What You Can Do With It</h2><p>Most of our customers who buy the extension, just telling us that it is awesome checkout platform for their stores and very easy to customize it for skilled developer. I&#8217;ve seen at least 5 websites with customized version of CheckItOut!, that have really amazing flow implementation. It is very easy to customize from layout XMl as well as on CSS level.</p><p>Hope you will like it as well, as most of our customers!</p><p>P.S. Just forgot to give you a link for it: <a
href="http://shop.ecomdev.org/checkitout.html" title="Our Magento Checkout Extension">CheckItOut! &#8211; Magento Checkout Extension</a></p><p>The post <a
href="http://www.ecomdev.org/2012/11/29/magento-checkout-extension-ideas-architecture-revealed.html">Our Magento Checkout Extension Ideas &#038; Architecture Revealed</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/11/29/magento-checkout-extension-ideas-architecture-revealed.html/feed</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>5 Great Reasons for Visiting Test Driven Development Training in January</title><link>http://www.ecomdev.org/2012/11/27/five-great-reasons-for-visiting-test-driven-development-training.html</link> <comments>http://www.ecomdev.org/2012/11/27/five-great-reasons-for-visiting-test-driven-development-training.html#comments</comments> <pubDate>Tue, 27 Nov 2012 15:27:21 +0000</pubDate> <dc:creator>Ivan Chepurnyi</dc:creator> <category><![CDATA[News]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=7196</guid> <description><![CDATA[<p>During MeetMagento Poland conference I announced the launch of the registration for Test Driven Development course from 9th till 10th of January. Today I want to provide more information about the course and benefits you can get from it! Reason #1. Knowledge This course will help you in learning the main concepts of test drived [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/11/27/five-great-reasons-for-visiting-test-driven-development-training.html">5 Great Reasons for Visiting Test Driven Development Training in January</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>During MeetMagento Poland conference I announced the launch of the registration for Test Driven Development course from 9th till 10th of January. Today I want to provide more information about the course and benefits you can get from it!</p><h2>Reason #1. Knowledge</h2><p>This course will help you in learning the main concepts of test drived development with Magento. Also it gives awesome opportunity for getting familiar with best practices in usage of our EcomDev_PHPUnit extension. BTW, just few weeks before the course, a new version of extension going to be released. This version will contain a lot of code refactoring and optimization, that of course will benefit you in your day to day development.</p><h2>Reason #2. Attendees</h2><p>This training course is a great opportunity to meet with other developers who is also addicted to test driven development. Together with them, you can learn much more, than doing it yourself.</p><h2>Reason #3. Magento-Hackathon</h2><p>As you know from 11th till 13th of January, there is another awesome event planned in Berlin! I cannot imagine better opportunity to apply your knowledge on practice, right after the training! Check it out: <a
href="http://www.magento-hackathon.de/">http://www.magento-hackathon.de/</a></p><h2>Reason #4. Location</h2><p>The training center is located in the city centre of Berlin. It is in average a 20 minute walk from the most popular touristic sights. Check the location on the map: <a
href="http://goo.gl/maps/qn7o0">http://goo.gl/maps/qn7o0</a></p><h2>Reason #5. Cookies</h2><p>Every Magento developer likes cookies, so there will be enough amount of them to meet the demand.</p><h2>Not yet interested? Check out the training agenda!</h2><div
class='et-box et-shadow'><div
class='et-box-content'><h3>9th of January, 2013</h3><ul><li>TDD vs Standard Magento Development</li><li>Testing Module Configuration<ul><li>Class Aliases</li><li>Layout Definitions</li><li>Scheme &amp; Data Setups</li><li>Events</li><li>Controllers</li><li>etc</li></ul></li><li>Testing Models &amp; Observers<ul><li>What to Test</li><li>Emulation of System Proceses</li><li>Reusable Test Cases &amp; Expectations</li></ul></li><li>Test Doubles &amp; Fixtures<ul><li>How to Mock System Resources</li><li>Isolation of Test Case</li><li>Fixtures</li></ul></li></ul><h3>10th of January, 2013</h3><ul><li>File System Based Tests</li><li>Testing Blocks</li><li>Testing Controllers &amp; Layout<ul><li>Understanding of Layout Based Controller Tests</li><li>What to Test</li><li>Controller Specific Assertions</li><li>Layout Specific Assertions</li></ul></li><li>Continuous Integration<ul><li>Why Make It Continuos</li><li>Configuring Environment for CI</li><li>Additional Useful Tools</li></ul></li><li>Customizations Of EcomDev_PHPUnit<ul><li>Custom Test Structures</li><li>Building Fixture Loaders</li></ul></li></ul></div></div><h2>Training Facility</h2><p>The FastLane Institute of Knowledge provides a fully equipped training room with PC that have all the required preinstalled software. So you don&#8217;t need to bring own laptop, install development environment and Magento. Everything will be already prepared for you!</p><h2>Do You Want to Register?</h2><p>Just do it right now at the <a
title="Test Driven Development Course in Berlin" href="http://www.ecomdev.org/tdd-training-in-berlin-jan-2012  " target="_blank">following page</a>.</p><p>The post <a
href="http://www.ecomdev.org/2012/11/27/five-great-reasons-for-visiting-test-driven-development-training.html">5 Great Reasons for Visiting Test Driven Development Training in January</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/11/27/five-great-reasons-for-visiting-test-driven-development-training.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Magento Smart Trick of The Day: Dynamic Home Page</title><link>http://www.ecomdev.org/2012/11/01/magento-smart-trick-of-the-day-dynamic-home-page.html</link> <comments>http://www.ecomdev.org/2012/11/01/magento-smart-trick-of-the-day-dynamic-home-page.html#comments</comments> <pubDate>Thu, 01 Nov 2012 13:21:03 +0000</pubDate> <dc:creator>Ivan Chepurnyi</dc:creator> <category><![CDATA[Tricks]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=7099</guid> <description><![CDATA[<p>Today there we were discussing one of the project specific functionality. Customer wants to show different homepage for logged in and logged out users. And the were a lot of ideas on rewriting controller, helper or model. However, in the end, the smartest idea was to realize all this logic without any rewrite. Idea So [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/11/01/magento-smart-trick-of-the-day-dynamic-home-page.html">Magento Smart Trick of The Day: Dynamic Home Page</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>Today there we were discussing one of the project specific functionality. Customer wants to show different homepage for logged in and logged out users. And the were a lot of ideas on rewriting controller, helper or model. However, in the end, the smartest idea was to realize all this logic without any rewrite.</p><h2>Idea</h2><p>So as all of you know, the identifier of the home page is stored in configuration and retrieved via <strong>Mage::getStoreConfig()</strong> method. But not everyone knows, that you can easily change any configuration value on the fly without changing the actual values in the database or file system. And we decided to use this smart trick to substitute the value of in configuration before the page renders.</p><h2>Realization</h2><p>First of all we need to create module that will contain our observer. I won&#8217;t describe how to do it, since I believe you can do it yourself.</p><p>So let&#8217;s just start from creating an observer that will make this substitution on the fly:</p><pre class="brush: php; title: ; notranslate">
class Your_ModuleName_Model_Observer
{
    // Configuration path for our custom cms homepage
    const XML_PATH_FOR_CONFIG_TO_CUSTOM_HOMEPAGE = 'somemodule_section/home/page';
    /**
     * Substitutes homepage during by replacing
     * configuration value for the current store
     *
     */
    public function substituteHomePage()
    {
        $customHomePageForLoggedIn = Mage::getStoreConfig(self::XML_PATH_FOR_CONFIG_TO_CUSTOM_HOMEPAGE);
        if (Mage::helper('customer')-&gt;isLoggedIn()
            &amp;&amp; $customHomePageForLoggedIn) {
            // Substitute only if page is defined
            Mage::app()-&gt;getStore()-&gt;setConfig(
                Mage_Cms_Helper_Page::XML_PATH_HOME_PAGE,
                $customHomePageForLoggedIn
            );
        }
    }
}
</pre><p>As you noticed in the code, the page that is gets set for logged in customers defined somewhere in configuration. It is because we don&#8217;t like hardcode values in our modules ;). If you&#8217;d like to know how to define this configurations, please refer to <a
title="Custom configuration fields in Magento" href="http://www.ecomdev.org/2010/10/27/custom-configuration-fields-in-magento.html">our article about it</a>.</p><p>Then the next step is to attach our observer to a particular controller preDispatch. In our case it is <strong>cms_index_index</strong> action, so event name will be <strong>controller_action_predispatch_cms_index_index</strong>. You need to specify the following in config.xml of your module, to make it happen:</p><pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config&gt;
   &lt;frontend&gt;
       &lt;events&gt;
          &lt;controller_action_predispatch_cms_index_index&gt;
              &lt;observers&gt;
                  &lt;your_modulename&gt;
                      &lt;model&gt;your_modulename/observer&lt;/model&gt;
                      &lt;method&gt;substituteHomePage&lt;/method&gt;
                  &lt;/your_modulename&gt;
              &lt;/observers&gt;
          &lt;/controller_action_predispatch_cms_index_index&gt;
       &lt;/events&gt;
   &lt;/frontend&gt;
&lt;/config&gt;
</pre><h2>Where To Use</h2><p>The trick above can be used not only for this functionality. It is just a particular use case we have met on one of our projects, you have more ways to implement it based on different conditions. For instance, if you are developing a project based on enterprise edition, you can make conditions for pages based on a particular customer segment. But in this case you should consider, that full page cache is not taking care of the current segment when caching data, so some magic with cache processor should be done.</p><p>Have fun developing with Magento!</p><p>The post <a
href="http://www.ecomdev.org/2012/11/01/magento-smart-trick-of-the-day-dynamic-home-page.html">Magento Smart Trick of The Day: Dynamic Home Page</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/11/01/magento-smart-trick-of-the-day-dynamic-home-page.html/feed</wfw:commentRss> <slash:comments>8</slash:comments> </item> <item><title>Magento and style custom elements of the form</title><link>http://www.ecomdev.org/2012/10/04/magento-and-style-custom-elements-of-the-form.html</link> <comments>http://www.ecomdev.org/2012/10/04/magento-and-style-custom-elements-of-the-form.html#comments</comments> <pubDate>Thu, 04 Oct 2012 10:00:21 +0000</pubDate> <dc:creator>Artem Deykun</dc:creator> <category><![CDATA[How To]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=7043</guid> <description><![CDATA[<p>Current realities of web-design require from the front-end developer to copy all elements. One of the most difficult on my opinion are elements of the forms. Realization has varying difficulty for online business card and for huge CMS like Magento. Is it possible to make it pixel to pixel with the design for Magento template? [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/10/04/magento-and-style-custom-elements-of-the-form.html">Magento and style custom elements of the form</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>Current realities of web-design require from the front-end developer to copy all elements. One of the most difficult on my opinion are elements of the forms.</p><p>Realization has varying difficulty for online business card and for huge CMS like Magento.<br
/> Is it possible to make it pixel to pixel with the design for Magento template? Certainly yes, but just if you know all render content.</p><p>If you want to create general-purpose style for all themes for Magento you will stumble upon many obstacles.</p><h2>First step &#8211; browser support in terms of reference</h2><p><img
class="alignnone size-full wp-image-7046" title="termofref" src="http://www.ecomdev.org/wp-content/uploads/2012/12/termofref.jpg" alt="" width="640" height="163" /></p><p>The first step for beginning creating custom fields, is a condition in the terms of reference must be the paragraph about browser suppor like this:</p><blockquote><p><strong>Browser Support</strong><br
/> The custom fields of form will be developed as in design for browsers with support CSS3. In old browsers like IE7,8, Firefox2 will be displayed default fields.</p></blockquote><ul><li>You have a lot of arguments in favor of this.</li><li>The less code in HTML layout – better for SEO.</li><li>Faster upload and render page.</li><li>Less JavaScript – the chipper support the project in future.</li><li>Those people who use old browsers will not appreciate efforts.</li><li>It’s modernly.</li></ul><h2>HTML5 and CSS3 Rescue Rangers</h2><p><img
class="alignnone size-full wp-image-7048" title="html5css3" src="http://www.ecomdev.org/wp-content/uploads/2012/12/html5css31.png" alt="" width="640" height="163" /></p><p>For a simple web-site it is possible to write general stylesheet on CSS3. The common idea of realization custom elements like radio or checkbox on CSS3 is to hide input and set background to label with sprite.</p><pre class="brush: css; title: ; notranslate">input[type=&quot;checkbox&quot;] {
    opacity: 0;
    position: absolute;
}
input[type=&quot;checkbox&quot;] + label::before {
    background: url('custom_checkbox.png') no-repeat 0 -15px;
}</pre><p>This method needs to be accurate and sticks the same layout for elements all over the project.</p><h3>Problematic situations in the Magento</h3><p>In different blocks we see different layout.</p><blockquote><p>In related product you can see checkbox with no label.<br
/> In checkout radio which sometimes wrapped in span, sometimes not.<br
/> In rating block we can see label wrapped in span.<br
/> In account page we can find checkbox wrapped in div and with js event on it.</p></blockquote><p>So, if you have the goal to solve this problem just with CSS3 you need to refactor all template files and structure them the same as it possible.</p><p><strong>Some advices:</strong></p><ul><li>Try don’t change existing class names.</li><li>Be careful with js events in tags.</li><li>Always test form validation after customization.</li></ul><p><strong>Be very careful with checkout in Magento (v 1.7): </strong><br
/> HTML render different structured HTML layout, so you must check every step and all options.</p><h3>Ready to use CSS3 stylesheets</h3><p>Check the solution for checkbox elements, radio-buttons and drop-down lists created by our company for you:</p><h4>Custom checkbox</h4><ul><li><a
href="https://github.com/EcomDev/examples/blob/master/custom-checkbox/default.css">Code on GitHub</a></li><li><a
href="http://examples.ecomdev.org/article-checkbox/index.html">Demo &amp; Documentation</a></li></ul><h4>Custom radio-button</h4><ul><li><a
href="https://github.com/EcomDev/examples/blob/master/custom-radio/default.css">Code on GitHub</a></li><li><a
href="http://examples.ecomdev.org/article-radio/index.html">Demo &amp; Documentation</a></li></ul><h4>Custom dropdown list</h4><ul><li><a
href="https://github.com/EcomDev/examples/blob/master/custom-dropdown/default.css">Code on GitHub</a></li><li><a
href="http://examples.ecomdev.org/article-dropdown/index.html">Demo &amp; Documentation</a></li></ul><p>Soon we will produce you custom buttons and inputs stylesheet.</p><h2>Implement stylesheets to Magento Project</h2><p><img
class="alignnone size-full wp-image-7049" title="mag" src="http://www.ecomdev.org/wp-content/uploads/2012/12/mag.png" alt="" width="640" height="163" /></p><p>You can mention, that custom checkbox and custom radio-button is almost identical – it’s really true but it was divided for this article deliberately because for the reason of different layout all over the Magento project it’s better to style blocks one by on.</p><p>If you are sure in your skills and adequacy your project you can use common method to checkbox and radio.</p><h3>Custom radio-buttons in poll (radio-button)</h3><p>You can see a video-guide about implementing custom radio-buttons to poll block on Magento 1.7 Community Edition.</p><p><iframe
width="640" height="480" src="http://www.youtube.com/embed/XKh2xZMeEqI" frameborder="0" allowfullscreen></iframe></p><p><strong>Instruction</strong></p><ol><li>Include CSS file in project</li><li>Insert CSS file within Magento XML layouts</li><li>Adjust your styles within situation and fix bugs if you have.</li><li>Test in browsers.</li><li>Try to submit form.</li></ol><p><strong>Result:</strong></p><p><img
class="alignnone size-full wp-image-7051" title="radio" src="http://www.ecomdev.org/wp-content/uploads/2012/12/radio.png" alt="" width="225" height="210" /></p><h3>Custom checkboxes in related product (checkbox)</h3><p>In related product we have checkboxes with lo label. Technically we can solve it in two ways:</p><ol><li>Editing template file</li><li>Hack in JS without editing template file</li></ol><h4>With editing template file</h4><p><strong>Step 1</strong><br
/> Insert line with label in file &#8220;<strong>catalog/product/list/related.phtml</strong>&#8220;. It must looks like this:</p><pre class="brush: php; title: ; notranslate">
&lt;input class=&quot;checkbox related-checkbox&quot; type=&quot;checkbox&quot; id=&quot;related-checkbox&lt;?php echo $_item-&gt;getId() ?&gt;&quot;
name=&quot;related_products[]&quot; value=&quot;&lt;?php echo $_item-&gt;getId() ?&gt;&quot; /&gt;
&lt;label for=&quot;related-checkbox&lt;?php echo $_item-&gt;getId() ?&gt;&quot;&gt;&lt;/label&gt;
</pre><p><strong>Step 2</strong><br
/> Implement stylesheet CSS the same way as in the previos example about radio-button.</p><p><strong>Step 3</strong><br
/> Make some adjustments in CSS to display checkbox in right way</p><pre class="brush: css; title: ; notranslate">
#block-related label {
    float:left;
}
</pre><h4>Hack in JS without editing template file</h4><p>The same as in the previos solution but in first step instead changes in templates include in project JS based on prototype.</p><pre class="brush: jscript; title: ; notranslate">
$('block-related').select(&quot;input[type=checkbox]&quot;).each(function(el){
   new Insertion.After(el,
   '&lt;label for=&quot;' + el.identify() + '&quot;&gt;&lt;/label&gt;');
});
</pre><p><strong>Result:</strong></p><p><img
class="alignnone size-full wp-image-7053" title="checkbox" src="http://www.ecomdev.org/wp-content/uploads/2012/12/checkbox.png" alt="" width="191" height="257" /></p><h2>Conclusion</h2><p>As conclusion we can say, that there are no universal method of integration custom elements form to all project. But we can derive a formula of successful front-end development at this part.</p><p>The post <a
href="http://www.ecomdev.org/2012/10/04/magento-and-style-custom-elements-of-the-form.html">Magento and style custom elements of the form</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/10/04/magento-and-style-custom-elements-of-the-form.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Magento Checkout: Functionality Concept</title><link>http://www.ecomdev.org/2012/08/28/magento-checkout-functionality-concept.html</link> <comments>http://www.ecomdev.org/2012/08/28/magento-checkout-functionality-concept.html#comments</comments> <pubDate>Tue, 28 Aug 2012 08:00:44 +0000</pubDate> <dc:creator>Ivan Chepurnyi</dc:creator> <category><![CDATA[Overview]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=6834</guid> <description><![CDATA[<p>Dear Magento Developer, today we are going to start learning about Magento checkout process. This article will be the first one in the series, that will describe Magento Checkout &#38; Sales process from A to Z. In this article you will get acquainted with main concept of the checkout process, including general description of modules and [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/08/28/magento-checkout-functionality-concept.html">Magento Checkout: Functionality Concept</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>Dear Magento Developer, today we are going to start learning about Magento checkout process. This article will be the first one in the series, that will describe Magento Checkout &amp; Sales process from A to Z. In this article you will get acquainted with main concept of the checkout process, including general description of modules and entities. In the next articles it would be described more in details about aspects of Magento Checkout process customization.<br
/> <span
id="more-6834"></span></p><h2>Main Magento Checkout Modules</h2><p>Checkout functionality is spread over different modules. There are 4 modules, that represent the base functionality of it. Of course there are more modules, involved in the process, but most of them (like shipping, payment method) just extend existing functionality of base ones. So let&#8217;s take a look at these base modules for checkout process.</p><h3>Mage_Checkout module</h3><p>Talking about this module, it considers to be the main module in checkout process. It contains controllers, blocks and models, that realize the logic of checkout flow. It has currently two on-site Magento checkout flows and, I suppose, you know them: Onepage and Multishipping. Both of them have similar structure, but realized via different controllers, blocks and models.</p><h4>Onepage checkout flow</h4><p>Onepage checkout flow is the most feature-rich and default one. Also all the payment and shipping methods, that are developed for Magento has been supporting this checkout flow more often, than other ones. It splits up into 6 steps:</p><ul><li><strong>Checkout Type Selection Step</strong><br
/> This is an entry point of the checkout flow, where customer has a choice how to proceed with checkout. There are few options available for him/her, depending on configuration: login as a customer, create a customer account during checkout or just make an order without registration (i.e. guest checkout). If a customer has already logged in, this step wouldn&#8217;t show up at all.</li><li><strong>Billing Address Step</strong><br
/> At this step customer enters his billing address, based on wich the available payment methods will be retrieved. Also against this information, the payment gateway usually performs a fraud check. If a customer is logged in, then he will just need to select one of addresses stored in his address book. If customer chose to use this address as his shipping one, then it will be just copied into it. Also based on billing address, taxes can be calculated, but it depends on configuration.</li><li><strong>Shipping Address Step</strong><br
/> This step is used for calculation of delivery costs and available shipping methods. Also by default Magento calculates taxes based on shipping address, if it stays the same in configuration. If there are no products, that must be shipped (e.g. digital/virtual products), this step is omitted.</li><li><strong>Shipping Method Step</strong><br
/> This step contains information about available shipping methods and costs. The chosen shipping method may affect available payment methods in the next step, because of order total being changed. The information for this step is retrieved from <strong>Mage_Shipping</strong> module and all the other ones, that extends it (e.g. some specific shipping carrier modules). In such a way, when there are no products in order, that must be shipped, this block is not visible as in previous step.</li><li><strong>Payment Method Step</strong><br
/> This step allows customer to choose preferred payment method and, of course, supply payment details (depends on payment method). The data for this step is supplied by <strong> Mage_Payment</strong> and all modules, that provide particular payment provider integration and extend this module functionality.</li><li><strong>Review Step</strong><br
/> This step is the last one in Onepage checkout, before an order thank-you page. It shows order summary and some specific blocks, that may be added for receiving customer consent on terms and conditions of purchase, 3D secure authorization, etc.</li></ul><p>The functionality of these steps are represented by such classes:</p><ul><li><strong>Mage_Checkout_Block_Onepage</strong> and <strong>Mage_Checkout_Block_Onepage_*</strong> classes represent view blocks of each step.</li><li><strong>Mage_Checkout_OnepageController </strong>class realizes controller logic for saving data from checkout and redirecting customer to a proper page.</li><li><strong>Mage_Checkout_Model_Onepage </strong>class is a model of checkout flow and takes care about validation and saving of the data in a proper way.</li></ul><h4>Multiple shipping addresses checkout flow</h4><p>Multi-shipping flow allows customer to choose different shipping address on item level, but has some architectural limitations, that doesn&#8217;t allow you to use it with all payment methods. It is splited up into such steps:</p><ul><li><strong>Login or Create an Account Step</strong><br
/> This step is required for checkout functionality, because of limitations related to address selection (it is required for Magento to have address for multiple shipping, being selected from customer address book)</li><li><strong>Select Addresses Step</strong><br
/> At this step customer selects a shipping address from address book for particular quote item. As well, by logic of this checkout flow, a separate address can be selected even for the same shopping cart item, having qty greater than 1.</li><li><strong>Shipping Information Step</strong><br
/> This step is used to choose delivery method per shipping address. The information about delivery costs retrieved via <strong>Mage_Shipping</strong> module, like in Onepage checkout flow.</li><li><strong>Billing Information Step</strong><br
/> At this step customer can change his billing address from address book (default billing address is used usually). Also customer can choose the payment method, he would like to pay with.Information about payment methods are also retrieved  from <strong>Mage_Payment</strong> module, but not all the enabled payment methods can be used for multiple shipping. Magento cannot use payment method with redirect to payment gateway page, because it is related to architectural limitation of multiple shipping (it is creating a separate order for each shipping address).</li><li><strong>Place Order Step</strong><br
/> This step is similar to Review step in one-page checkout. It shows order summary and some specific blocks, that may be added for receiving customer consent on terms and conditions of purchase, 3D secure authorization, etc.</li></ul><p>The functionality of this checkout flow is realized by the following classes:</p><ul><li><strong>Mage_Checkout_Block_Multishipping_*</strong> classes represent view blocks for each step.</li><li><strong>Mage_Checkout_MultishippingController </strong>class realizes controller logic for saving data from checkout and redirecting customer to a proper page.</li><li><strong>Mage_Checkout_Model_Type_Multishipping </strong>class is a model of checkout flow and takes care about validation and saving of the data in a proper way.</li></ul><h4>Generic classes</h4><p>Also checkout has some generic classes, that are used at shopping cart and by both checkout flows.</p><ul><li><strong>Mage_Checkout_Model_Session</strong> class is a session object, that stores information about current quote object and available checkout steps (depends on checkout flow).</li><li><strong>Mage_Checkout_Model_Cart </strong>class realizes simplified way of modification of the quote object at shopping cart page. Used in the system to add/update/remove products from quote.</li><li><strong>Mage_Checkout_Model_Agreement</strong> and <strong>Mage_Checkout_Block_Agreements</strong> classes are used for showing up terms and conditions checkboxes and text at the checkout page.</li></ul><h3>Mage_Sales module</h3><p>The next module is not less important than Mage_Checkout. This module provides models that represent small units of checkout and sales functionality. These units can be generally separated in two groups: quote entities (pre sale process) and order entities (after sale process).</p><h4>Quote Entities</h4><p>These entities are used for collecting order information before customer pressed &#8220;Place Order&#8221; button. They also only temporary ones, if you&#8217;ve set up cron jobs properly in Magento you will notice that with some period of time old quote objects are getting deleted from the database. There are such quote entities available:</p><h5>Quote</h5><p>This is the main entity, from which later on the order is created. It contains general information about order, currency and its rate, customer information and some general total values. It is also an entry point for access to all the other entities, like addresses, items, payment, shipping rates. The functionality of this entity is realized by <strong>Mage_Sales_Model_Quote</strong> class.</p><h5>Quote Item</h5><p>The next one, is an entity of a single product line in the order. It contains information about product, its relations and data for price calculations (prices, row totals, discounts, taxes, etc). It is represented by <strong>Mage_Sales_Model_Quote_Item </strong>class.</p><h5>Quote Address</h5><p>This entity contains billing or shipping information depending on it type. Also this entity is used for all the total calculations, because Magento can properly calculate taxes via using this information. There are some specific logic in calculation of the totals, depending on the type of order:</p><ul><li><strong>Virtual Order</strong> &#8211; if all the items in the quote are not applicable for shipping (e.g. downloadable products, digital gift cards), then billing address is used for calculation of all the totals of the order, since items will be assigned to billing address.</li><li><strong>Normal Order</strong> &#8211; if any item in the quote is applicable for shipping, then shipping address is used for calculation of all the totals. If there is more then one shipping address with assigned quote items to it, then the totals will be merged and summary will be used for quote object.</li></ul><p>More about totals and addresses you will learn from the next articles.</p><h5>Quote Address Item</h5><p>This entity is used only if Multishipping flow. It extends functionality of quote items by linking total calculation per shipping address. The functionality of this entity is realized by <strong>Mage_Sales_Model_Quote_Address_Item</strong> class.</p><h5>Quote Address Shipping Rate</h5><p>This entity is used for storing result of the last shipping rate collection process, this one is used only for temporary purpose and not exported into order. The functionality is realized by <strong>Mage_Sales_Model_Quote_Address_Rate </strong> class.</p><h5>Quote Payment</h5><p>The entity is used for storing and validation of payment data entered by customer, and using it later on during order placement process, by another entity. This entity is not doing any payment transactions, since all transactions are done based on created order. The functionality is realized by <strong>Mage_Sales_Model_Quote_Payment</strong> class.</p><h4>Order Entities</h4><p>When customer pressed &#8220;Place Order&#8221; button in the admin panel, these entities will take the control over checkout process. The entities data are retrieved from quote by using service models and fieldset maps defined in configuration (see <strong>global/fieldsets </strong>in <a
title="Magento module configuration file reference" href="http://www.ecomdev.org/2010/08/31/magento-module-configuration-file-reference.html" target="_blank">this article</a>). There are such entities available:</p><h5>Order</h5><p>This is the general entity of the post sale process. It contains values of totals calculated during checkout process, sale state and general information about customer. As well this entity can be used as an entry point to access all the other entities related to it (items, addresses, shipments, invoices, etc).</p><p>The data for this entity gets imported from quote and quote address.</p><p>Unlike a quote address entity, this one does not calculate totals all the time. There are only few cases of totals being updated:</p><ul><li>Creation of<strong> invoice </strong>leads to updated order paid total amounts.</li><li>Creation of<strong> creditmemo </strong>leads to updated  order refund total amounts.</li><li>In case of <strong>cancelled order </strong>appropriate total amounts will be updated as well.</li></ul><p>The functionality of this entity is realized by <strong>Mage_Sales_Model_Order</strong> class.</p><h5>Order Item</h5><p>This is an entity of a single product line in the order with information about ordered, paid, canceled and refunded amounts. As well this entity contains some general information about product and options selected during checkout process.</p><p>Depending on the checkout flow the data for this entity is supplied from quote item (onepage) or quote item + address item (multi-shipping).</p><p>The special qty properties of this entity realizing system logic of possibility to create invoice, creditmemo, shipment, RMA or cancel an order. More details about their usage you will learn from the next article about customizations of quote and order entities.</p><p>The functionality of this entity is realized by <strong>Mage_Sales_Model_Order_Item</strong> class.</p><h5>Order Address</h5><p>This entity contains address information for specific address type. If order is not virtual, there order will have two addresses: billing and shipping. The entity data is transfered from quote address, but unlike quote address, it doesn&#8217;t have total amounts, only address and selected shipping method info.</p><p>The functionality of the entity is realized by <strong>Mage_Sales_Model_Order_Address</strong> class.</p><h5>Order Payment</h5><p>The entity represent itself a realization of unified way of all payment interaction with order. It contains data about payment method and some transaction details (depends on payment method realization). This entity using a payment method model that is provided from <strong>Mage_Payment</strong> or module that extends its functionality. So basically the entity itself is just a facade, that uses appropriate object to register payment transactions for an order.</p><p>The functionality of the entity is realized by <strong>Mage_Sales_Model_Order_Payment</strong> class.</p><h5>Order Payment Transaction</h5><p>This entity first time were introduced in Community Edition 1.4 to make possible storing of multiple transactions within one order. It was not possible before 1.4 to have multiple refunds working correctly, because of overridden transaction id for payment entity after first refund.</p><p>Basically transactions is a hierarchical structure of the payment method data, you can manage them within your payment method implementation in any way. For instance your payment module can create two partial credit card authorizations. In this case you need to track capture process for each authorization operation separately. This entity will help you to achieve correctly working solution.</p><p>The entity itself doesn&#8217;t have some specific payment functionality, it just stores data that were set by payment method instance. It is realized via <strong>Mage_Sales_Model_Order_Payment_Transaction</strong> class.</p><h5>Order Status History</h5><p>This one is very simple unit. It just used for tracking changes in order status with possibility to track some system message. The functionality is realized by <strong>Mage_Sales_Model_Order_Status_History</strong>.</p><h5>Invoice</h5><p>This entity is used to track actual payment capture operation for the order. Invoice has own items that are used for tracking payment state per every item qty in the order. As soon as invoice changes status to paid and a referencing order item sate and paid amount with qty will be updated.</p><p>There are two kind of invoices:</p><ul><li><strong>Online</strong> This kind of invoice is not available if payment method haven&#8217;t supplied transaction identifier during authorization process. When you create an online invoice, it will interact with payment method model for capturing money via payment gateway.</li><li><strong>Offline</strong> This kind of invoice is always available in Magento. Mostly used with non-online payment method, like &#8220;Check/Money Order&#8221;. If you create such an invoice, it won&#8217;t charge real customer&#8217;s money, it will just register that order items were paid.</li></ul><p>The functionality of invoice and its sub-entities is realized by the following classes:</p><ul><li><strong>Mage_Sales_Model_Order_Invoice</strong> an invoice itself</li><li><strong>Mage_Sales_Model_Order_Invoice_Item</strong> an invoice item, that is linked to order item.</li><li><strong>Mage_Sales_Model_Order_Invoice_Comment</strong> an invoice comment for some system or custom messages of admin user.</li><li><strong>Mage_Sales_Model_Order_Invoice_Total_*</strong> all of this classes are realizing total collectors logic to calculate proper amount of invoice amounts, that need to be paid.</li></ul><h5>Shipment</h5><p>This entity is used to track shipping status of the items in the order. When order state is changed to &#8220;processing&#8221;, it will be possible to create a shipment for particular order items or the whole order. The shipment is similar to invoice, except, that it has no total collectors and just registers qty that on item level for shipped items. As soon as all order items were shipped, the order will change its state to &#8220;complete&#8221;.</p><p>The functionality of the shipment and its sub-entities is realized by the following classes:</p><ul><li><strong>Mage_Sales_Model_Order_Shipment</strong> a shipment itself</li><li><strong>Mage_Sales_Model_Order_Shipment_Item</strong> a shipment item, that is linked to order item.</li><li><strong>Mage_Sales_Model_Order_Shipment_Comment</strong> a shipment comment for some system or custom messages of admin user.</li><li><strong>Mage_Sales_Model_Order_Shipment_Track</strong> a tracking number record, that is used for tracking delivery by API of some delivery method (FedEx, DHL, UPS, etc).</li></ul><h5>Creditmemo</h5><p>This entity is used for tracking refund process of the payment to customer for invoiced order items. Non-invoiced order items cannot be refunded, since no actual capture operation were registered for them.</p><p>There are two kind of creditmemos:</p><ul><li><strong>Online</strong> This kind of creditmemo is not available if payment method haven&#8217;t supplied transaction identifier during capture process. When such a creditmemo is created it will refund money back to customer via payment method model.</li><li><strong>Offline</strong> Like an offline invoice, this kind of creditmemo will be used only to register refund in Magento.</li></ul><p>The functionality of creditmemo and its sub-entities is realized by the following classes:</p><ul><li><strong>Mage_Sales_Model_Order_Creditmemo</strong> a creditmemo itself</li><li><strong>Mage_Sales_Model_Order_Creditmemo_Item</strong> a creditmemo item, that is linked to order item.</li><li><strong>Mage_Sales_Model_Order_Creditmemo_Comment</strong> a creditmemo comment for some system or custom messages of admin user.</li><li><strong>Mage_Sales_Model_Order_Creditmemo_Total_*</strong> all of this classes are realizing total collectors logic to calculate proper amount for refunding only money that was paid for items specified in creditmemo.</li></ul><p>All of these entities and other entities, that are defined in this module, will be described more in detail in the next articles with useful code snippets and customization guidelines.</p><h3>Mage_Shipping module</h3><p>This module is used for retrieving shipping costs and shipment tracking info for post sale process. It has a single model (<strong>Mage_Shipping_Model_Shipping</strong>), that reads configuration for gathering all the shipping carrier models and sends rate requests for calculation of shipping costs. All the carrier models are extended from <strong>Mage_Shipping_Model_Carrier_Abstract</strong> class, that is defined in this module.</p><p>Some carriers that are implemented by this module:</p><ul><li><strong>Mage_Shipping_Model_Carrier_Tablerate</strong> Fixed carrier implementation, that calculates shipping prices based on data stored in the database table. The rate is calculated based on destination and one of order totals (weight, amount, qty, etc).</li><li><strong>Mage_Shipping_Model_Carrier_Flatrate</strong> Fixed carrier implementation, that calculates shipping prices based on fixed price specified in the admin panel. Calculation formula depends on configuration.</li><li><strong>Mage_Shipping_Model_Carrier_Freeshipping</strong> Fixed carrier implementation, that always gives zero shipping price. The availability of this shipping method depends on minimum order subtotal specified in configuration.</li></ul><h3>Mage_Payment module</h3><p>This module is used during checkout process for retrieving of available payment methods and processing order payment later on. The payment methods are retrieved from configuration like shipping carriers in <strong>Mage_Shipping</strong> module.</p><p>All the payment method models are extended from an abstract class that is defined in this module (<strong>Mage_Payment_Model_Method_Abstract</strong>). Also this module has some generic payment methods that store owner already can use:</p><ul><li><strong>Mage_Payment_Model_Method_Checkmo</strong> Offline payment method, that allows customer to pay in cash or by check. When customer choose this payment method, the information about check beneficiary will be shown (if admin user specified it).</li><li><strong>Mage_Payment_Model_Method_Ccsave</strong> Offline payment method, that stores creditcard number for further processing by admin user.</li><li><strong>Mage_Payment_Model_Method_Purchaseorder</strong> Offline payment method, that stores PO number for further processing by admin user.</li><li><strong>Mage_Payment_Model_Method_Free</strong> Offline payment method, that is used only when grand total of the order is equal to zero. In Enterprise version of Magento it is used to track order that are fully paid by customer balance, reward points or giftcards.</li></ul><p>Of course there are more payment methods available in core, but they are implemented as standalone modules and can be disabled at any time. Mage_Payment module is always available.</p><h2>Summary</h2><p>This article itself cannot describe all the functionality of checkout, it is just a short overview. Anyway, I hope you got something valuable for yourself from it.<br
/> This article is only the first one in the series, so don&#8217;t forget to follow updates of our blog. There are more than ten topic drafts already, that are waiting to be shared with Magento community.</p><p>The post <a
href="http://www.ecomdev.org/2012/08/28/magento-checkout-functionality-concept.html">Magento Checkout: Functionality Concept</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/08/28/magento-checkout-functionality-concept.html/feed</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>Your project</title><link>http://www.ecomdev.org/your-project.html</link> <comments>http://www.ecomdev.org/your-project.html#comments</comments> <pubDate>Wed, 15 Aug 2012 08:37:37 +0000</pubDate> <dc:creator>Andrey Korolyov</dc:creator> <category><![CDATA[Portfolio]]></category> <guid
isPermaLink="false">http://www.ecomdev.org/?p=6818</guid> <description><![CDATA[<p>This project can be yours. But we do not limit potential features by listed below. Frontend Full theme development from PSD Custom styled components for widgets (banners, featured, etc) Quick view feature Custom layered navigation Custom search navigation Selectable category view layouts Selectable homepage layouts Backend: Data migration Custom sync data gathering feature with few [...]</p><p>The post <a
href="http://www.ecomdev.org/your-project.html">Your project</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<p>This project can be yours. But we do not limit potential features by listed below.</p><div
class="portfolio-descr"><p><strong>Frontend</strong></p><ul><li>Full theme development from PSD</li><li>Custom styled components for widgets (banners, featured, etc)</li><li>Quick view feature</li><li>Custom layered navigation</li><li>Custom search navigation</li><li>Selectable category view layouts</li><li>Selectable homepage layouts</li></ul><p><strong>Backend:</strong></p><ul><li>Data migration</li><li>Custom sync data gathering feature with few end-points</li><li>Custom catalog sync with products and inventory</li><li>Complex and custom shipping rules</li><li>Customized checkout flow</li><li>Custom advanced search with filterable results</li><li>New product custom option type</li><li>Custom menu admin panel with tool for shopmanager</li><li>Custom attribute&#8217;s groups management</li><li>Custom discount code rules</li><li>Custom proce matrixes based on options</li><li>Integrated product-movie management</li><li>Pick-up-at-store shipping with maps and management panel</li></ul><p><strong>Our extensions:</strong></p><ul><li>Multiple filters</li><li>Smart ColorSelector</li><li>ExIm</li><li>Url Rewrite Indexer</li><li>CheckItOut</li><li>StoreLocator</li><li>BrandManager</li></ul></div><div
class='et-box et-shadow'><div
class='et-box-content'><div
class='gf_browser_unknown gform_wrapper' id='gform_wrapper_3' ><form
method='post' enctype='multipart/form-data'  id='gform_3'  action='/feed'><div
class='gform_body'><ul
id='gform_fields_3' class='gform_fields top_label description_below'><li
id='field_3_8' class='gfield               gfield_contains_required' ><label
class='gfield_label' for='input_3_8'>Name<span
class='gfield_required'>*</span></label><div
class='ginput_container'><input
name='input_8' id='input_3_8' type='text' value='' class='medium' tabindex='1' /></div></li><li
id='field_3_3' class='gfield               gfield_contains_required' ><label
class='gfield_label' for='input_3_3'>Company<span
class='gfield_required'>*</span></label><div
class='ginput_container'><input
name='input_3' id='input_3_3' type='text' value='' class='medium'  tabindex='2'  /></div></li><li
id='field_3_2' class='gfield               gfield_contains_required' ><label
class='gfield_label' for='input_3_2'>Email<span
class='gfield_required'>*</span></label><div
class='ginput_container'><input
name='input_2' id='input_3_2' type='text' value='' class='medium'  tabindex='3'  /></div></li><li
id='field_3_9' class='gfield' ><label
class='gfield_label' for='input_3_9'>Phone</label><div
class='ginput_container'><input
name='input_9' id='input_3_9' type='text' value='' class='medium' tabindex='4' /></div></li><li
id='field_3_4' class='gfield' ><label
class='gfield_label' for='input_3_4'>Please provide a quote on</label><div
class='ginput_container'><select
name='input_4' id='input_3_4'  class='medium gfield_select' tabindex='5' ><option
value=' An Ecommerce Website' > An Ecommerce Website</option><option
value='Systems Integration &amp; Custom Build' >Systems Integration &amp; Custom Build</option><option
value='A Content Management System' >A Content Management System</option><option
value='Outsourcing Services' >Outsourcing Services</option><option
value='Custom Magento Extension' >Custom Magento Extension</option><option
value='I dont know what I need yet, please call me...' >I dont know what I need yet, please call me...</option></select></div></li><li
id='field_3_10' class='gfield               gfield_contains_required' ><label
class='gfield_label' for='input_3_10'>Deadline<span
class='gfield_required'>*</span></label><div
class='ginput_container'><select
name='input_10' id='input_3_10'  class='medium gfield_select' tabindex='6' ><option
value=' It&#039;s urgent! I need it as soon as possible' > It&#039;s urgent! I need it as soon as possible</option><option
value=' 1 - 4 weeks' > 1 - 4 weeks</option><option
value='4 - 8 weeks' >4 - 8 weeks</option><option
value='8 - 16 weeks' >8 - 16 weeks</option><option
value='16+ weeks' >16+ weeks</option><option
value='I&#039;m Not Sure' >I&#039;m Not Sure</option></select></div></li><li
id='field_3_7' class='gfield' ><label
class='gfield_label' for='input_3_7'>Budget Range</label><div
class='ginput_container'><select
name='input_7' id='input_3_7'  class='medium gfield_select' tabindex='7' ><option
value='less than $10,000' >less than $10,000</option><option
value='$10,000 - $25,000' >$10,000 - $25,000</option><option
value='$25,000 - $50,000' >$25,000 - $50,000</option><option
value='$50,000 - $100,000' >$50,000 - $100,000</option><option
value='more than $100,000' >more than $100,000</option></select></div></li><li
id='field_3_5' class='gfield' ><label
class='gfield_label' for='input_3_5'>Project details</label><div
class='ginput_container'><textarea name='input_5' id='input_3_5' class='textarea medium' tabindex='8'  rows='10' cols='50'></textarea></div></li><li
id='field_3_6' class='gfield' ><label
class='gfield_label' for='input_3_6'>Project blueprint if you have</label><div
class='ginput_container'><input
name='input_6' id='input_3_6' type='file' value='' size='20' class='medium' tabindex='9' /></div></li></ul></div><div
class='gform_footer top_label'> <input
type='submit' id='gform_submit_button_3' class='button gform_button' value='Submit' tabindex='10' /> <input
type='hidden' class='gform_hidden' name='is_submit_3' value='1' /> <input
type='hidden' class='gform_hidden' name='gform_submit' value='3' /> <input
type='hidden' class='gform_hidden' name='gform_unique_id' value='5198b50e3f5af' /> <input
type='hidden' class='gform_hidden' name='state_3' value='YToyOntpOjA7czo2OiJhOjA6e30iO2k6MTtzOjMyOiJkNTMyNzI4MTEwODU2ZjZlOTE4YTcxMzJjZjY5MGU1NyI7fQ==' /> <input
type='hidden' class='gform_hidden' name='gform_target_page_number_3' id='gform_target_page_number_3' value='0' /> <input
type='hidden' class='gform_hidden' name='gform_source_page_number_3' id='gform_source_page_number_3' value='1' /> <input
type='hidden' name='gform_field_values' value='' /></div></form></div></div></div><p>The post <a
href="http://www.ecomdev.org/your-project.html">Your project</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/your-project.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>KLM</title><link>http://www.ecomdev.org/2012/07/22/klm.html</link> <comments>http://www.ecomdev.org/2012/07/22/klm.html#comments</comments> <pubDate>Sun, 22 Jul 2012 09:28:15 +0000</pubDate> <dc:creator>Yaroslav Chervonenko</dc:creator> <category><![CDATA[Portfolio]]></category> <guid
isPermaLink="false">http://blog2.magentolive.nl/?p=6209</guid> <description><![CDATA[<p>Frontend Full theme development from PSD Custom styled components for widgets (banners, featured, etc) Quick view feature Custom layered navigation with sliders Backend: Shop migration Flight reservation system integration Complex delivery rules per products Integration with airline loyalty system Strict admin user restrictions Special PDF packing slips Special reports Special customer recognition system Customized checkout [...]</p><p>The post <a
href="http://www.ecomdev.org/2012/07/22/klm.html">KLM</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></description> <content:encoded><![CDATA[<div
class="portfolio-descr"><p><strong>Frontend</strong></p><ul><li>Full theme development from PSD</li><li>Custom styled components for widgets (banners, featured, etc)</li><li>Quick view feature</li><li>Custom layered navigation with sliders</li></ul><p><strong>Backend:</strong></p><ul><li>Shop migration</li><li>Flight reservation system integration</li><li>Complex delivery rules per products</li><li>Integration with airline loyalty system</li><li>Strict admin user restrictions</li><li>Special PDF packing slips</li><li>Special reports</li><li>Special customer recognition system</li><li>Customized checkout flow</li><li>Special price appearance on the frontend</li></ul><p><strong>Our extensions:</strong></p><ul><li>Multiple filters</li><li>ExIm</li></ul></div><div
class='et-image-slider et_sliderfx_fade et_sliderauto_true et_sliderauto_speed_7000 et_slidertype_images' id='et-image-slider103'><div
class='et-image-slides'><div
class='et-image' style='background: url(http://www.ecomdev.org/wp-content/uploads/2012/07/kml1.png) no-repeat; width: 585px; height: 300px;'><span
class='et-image-overlay'> </span></div><div
class='et-image' style='background: url(http://www.ecomdev.org/wp-content/uploads/2012/07/klm2.png) no-repeat; width: 585px; height: 300px;'><span
class='et-image-overlay'> </span></div><div
class='et-image' style='background: url(http://www.ecomdev.org/wp-content/uploads/2012/07/klm3.png) no-repeat; width: 585px; height: 300px;'><span
class='et-image-overlay'> </span></div><div
class='et-image' style='background: url(http://www.ecomdev.org/wp-content/uploads/2012/07/klm4.png) no-repeat; width: 585px; height: 300px;'><span
class='et-image-overlay'> </span></div><div
class='et-image' style='background: url(http://www.ecomdev.org/wp-content/uploads/2012/07/klm5.png) no-repeat; width: 585px; height: 300px;'><span
class='et-image-overlay'> </span></div></div><div
class='et-image-shadow'></div><div
class='et-image-shadowleft'></div><div
class='et-image-shadowright'></div></div><p>The post <a
href="http://www.ecomdev.org/2012/07/22/klm.html">KLM</a> appeared first on <a
href="http://www.ecomdev.org">EcomDev Magento Developers</a>.</p>]]></content:encoded> <wfw:commentRss>http://www.ecomdev.org/2012/07/22/klm.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>