Despatch Date Module – part 8: Customise the order grid

Despatch Date Module – part 8: Customise the order grid

In this post, we’re going to add our new despatch date field as a column to the order grid page. This is the page with the list of customer orders. We’ll also add the company name as this column has also been requested by our client.

Here’s a view of what the order grid will look like when the two new columns have been added: ‘Company’ and ‘Despatch Date’.

order-grid

We’re going to make some changes to our module to achieve this. We’ll add the directories shown in orange. And shown in red are the the files that we’ll add, Grid.php and Format.php, and config.xml, which we need to change.

summary_module_Blocks

If you’ve been following in this series, you’ll know how we can display template and block names (or ‘hints’) on our Admin pages to show us what templates and blocks we are dealing with. (See part 2.) All the work in creating the order grid page is done in the block class ‘Mage_Adminhtml_Block_Sales_Order_Grid’ which is defined in /app/code/core/Mage/Adminhtml/Sales/Order/Grid.php. We won’t need to touch the template associated with this block, app/design/adminhtml/default/default/template/widget/grid.html, because it draws on the block class for it’s content with statements like ‘ <?php foreach ($this->getColumns() as $_column): ?>’.   The ‘getColumns()’ method can be found in ‘Mage_Adminhtml_Block_Widget_Grid’, which is the parent class of ‘Mage_Adminhtml_Block_Sales_Order_Grid’.

In case you were wondering, the template is tied to the class ‘Mage_Adminhtml_Block_Sales_Order_Grid’ in the class’s parent class ‘Mage_Adminhtml_Block_Widget_Grid’in the constructor method thus: ‘$this->setTemplate(‘widget/grid.phtml’);’. For the uninitiated, setting the template in the block class (‘programmatically’) is an alternative to setting it in the layout xml file.

We’ll extend ‘Mage_Adminhtml_Block_Sales_Order_Grid’ within our module in a new class ‘Blessthemoon_Despatchdate_Block_Adminhtml_Sales_Order_Grid’ defined in a new file Blessthemoon/despatchdate/Block/Adminhtml/Sales/Order/Grid.php. For the sake of good organisation, we’ve set up the directory path within our module to mirror the directory path of Mage/Adminhtml/Block/Sales/Order/Grid.php. We are overriding the methods ‘_prepareCollection()’ and ‘_prepareColumns()’. The first of these methods ‘_prepareCollection()’ is shown in the following code with additions in red.

1  <?php

2  

3  class Blessthemoon_Despatchdate_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid

4  {

5  protected function _prepareCollection()

6  {

7  $collection = Mage::getResourceModel($this->_getCollectionClass());

8  $collection->getSelect()->join(‘sales_flat_order_address’, ‘main_table.entity_id=sales_flat_order_address.parent_id AND sales_flat_order_address.address_type=\’billing\”,array(‘company’),NULL);

9  $collection->getSelect()->distinct();

10 $collection->getSelect()->join(‘sales_flat_order’, ‘main_table.entity_id = sales_flat_order.entity_id’, array(‘estdate’),NULL);

11 $this->setCollection($collection);

12 if ($this->getCollection()) {

13 $this->_preparePage();

14 $columnId = $this->getParam($this->getVarNameSort(), $this->_defaultSort);

15 $dir = $this->getParam($this->getVarNameDir(), $this->_defaultDir);

16 $filter = $this->getParam($this->getVarNameFilter(), null);

17 if (is_null($filter)) {

18 $filter = $this->_defaultFilter;

19 }

20 if (is_string($filter)) {

21 $data = $this->helper(‘adminhtml’)->prepareFilterString($filter);

22 $this->_setFilterValues($data);

23 }

24 else if ($filter && is_array($filter)) {

25 $this->_setFilterValues($filter);

26 }

27 else if(0 !== sizeof($this->_defaultFilter)) {

28 $this->_setFilterValues($this->_defaultFilter);

29 }

30 if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {

31 $dir = (strtolower($dir)==’desc’) ? ‘desc’ : ‘asc’;

32 $this->_columns[$columnId]->setDir($dir);

33 $this->_setCollectionOrder($this->_columns[$columnId]);

34 }

35 if (!$this->_isExport) {

36 $this->getCollection()->load();

37 $this->_afterLoadCollection();

38 }

39 }

40 return $this;

41 }

The ‘_prepareCollection()’ method in line 7 starts by instantiating the model collection. The ‘getCollectionClass’ method, which can be found in our new class’s parent, will get the resource model ‘sales/order_grid_collection’. This model accesses values directly from the ‘sales_flat_order_grid’ table in the database. All columns in the out-of-the-box default order grid are taken directly from this table. However, the column ‘est_date’ (despatch date) resides in the ‘sales_flat_order’ table, and the column ‘company’ resides in the ‘sales_flat_order_address’ table.

To access columns in other tables we need to use SQL joins as you can see in lines 8 and 10 of the code. The joins we need are shown in the diagram.

sql_join_tables

In line 8 of the code, you can see, how we access ‘company’. We join, where the ‘parent_id’ column in the ‘sales_flat_order_address’ table is equal to the ‘entity_id’ column in the ‘sales_flat_order_grid’ table (‘main_table’). As there are multiple addresses for each order, we select where ‘address_type=\’billing\”. To ensure we select only one record for each order, we use ‘getSelect()->distinct()’ in line 9. Similarly, in line 10 we access the column ‘estdate’ by joining where the ‘entity_id’ column in the ‘sales_flat_order’ table is equal to the ‘entity_id’ column in the ‘sales_flat_order_grid’ table (‘main_table’).

Now that we have our collection, we can add the extra columns to the grid that we need. The following code shows the rest of our Grid.php file with the changes we’ll make to the ‘_prepareColumns()’ method shown in red.

1  

2  

3  class Blessthemoon_Despatchdate_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid

4  {

:  

42 protected function _prepareColumns()

43 {

44 $this->addColumn(‘real_order_id’, array(

45 ‘header’=> Mage::helper(‘sales’)->__(‘Order #’),

46 ‘width’ => ’80px’,

47 ‘type’ => ‘text’,

48 ‘index’ => ‘increment_id’,

49 ));

50 if (!Mage::app()->isSingleStoreMode()) {

51 $this->addColumn(‘store_id’, array(

52 ‘header’ => Mage::helper(‘sales’)->__(‘Purchased From (Store)’),

53 ‘index’ => ‘store_id’,

54 ‘type’ => ‘store’,

55 ‘store_view’=> true,

56 ‘display_deleted’ => true,

57 ));

58 }

59 $this->addColumn(‘created_at’, array(

60 ‘header’ => Mage::helper(‘sales’)->__(‘Purchased On’),

61 ‘index’ => ‘created_at’,

62 ‘type’ => ‘datetime’,

63 ‘width’ => ‘100px’,

64 ));

65 $this->addColumn(‘company’, array(

66 ‘header’ => Mage::helper(‘customer’)->__(‘Company’),

67 ‘index’ => ‘company’

68 ));

69 $this->addColumn(‘billing_name’, array(

70 ‘header’ => Mage::helper(‘sales’)->__(‘Bill to Name’),

71 ‘index’ => ‘billing_name’,

72 ));

73 $this->addColumn(‘shipping_name’, array(

74 ‘header’ => Mage::helper(‘sales’)->__(‘Ship to Name’),

75 ‘index’ => ‘shipping_name’,

76 ));

77 $this->addColumn(‘estdate’, array(

78 ‘header’ => Mage::helper(‘sales’)->__(‘Despatch Date’),

79 ‘index’ => ‘estdate’,

80 ‘renderer’ => ‘Blessthemoon_Despatchdate_Block_Adminhtml_Sales_Order_Renderer_Format’,

81 ‘align’ => ‘right’,

82 ));

83 $this->addColumn(‘base_grand_total’, array(

84 ‘header’ => Mage::helper(‘sales’)->__(‘G.T. (Base)’),

85 ‘index’ => ‘base_grand_total’,

86 ‘type’ => ‘currency’,

87 ‘currency’ => ‘base_currency_code’,

88 ));

89 $this->addColumn(‘grand_total’, array(

90 ‘header’ => Mage::helper(‘sales’)->__(‘G.T. (Purchased)’),

91 ‘index’ => ‘grand_total’,

92 ‘type’ => ‘currency’,

93 ‘currency’ => ‘order_currency_code’,

94 ));

95 $this->addColumn(‘status’, array(

96 ‘header’ => Mage::helper(‘sales’)->__(‘Status’),

97 ‘index’ => ‘status’,

98 ‘type’ => ‘options’,

99 ‘width’ => ’70px’,

100‘options’ => Mage::getSingleton(‘sales/order_config’)->getStatuses(),

101));

102if (Mage::getSingleton(‘admin/session’)->isAllowed(‘sales/order/actions/view’)) {

103$this->addColumn(‘action’,

104array(

105‘header’ => Mage::helper(‘sales’)->__(‘Action’),

106‘width’ => ’50px’,

107‘type’ => ‘action’,

108‘getter’ => ‘getId’,

109‘actions’ => array(

110array(

111‘caption’ => Mage::helper(‘sales’)->__(‘View’),

112‘url’ => array(‘base’=>’*/sales_order/view’),

113‘field’ => ‘order_id’

114)

115),

116‘filter’ => false,

117‘sortable’ => false,

118‘index’ => ‘stores’,

119‘is_system’ => true,

120));

121}

122$this->addRssList(‘rss/order/new’, Mage::helper(‘sales’)->__(‘New Order RSS’));

123$this->addExportType(‘*/*/exportCsv’, Mage::helper(‘sales’)->__(‘CSV’));

124$this->addExportType(‘*/*/exportExcel’, Mage::helper(‘sales’)->__(‘Excel XML’));

125return parent::_prepareColumns();

126}

127}

The ‘addColumn’ method takes two arguments, an id and an array containing key value pairs to describe the column required. For ‘company’, the array specifies the ‘header’ which is ‘Company’ and the table column required with ‘index’ which is ‘company’. For ‘estdate’ (the despatch date’), in addition to ‘header’ and ‘index’, we identify with ‘align’ that we want the column ‘right’ aligned. We also use ‘renderer’ which allows us to specify how we want the values transformed or formatted to appear in the order grid. To do this we specify a class name, and we’ll need to build this class with the method ‘render’, which will be called when this block class is instantiated.

This code shows our new class which is located in ‘Renderer/Format.php’ along side our block file Grid.php. (See the module structure diagram above for a reminder.)

1<?php

2

3class Blessthemoon_Despatchdate_Block_Adminhtml_Sales_Order_Renderer_Format extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Action

4{

5public function render(Varien_Object $row)

6{

7$date = $row->getData($this->getColumn()->getIndex());

8if (!empty($date)) {

9$explodeDate = explode(“/”,$date);

10$formattedDate = $explodeDate[2].”/”.$explodeDate[1].”/”.$explodeDate[0];

11return $formattedDate;

12}

13}

14}

The new class extends ‘Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Action’ (line 3) which has the method ‘render’ which we want to override. For the currently rendered row passed into the method as $row, the method uses ‘getData’. Whereas, ‘getData()’ without any parameters gets an array of all attributes and their values for the current order id, in this case, with ‘$this->getColumn()->getIndex()’, we obtain the value of just the column specified by ‘index’ within ‘addColumn(‘estdate’,array(…,’index’=>’estdate’,…)’, i.e. ‘estdate’.

Next in lines 9 through 11, we transform the date from ‘YYY/MM/DD’ to ‘DD/MM/YYYY’ and return it. We could use ‘render’ to do much more as needed. For example, returning color coded dates based on whether the the despatch date is before or after today’s date.

With our block class, Grid.php, and its supporting class, Format.php, completed, we’ve just some housekeeping to take care of before we’re ready for testing. We need to tell Magento in config.xml about these two new block classes. These lines are shown in red.

1<?xml version=”1.0″?>

2<config>

3<modules>

4<Blessthemoon_Despatchdate>

5<version>0.1.0</version>

6</Blessthemoon_Despatchdate>

7</modules>

8<global>

9<blocks>

10<despatchdate>

11<class>Blessthemoon_Despatchdate_Block</class>

12</despatchdate>

13<adminhtml>

14<rewrite>

15<sales_order_grid>Blessthemoon_Despatchdate_Block_Adminhtml_Sales_Order_Grid</sales_order_grid>

16</rewrite>

17<rewrite>

18<widget_grid_column_renderer_action> Blessthemoon_Despatchdate_Block_Adminhtml_Sales_Order_Renderer_Format </widget_grid_column_renderer_action>

19</rewrite>

20</adminhtml>

21</blocks>

22<models>

23<sales>

24<rewrite>

25<order>Blessthemoon_Despatchdate_Model_Sales_Order</order>

26</rewrite>

27</sales>

28</models>

29<resources>

30<despatchdate_setup>

31<setup>

32<module>Blessthemoon_Despatchdate</module>

33<class>Blessthemoon_Despatchdate_Model_Resource_Setup</class>

34</setup>

35</despatchdate_setup>

36</resources>

37</global>

38<admin>

39<routers>

40<despatchdate>

41<use>admin</use>

42<args>

43<module>Blessthemoon_Despatchdate</module>

44<frontName>despatchdate</frontName>

45</args>

46</despatchdate>

47</routers>

48</admin>

49<adminhtml>

50<layout>

51<updates>

52<despatchdate>

53<file>despatchdate.xml</file>

54</despatchdate>

55</updates>

56</layout>

57</adminhtml>

58</config>

If you worked through part 7 of this series, you may recall how we used the ‘rewrite’ tag to override a model class. Here we’ve used the same syntax to override our block classes in ‘<sales_order_grid>’ and ‘<widget_grid_column_renderer_action>’ within ‘<adminhtml>’.

We’re there! We should have both ‘Despatch Date’ and ‘Company’ displayed nicely in our order grid page. In the next post, we’ll look at how we can also display the despatch date for customers in their ‘My Account’ area for any orders they’ve made.


david.mann

Leave a Reply

Your email address will not be published. Required fields are marked *