Override Admin Sales Order Search Grid

Last modified by gppgolf on Fri, June 10, 2011 10:46
Source|Old Revisions  

This is an old revision of the document!


When you are completing an offline order, using the admin Create Order functionality, when you Add Products, you are presented with a Product Search Grid. By default, this grid does not display the stock quantity. What I will show you here, is how to add the stock quantity without altering core code.

The following assumes that you are doing this on your local dev/test machine first!!!

1) Create the following folder structure (substitute Fws for your own company name in all the following examples): magento/code/local/Fws/Adminhtml/Block/Sales/Order/Create/Search

2) Copy the file from magento/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Search/Grid.php to your new location in step 1

3)Open the file magento/code/local/Fws/Adminhtml/Block/Sales/Order/Create/Search/Grid.php Replace the Class declaration from:

class Mage_Adminhtml_Block_Sales_Order_Create_Search_Grid extends Mage_Adminhtml_Block_Widget_Grid

to:

class Fws_Adminhtml_Block_Sales_Order_Create_Search_Grid extends Mage_Adminhtml_Block_Sales_Order_Create_Search_Grid

4) Within your Grid.php you can now begin to override the necessary functionality: First let’s set the id of our class

public function __construct()
  {
   parent::__construct();
   $this->setId('fws_adminhtml_block_sales_order_create_search_grid');

Then we need to add the Qty filter to the collection in the _prepareCollection() method. One option (the one previously advocated here) is to copy in the entire _prepareCollection function and add our own code. However, a better, more future proof way to do this is to override setCollection (called at the bottom of _prepareCollection) and tweak our filter there. Like this:

public function setCollection($collection)
{
        $collection->joinAttribute('artist','catalog_product/artist', 'entity_id', null,'left')
            ->addAttributeToFilter('type_id', array_keys(
                Mage::getConfig()->getNode('adminhtml/sales/order/create/available_product_types')->asArray()
            ))
              ->joinField('qty2',
                'cataloginventory/stock_item',
                'qty','product_id=entity_id','{{table}}.stock_id=1','left');
          parent::setCollection($collection);
}

This allows us to keep any future changes without needing to come back to our plugin and yet makes sure our filter gets called.

There are 2 things added

a) I have added a reference to a custom product attribute, so that I can retrieve its id:

 
->joinAttribute('artist','catalog_product/artist', 'entity_id', null,'left')

b) I get the stock quantity is this way

->joinField('qty2',
'cataloginventory/stock_item',                'qty','product_id=entity_id','{{table}}.stock_id=1','left')

Notice how I’ve named the variable returned as “qty2” - this is because “qty” is already used to determine how many of a selected product are added to the shopping cart.

We then send our modified collection on up to our parent:

          parent::setCollection($collection);

This is the same as calling:

        Mage_Adminhtml_Block_Widget_Grid::setCollection(); 

as the grid we’re overriding doesn’t change the setCollection function.

The next code block that needs amending is protected function _prepareColumns(), where you render your columns. Here again, we can either copy all the code in (requiring that we come back to check this everytime we upgrade Magento) or we can override things. We’ll choose to override.

So first we call our parent’s prepareColumns (so that we already have our columns). Then, I populate a drop down of artist names & then render the artist column:

    protected function _prepareColumns()
    {
        parent::_prepareColumns();

$artist_items = Mage::getModel('eav/entity_attribute_option')
            ->getCollection()
            ->setStoreFilter()
            ->join('attribute','attribute.attribute_id=main_table.attribute_id', 'attribute_code');
        foreach ($artist_items as $artist_item) :
            if ($artist_item->getAttributeCode() == 'artist')
                $artist_options[$artist_item->getOptionId()] = $artist_item->getValue();
        endforeach;

      $this->addColumn('artist',
            array(
                'header'=> Mage::helper('catalog')->__('Artist Name'),
                'width' => '80px',
                'index' => 'artist',
                 'type'  => 'options',
                'options' => $artist_options,
        ));

Then I render the Qty in Stock column:

 $this->addColumn('qty2', array(
            'header'    => Mage::helper('sales')->__('# in Stock'),
            'width'     => '80',
            'name'      => 'qty2',
            'index'     => 'qty2',

        ));

Once again we override the call to parent:: with the following

    // we call back up to our grandparent's prepare columns
        return Mage_Adminhtml_Block_Widget_Grid::_prepareColumns();

Note: by calling first our parent’s _prepareColumns and then our grandparent’s _prepareColumns, we are calling _prepareColumns in our grandparent twice. But the calling of that relatively efficient code twice seems a small price to pay for much more maintainable code for us. Your mileage may vary.

Note also that if you want to re-arrange your column’s positions relative to other columns, your best bet is to use Magento 1.4 (where they added addColumnAfter() ) Otherwise, look at the old revision of this page for more info on how to copy in all the code necessary to make this work.

The complete code is here. Remember, replace all the code that refers to “artist” as you will not have the necessary model, attribute, etc.

<?php

class Fws_Adminhtml_Block_Sales_Order_Create_Search_Grid extends Mage_Adminhtml_Block_Sales_Order_Create_Search_Grid//Mage_Adminhtml_Block_Widget_Grid
{
  public function __construct()
  {
       parent::__construct();
        $this->setId('fws_adminhtml_block_sales_order_create_search_grid');//
  }

  //protected function setCollection($collection)
public function setCollection($collection)
  {
        $collection->joinAttribute('artist','catalog_product/artist', 'entity_id', null,'left')
            ->addAttributeToFilter('type_id', array_keys(
                Mage::getConfig()->getNode('adminhtml/sales/order/create/available_product_types')->asArray()
            ))
              ->joinField('qty2',
                'cataloginventory/stock_item',
                'qty','product_id=entity_id','{{table}}.stock_id=1','left');
           parent::setCollection($collection);
    }

    protected function _prepareColumns()
    {
          parent::_prepareColumns();
       
        $artist_items = Mage::getModel('eav/entity_attribute_option')
            ->getCollection()
            ->setStoreFilter()
            ->join('attribute','attribute.attribute_id=main_table.attribute_id', 'attribute_code');
        foreach ($artist_items as $artist_item) :
            if ($artist_item->getAttributeCode() == 'artist')
                $artist_options[$artist_item->getOptionId()] = $artist_item->getValue();
        endforeach;

      $this->addColumnAfter('artist',
            array(
                'header'=> Mage::helper('catalog')->__('Artist Name'),
                'width' => '80px',
                'index' => 'artist',
                 'type'  => 'options',
                'options' => $artist_options,
        ), 'entity_id');
     $this->addColumnAfter('qty2', array(
            'header'    => Mage::helper('sales')->__('# in Stock'),
            'width'     => '80',
            'name'      => 'qty2',
            'index'     => 'qty2',

        ), 'total_shipping_amount');

    // we call back up to our grandparent's prepare columns
        return Mage_Adminhtml_Block_Widget_Grid::_prepareColumns();
       
    }
}

Then we need to add our own module declaration:

So, add a file Fws_Adminhtml.xml to magento/etc/modules with the following code

<?xml version="1.0"?>
<config>
    <Fws_Adminhtml>
             <active>true</active>
             <codePool>local</codePool>
    </Fws_Adminhtml>
</config>

Create your config file for your new module in the following location: magento/code/local/Fws/Adminhtml/etc/config.xml This is where the magic happens (you are telling Magento to replace the default search order grid with your own grid). Modify the lines below as appropriate to your module.

<?xml version="1.0"?>
<config>
        <modules>
                <Fws_Adminhtml>
                        <version>1.0</version>
                </Fws_Adminhtml>
        </modules>
        <global>
                <blocks>
                        <adminhtml>
                                <rewrite>
                                        <sales_order_create_search_grid>Fws_Adminhtml_Block_Sales_Order_Create_Search_Grid</sales_order_create_search_grid>
                                </rewrite>
                        </adminhtml>
                </blocks>
        </global>
</config>

You then need to clear your cache, x your fingers and try to create a new order from within admin - you should see a column “# in Stock” populated with stock quantity for each product.

Please chip in with corrections, improvements, etc.

acorncom and Eddie




 

Magento 2 GitHub Repository

Magento Job Board - Some sort of tag line goes here

Latest Posts| View all Jobs