Pages

Tuesday 24 June 2014

Add Custom Fields to Order and Quote

In this blog, we will see how to add custom fields to magento onepage checkout steps. This method can be used to add custom field to any step in the checkout page, although in the current blog I have demonstrated how to add it to the shipping method step. This method will work on all magento versions. The tutorial is quite long since many files are required, here is source code of the module created in the tutorial.

Let start step by step, on how to add a fields on the shipping method step.

Step1: Adding HTML

This is the most simple step. I will add a text field to the shipping_method .phtml file.
For magento 1.13.0 we need to override the checkout/onepage/shipping_method .phtml. Open the phtml file, find the code

 <div id="onepage-checkout-shipping-method-additional-load">
        <?php echo $this->getChildHtml('additional') ?>
    </div>

and after add this line of code.

 <div>
        <!--Custom Field-->
        <fieldset>
            <ul class="form-list">
                <li class="control">
                    <input type="checkbox"
                           name="custom[shp_method]"
                           value="1"
                           title="<?php echo $this->__('Third Party') ?>"
                           id="shp_method:shp_method"
                           class="checkbox" onchange="shippingMethod.setEmpty();"/>
                    <label for="shp_method:shp_method"><?php echo $this->__('Third Party') ?></label>
                </li>
                <li class="fields">
                    <div class="field">
                        <label for="billing:account" class="required">
                            <em>*</em><?php echo $this->__('Account No') ?></label>
                        <div class="input-box">
                            <input  type="text" name="custom[account]"
                                    value="<?php echo $this->htmlEscape($this->getQuote()->getAccount()) ?>"
                                    title="<?php echo $this->__('Account No') ?>"
                                    id="billing:account" />
                        </div>
                    </div>
                </li>
                <li class="fields">
                    <div class="field">
                        <label for="billing:phone" >
                            <?php echo $this->__('Phone No') ?></label>
                        <div class="input-box">
                            <input  type="text" name="custom[phone]"
                                    value="<?php echo $this->htmlEscape($this->getQuote()->getPhone()) ?>"
                                    title="<?php echo $this->__('Phone No') ?>"
                                    id="billing:phone" />
                        </div>
                    </div>
                </li>
                <li class="fields">
                    <div class="field">
                        <label for="billing:comment"  >
                            <?php echo $this->__('Comment ') ?></label>
                        <div class="input-box">
                            <!--  <input type="text"  />-->
                            <textarea  name="custom[comment]"
                                       value="<?php echo $this->htmlEscape($this->getQuote()->getComment()) ?>"
                                       title="<?php echo $this->__('Comment') ?>"
                                       id="billing:comment"></textarea>
                        </div>
                    </div>
                </li>
            </ul>
        </fieldset>
        <!--Custom Field end-->
    </div>

after closing </form> tag

<script type="text/javascript">
    var billing_Form = new VarienForm('co-shipping-method-form');
    billing_Form.extraChildParams = ' onchange="shippingMethod.setEmpty();"';

</script>

and skin\frontend\easylife\default\js\opcheckout.js file under shippingmethod.prototype add below function.

 setEmpty:function(){
        //alert('Values');
        $('billing:account').value = '';
        $('billing:phone').value = '';
        $('billing:comment').value = '';

    },

and under validate function add below line of code.

var flag = $('shp_method:shp_method').checked;
        var account =   $('billing:account').value;
        //alert(flag);
        if (flag) {
            if(account == ''){
                alert(Translator.translate('Please specify account Number.').stripTags());
                return;
            }
        
        }

        flag = 0;


So, as you can see we are simply adding a text with name as custom After doing this, you should see a field in shipping_method.phtml as shown 

 . You can add this field on any checkout step, it doesn’t matter for my code.


Custom field on checkout page


 

Step2: Save the field in Quote and Order Tables
To save, out field to the quote object and database he are the things to do. First i will create a database table column. Put the following sql in your modules install file.

<?php
/* @var $installer Mage_Core_Model_Resource_Setup */
require_once('app/Mage.php');
$installer = $this;
$installer->startSetup();
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$installer = new Mage_Sales_Model_Resource_Setup('core_setup');
$attribute  = array(
    'type' => 'varchar',
    'backend_type' => 'varchar',
    'frontend_input' => 'varchar',
    'is_user_defined' => true,
    'label' => 'Delivery Date',
    'visible' => true,
    'required' => false,
    'user_defined' => false,
    'default' => '0',
    'comparable' => false,
    'searchable' => false,
    'filterable' => false
);
$installer->addAttribute('order','thirdparty_account_no',$attribute);
$installer->addAttribute('quote','thirdparty_account_no',$attribute);
$installer->addAttribute('order','thirdparty_phone_no',$attribute);
$installer->addAttribute('quote','thirdparty_phone_no',$attribute);
$installer->addAttribute('order','thirdparty_comment',$attribute);
$installer->addAttribute('quote','thirdparty_comment',$attribute);
$installer->endSetup();

Here we are creating 3 columns/fields, one for quote and other for order. I will explain the use of order table later. Now open phpmyadmin and confirm if the quote and order tables are created.
Next we need to write some event observers to capture quote save, and load events. So open your modules config.xml file and inside the <global> tag put in

<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_ThirdParty>
            <version>0.1.0</version>
        </Easylife_ThirdParty>
    </modules>
    <frontend>
        <routers>          
            <!-- <thirdparty>
                 <use>standard</use>
                 <args>
                     <module>Easylife_ThirdParty</module>
                     <frontName>party</frontName>
                 </args>
             </thirdparty>-->
        </routers>
        <layout>
            <updates>
                <thirdparty>
                    <file>thirdparty.xml</file>
                </thirdparty>
            </updates>
        </layout>
    </frontend>
    <adminhtml>
        <layout>
            <updates>
                <thirdparty>
                    <file>easylife/thirdparty.xml</file>
                </thirdparty>
            </updates>
        </layout>
    </adminhtml>
    <global>
        <events>
            <checkout_type_onepage_save_order>
                <observers>
                    <checkout>
                        <type>singleton</type>
                        <class>Easylife_ThirdParty_Model_Observer</class>
                        <method>customDataSave</method>
                    </checkout>
                </observers>
            </checkout_type_onepage_save_order>
            <sales_quote_save_before> <!-- Name of Event -->
                <observers>
                    <save_before>
                        <type>singleton</type>
                        <class>Easylife_ThirdParty_Model_Observer</class>
                        <!-- Over Model Class -->
                        <method>saveQuoteBefore</method>
                        <!-- name of function -->
                    </save_before>
                </observers>
            </sales_quote_save_before>
        </events>
        <models>
            <sales>
                <rewrite>
                    <order>Easylife_ThirdParty_Model_Sales_Order</order>
                </rewrite>
            </sales>
            <thirdparty>
                <class>Easylife_ThirdParty_Model</class>
                <resourceModel>thirdparty_resource</resourceModel>
            </thirdparty>
            <thirdparty_resource>
                <class>Easylife_ThirdParty_Model_Resource</class>
            </thirdparty_resource>
        </models>
        <resources>
            <thirdparty_setup>
                <setup>
                    <module>Easylife_ThirdParty</module>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </thirdparty_setup>
            <thirdparty_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </thirdparty_read>
            <thirdparty_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </thirdparty_write>
        </resources>
        <blocks>
           
            <thirdparty>
                <class>Easylife_ThirdParty_Block</class>
            </thirdparty>
        </blocks>
        <helpers>
            <thirdparty>
                <class>Easylife_ThirdParty_Helper</class>
            </thirdparty>
        </helpers>
    </global>
</config>

and next we need to create our Observer classes in Model folder. So create an Observer.php in your modules Model folder.

<?php
class Easylife_ThirdParty_Model_Observer
{
    public function customDataSave($observer){
        $session = Mage::getSingleton("core/session");
        $account_no =$session->getData('account_no');
        $phone_no =$session->getData('phone_no');
        $comment =$session->getData('comment');
        $event = $observer->getEvent();
        $order = $event->getOrder();
        $order->setThirdpartyAccountNo($account_no);
        $order->setThirdpartyPhoneNo($phone_no);
        $order->setThirdpartyComment($comment);
    }
    public function saveQuoteBefore($evt){
        $session = Mage::getSingleton("core/session");
        $quote = $evt->getQuote();
        $post = Mage::app()->getFrontController()->getRequest()->getPost();
        if(isset($post['custom']['account'])){
            $var = $post['custom']['account'];
            $quote->setThirdpartyAccountNo($var);
            $session->setData('account_no',$post['custom']['account']);
        }
        if(isset($post['custom']['phone'])){
            $var = $post['custom']['phone'];
            $quote->setThirdpartyPhoneNo($var);
            $session->setData('phone_no',$post['custom']['phone']);
        }
        if(isset($post['custom']['comment'])){
            $var = $post['custom']['comment'];
            $quote->setThirdpartyComment($var);
            $session->setData('comment',$post['custom']['comment']);
        }

    }
}

and Create order.php file in model

<?php
class Easylife_ThirdParty_Model_Sales_Order extends Mage_Sales_Model_Order
{
    public function hasCustomFields()
    {
        $var    =  $this->getThirdpartyAccountNo();
        $var    .=  $this->getThirdpartyPhoneNo();
        $var    .=  $this->getThirdpartyComment();
        if($var && !empty($var)){
            return true;
        }else{
            return false;
        }
    }
    public function getFieldHtml(){
        $var    =  $this->getThirdpartyAccountNo();
        $var    .=  $this->getThirdpartyPhoneNo();
        $var    .=  $this->getThirdpartyComment();
        //Mage::log($var);
        $html = '<b>Account No:</b>'.$var.'<br/>';
        $html .= '<b>Phone No:</b>'.$var.'<br/>';
        $html .= '<b>Comment:</b>'.$var.'<br/>';
        // Mage::log($html);
        return $html;
    }
}

So, what we have done above is captured the quote events sales_quote_save_before and checkout_type_onepage_save_order. Using these events saved our custom field to database. Details of functions are given in comments. We have already create model classes for this
 Easylife_Custom_Model_Custom_Order which you will find in the source code.

Detailed Explanation
  • The first event captured by our module is sales_quote_save_before and saveQuoteBefore() function is called in our Observer class. What this function does, just before $quote->save() function is called, it reads our custom variable value ‘ssn’ from FORM POST data and simply sets it in the $quote object.
  • The next event captured in checkout_type_onepage_save_order and function called is saveCustomData(). This event is called, just an order is successfully placed. In this event, we read our custom field value from quote object and put in order table.
Step3: Display Our Field in My Account -> View Order
 After doing this, you should be able to see your custom field in My Account page as shown here

<?xml version="1.0"?>
<layout version="0.1.0">
    <sales_order_view>
        <reference name="my.account.wrapper">
            <block type="custom/custom_order" name="custom.order" template="custom/order.phtml" after='sales.order.info' />
        </reference>
    </sales_order_view>
</layout>

This layout file is simple and understandable. Basically, we are taking reference of my.account.wrapper block and adding a child block to it. Our block type is custom/order_view and template file is custom/order.phtml.
So we need to create our block class

<?php
class Easylife_ThirdParty_Block_Custom_Order extends Mage_Core_Block_Template{
    public function getCustomVars(){
        $model = Mage::getModel('custom/custom_order');
        return $model->getByOrder($this->getOrder()->getId());
    }
    public function getOrder()
    {
        return Mage::registry('current_order');
    }
}

and our order.phtml file

<div class="col-set order-info-box">
    <div class="col">

        <div class="box">

            <div class="box-title">

                <h2><?php echo $this->__('Custom Fields') ?></h2>
            </div>
            <div class="box-content">
                 
                    <?php
                        $custom = $this->getCustomVars();
                        foreach($custom as $key => $value){
                    ?>
                        <b><?php echo $this->__($key);?></b> : <?php echo $value;?> <br/>
                    <?php } ?>
                 
            </div>
        </div>
    </div>
</div>


Step4: Admin Order View Page
Next we need to show our custom field in Admin -> Order -> View Order page. To do this, in our adminhtml layout file, in my case custom.xml we will put in this code.


<?xml version="1.0"?>
<layout version="0.1.0">
    <adminhtml_sales_order_view>
        <reference name="order_info">
            <action method='setTemplate'>
                <template>easylife/thirdparty/sales/order/info.phtml</template>
            </action>
            <block type="adminhtml/sales_order_view_info" name="order_info2"
                   template="sales/order/view/info.phtml"></block>
            <block type="thirdparty/adminhtml_order" name="custom.order" template='easylife/thirdparty/order.phtml'/>
        </reference>
    </adminhtml_sales_order_view>
</layout>

So basically here I have added my block “custom.order” to the existing order_info block. So the code for block class custom/adminhtml_custom_order would be

<?php
class Easylife_ThirdParty_Block_Adminhtml_Order extends Mage_Adminhtml_Block_Sales_Order_Abstract
{
    public function load(){
        $order = Mage::getModel('sales/order');
        return $order;
    }
    public function getAccountNo()
    {
        $order = Mage::getModel('sales/order')->getOrder();
        return $order;
    }
}

and next we need to create their phtml files
custom/order.phtml

<?php $_order = $this->getOrder() ?>
<div class="box-left">
    <div class="entry-edit">
        <div class="entry-edit-head">
            <h4 class="icon-head head-account"><?php echo Mage::helper('sales')->__('Third Party Shipper Details') ?></h4>
        </div>
        <div class="fieldset">
            <table cellspacing="0" class="form-list">
                <tr>
                    <td style="width:20%" class="label"><strong>
                            <?php echo Mage::helper('sales')->__('Account No') ?></strong></td>
                    <td class="value"><?php echo $this->getOrder()->getThirdpartyAccountNo(); ?></td>
                </tr>
                <tr>
                    <td style="width:20%" class="label"><strong><?php echo Mage::helper('sales')->__('Phone No') ?></strong></td>
                    <td class="value"><?php echo $this->getOrder()->getThirdpartyPhoneNo(); ?></td>
                </tr>
                <tr>
                    <td style="width:20%" class="label"><strong><?php echo Mage::helper('sales')->__('Comments') ?></strong></td>
                    <td class="value"><?php echo $this->getOrder()->getThirdpartyComment(); ?></td>
                </tr>
            </table>
        </div>
    </div>
</div>
<div class="clear"></div>

and custom/sales/order/info.phtml file

<?php echo $this->getChildHtml('order_info2');?>
<?php echo $this->getChildHtml('custom.order');?>

That's it, we are done. Hopefully I have covered all sections related to order. If i missed something please comment below and I will add it.

Custom fields on sales order page
If you have any queries leave a comment.



No comments:

Post a Comment