Magento is an e-commerce platform that offers a lot of out the box.  It's extremely powerful and flexible but if the functionality that you want doesn't exist out of the box it can be added pretty easily using an extension.

One of our clients uses multiple carriers and shipping methods, but has made the business decision to offer a flat rate for each of those options.  While that makes life simple for gathering rates not worrying about product weights, getting shipping destination and looking up rates, there is some difficulty with creating promotions for the shipping options.  Some of the promotions that the client wanted to offer weren't able to be handled by Magneto natively, but we were able to implement the desired functionality with an extension.

Extension Structure

Magento uses an MVC structure, and the code directory is separated into 3 code pools - Core, Community, and Local.  The core directory is the default Magento functionality and should never be modified.  Community and Local are both for custom extensions with the major distinction of Local being your own extensions while 3rd party extensions belong in Community.  We'll assume that the extension we're building here will be shared on other projects or will go on Magento Connect for others to enjoy so we'll use the Community pool.

Magento uses a convention based system to look for extensions so naming and casing is very important.  Under the community directory, a folder with your company name should be created with the first letter capitalized.  Underneath that, we have the name of our extension, again paying close attention to naming and casing.

Let's write some code

The goal of this extension is to add start and end timestamps for promotional shipping (since no one likes staying up until 2 A.M. to make these changes manually).  We'll be basically adding a few fields onto a flat rate shipping carrier, so we can take a look at the default functionality and take a lot of what we need from there.  We can find the base shipping functionality in the \app\code\core\Mage\Shipping\ folder  In the system.xml file, we can take a look at the system.xml file to find how the flat rate shipping is setup.  We can replicate that in our module's system.xml file (\app\code\community\Liquid\Shipping\etc\system.xml) and add the fields we need.

A few changes to note from the core system.xml, we need to make sure we're using our module name under the groups and we can add then we can add our new fields.

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <sections>
        <carriers>
            <groups>
                <liquid_shipping translate="label">
                    <label>Liquid Shipping Carrier</label>
                    <sort_order>2</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>1</show_in_store>
                    <fields>
                        <discount_price translate="label">
                            <label>Discount Price</label>
                            <frontend_type>text</frontend_type>
                            <validate>validate-number validate-zero-or-greater</validate>
                            <sort_order>5</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </discount_price>
                        <discount_start_date translate="label">
                            <label>Discount Start Date</label>
                            <frontend_type>text</frontend_type>
                            <source_model>adminhtml/system_config_source_date_short</source_model>
                            <sort_order>6</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </discount_start_date>
                        <discount_end_date translate="label">
                            <label>Discount End Date</label>
                            <frontend_type>text</frontend_type>
                            <source_model>adminhtml/system_config_source_date_short</source_model>
                            <sort_order>6</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </discount_end_date>
                        <discount_message>
                            <label>Discount Message</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>7</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </discount_message>
						...
                    </fields>
                </liquid_shipping>
            </groups>
        </carriers>
    </sections>
</config>

Time for some PHP

Next we're going to create a new carrier extending the abstract class and implementing the carrier interface so we'll need to implement the getAllowedMethods and collectRates method. The getAllowedMethods method will simply return the name of our Method, and collectRates is where the meat of our work will be done.  We'll be utilizing our new fields - startDate, endDate, discountPrice, and discountMessage.

<?php
class Liquid_Shipping_Model_Carrier
extends Mage_Shipping_Model_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
	protected $_code = 'liquid_shipping';
	public function collectRates(Mage_Shipping_Model_Rate_Request $request)
	{
	...    
	}
	
	public function getAllowedMethods()
	{
	...
	}
}

Now that we have our files created, we can implement some logic.  Very simply what the below function will do is determine if the shipping method is active, check the current date against the discount start and end dates, and then use the appropriate rate and message.

   public function collectRates(Mage_Shipping_Model_Rate_Request $request)
    {
        if (!$this->getConfigFlag('active')) {
            return false;
        }
        $result = Mage::getModel('shipping/rate_result');
        $rate = Mage::getModel('shipping/rate_result_method');
        $startDate = new DateTime($this->getConfigData('discount_start_date'));
        $endDate = new DateTime($this->getConfigData('discount_end_date'));
        $currentDate = new DateTime("now");
        $shipPrice = $this->getConfigData('price');
        if (($startDate < $currentDate) && ($currentDate < $endDate)) {
            $discountMsg = $this->getConfigData('name') . $this->getConfigData('discount_message');
            $rate->setMethodTitle($discountMsg);
            $shipPrice = $this->getConfigData('discount_price');
        } else {
            $rate->setMethodTitle($this->getConfigData('name'));
        }
        $rate->setCarrier('liquid_shipping');
        $rate->setCarrierTitle($this->getConfigData('name'));
        $rate->setMethod('liquid_shipping');
        $rate->setPrice($shipPrice);
        $rate->setCost(0);
        $result->append($rate);
        return $result;
    }

Let's see what we've accomplished

One last step we need to take to enable our extension - we need to make Magento aware that our extension exists and is enabled.  In order to do this, we need to create another XML file and place it in /app/etc/modules.  Again naming is very important, and in this case our file is Liquid_Shipping.xml.

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Liquid_Shipping>
            <active>true</active>
            <codePool>community</codePool>
            <depends>
                <Mage_Shipping />
            </depends>
        </Liquid_Shipping>
    </modules>
</config>

What we see in the backend

After placing all of our code on the server, we'll see the changes in the Magento backed.  Our new method will show up as a new shipping method (System -> Configuration -> Shipping Methods).  We can then enter our values and enable our shipping method.

Now when we checkout, we'll see our new shipping method listed and the price will either be our normal shipping price, or our promo price with message.

While the above is a basic example and not production-ready you should now have a basic idea on how to create an extension to suit your needs.

You can download a copy of the sample code in this article from GitHub

Save

Published Oct 28, 2015