Override Admin Sales Order Search Grid

Last modified by acorncom on Tue, November 9, 2010 18:48
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 in the _prepareCollection() method:

protected function _prepareCollection()
    {
        $collection = Mage::getModel('catalog/product')->getCollection()
            ->setStore($this->getStore())
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('sku')
            ->addAttributeToSelect('price')
             ->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')
            ->addStoreFilter();

        if($this->helper('giftmessage/message')->getIsMessagesAvailable(
            'main', $this->getQuote(), $this->getStore()
        )) {
            $collection->addAttributeToSelect('gift_message_available');
        }

        Mage::getSingleton('catalog/product_status')->addSaleableFilterToCollection($collection);
        /**
         * need display all simple products
         */
        //Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);

        $this->setCollection($collection);
        if ($this->getCollection()) {

            $this->_preparePage();

           $columnId = $this->getParam($this->getVarNameSort(), $this->_defaultSort);
           $dir      = $this->getParam($this->getVarNameDir(), $this->_defaultDir);
           $filter   = $this->getParam($this->getVarNameFilter(), null);

            if (is_null($filter)) {
                $filter = $this->_defaultFilter;
            }


            if (is_string($filter)) {
                $data = array();
                $filter = base64_decode($filter);
                parse_str(urldecode($filter), $data);
                $this->_setFilterValues($data);
            } else if ($filter && is_array($filter)) {
                $this->_setFilterValues($filter);
            } else if(0 !== sizeof($this->_defaultFilter)) {
                $this->_setFilterValues($this->_defaultFilter);
            }

            if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
                $dir = (strtolower($dir)=='desc') ? 'desc' : 'asc';
                $this->_columns[$columnId]->setDir($dir);
                $column = $this->_columns[$columnId]->getFilterIndex() ?
                    $this->_columns[$columnId]->getFilterIndex() : $this->_columns[$columnId]->getIndex();
                $this->getCollection()->setOrder($column , $dir);
            }

            $this->getCollection()->load();
            $this->_afterLoadCollection();
        }

        //return parent::_prepareCollection();
        $this->getCollection()->addWebsiteNamesToResult();
        return $this;
        
    }

There are 3 amendments to the original code here

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.

c)I substitute “return parent::_prepareCollection();” for the following

Mage_Adminhtml_Block_Widget_Grid::_prepareCollection(); 

If I’d have left it to “parent::_prepareCollection();” then my additional database selects/joins may have been ignored (can Varian confirm this?).

The next code block that needs amending is protected function _prepareColumns(), where you render your columns:

Here I populate a drop down of artist names & then render the artist column:

$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

if ($this->getCollection()) {
        $this->_preparePage();

            $columnId = $this->getParam($this->getVarNameSort(), $this->_defaultSort);
            $dir      = $this->getParam($this->getVarNameDir(), $this->_defaultDir);
            $filter   = $this->getParam($this->getVarNameFilter(), null);

            if (is_null($filter)) {
                $filter = $this->_defaultFilter;
            }

            if (is_string($filter)) {
                $data = array();
                $filter = base64_decode($filter);
                parse_str(urldecode($filter), $data);
                $this->_setFilterValues($data);
            } else if ($filter && is_array($filter)) {
                $this->_setFilterValues($filter);
            } else if(0 !== sizeof($this->_defaultFilter)) {
                $this->_setFilterValues($this->_defaultFilter);
            }

            if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
                $dir = (strtolower($dir)=='desc') ? 'desc' : 'asc';
                $this->_columns[$columnId]->setDir($dir);
                $column = $this->_columns[$columnId]->getFilterIndex() ?
                    $this->_columns[$columnId]->getFilterIndex() : $this->_columns[$columnId]->getIndex();
                $this->getCollection()->setOrder($column , $dir);
            }

            $this->getCollection()->load();
            $this->_afterLoadCollection();
        } 

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');//
        $this->setRowClickCallback('order.productGridRowClick.bind(order)');
        $this->setCheckboxCheckCallback('order.productGridCheckboxCheck.bind(order)');
        $this->setRowInitCallback('order.productGridRowInit.bind(order)');
        $this->setDefaultSort('entity_id');
        $this->setUseAjax(true);
        if ($this->getRequest()->getParam('collapse')) {
            $this->setIsCollapsed(true);
        }

  }
   public function getStore()
    {
        return Mage::getSingleton('adminhtml/session_quote')->getStore();
    }
    /**
     * Retrieve quote object
     * @return Mage_Sales_Model_Quote
     */
    public function getQuote()
    {
        return Mage::getSingleton('adminhtml/session_quote')->getQuote();
    }

    protected function _addColumnFilterToCollection($column)
    {
        // Set custom filter for in product flag
        if ($column->getId() == 'in_products') {
            $productIds = $this->_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('entity_id', array('in'=>$productIds));
            } else {
                if($productIds) {
                    $this->getCollection()->addFieldToFilter('entity_id', array('nin'=>$productIds));
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }



  protected function _prepareCollection()
    {
        $collection = Mage::getModel('catalog/product')->getCollection()
            ->setStore($this->getStore())
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('sku')
            ->addAttributeToSelect('price')
             ->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')
            ->addStoreFilter();

        if($this->helper('giftmessage/message')->getIsMessagesAvailable(
            'main', $this->getQuote(), $this->getStore()
        )) {
            $collection->addAttributeToSelect('gift_message_available');
        }

        Mage::getSingleton('catalog/product_status')->addSaleableFilterToCollection($collection);
        /**
         * need display all simple products
         */
        //Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);

        $this->setCollection($collection);
        if ($this->getCollection()) {

            $this->_preparePage();

           $columnId = $this->getParam($this->getVarNameSort(), $this->_defaultSort);
           $dir      = $this->getParam($this->getVarNameDir(), $this->_defaultDir);
           $filter   = $this->getParam($this->getVarNameFilter(), null);

            if (is_null($filter)) {
                $filter = $this->_defaultFilter;
            }


            if (is_string($filter)) {
                $data = array();
                $filter = base64_decode($filter);
                parse_str(urldecode($filter), $data);
                $this->_setFilterValues($data);
            } else if ($filter && is_array($filter)) {
                $this->_setFilterValues($filter);
            } else if(0 !== sizeof($this->_defaultFilter)) {
                $this->_setFilterValues($this->_defaultFilter);
            }

            if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
                $dir = (strtolower($dir)=='desc') ? 'desc' : 'asc';
                $this->_columns[$columnId]->setDir($dir);
                $column = $this->_columns[$columnId]->getFilterIndex() ?
                    $this->_columns[$columnId]->getFilterIndex() : $this->_columns[$columnId]->getIndex();
                $this->getCollection()->setOrder($column , $dir);
            }

            $this->getCollection()->load();
            $this->_afterLoadCollection();
        }

        //return parent::_prepareCollection();
        $this->getCollection()->addWebsiteNamesToResult();
        return $this;
        
    }

    protected function _prepareColumns()
    {
        $this->addColumn('entity_id', array(
            'header'    => Mage::helper('sales')->__('ID'),
            'sortable'  => true,
            'width'     => '60',
            'index'     => 'entity_id'
        ));
       
       $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,
        ));
       $this->addColumn('name', array(
            'header'    => Mage::helper('sales')->__('Product Name'),
             'width'     => '200',
            'index'     => 'name'
        ));
        $this->addColumn('sku', array(
            'header'    => Mage::helper('sales')->__('Stock #'),
            'width'     => '80',
            'index'     => 'sku'
        ));
              $this->addColumn('price', array(
            'header'    => Mage::helper('sales')->__('Price'),
            'align'     => 'center',
            'type'      => 'currency',
            'currency_code' => $this->getStore()->getCurrentCurrencyCode(),
            'rate'      => $this->getStore()->getBaseCurrency()->getRate($this->getStore()->getCurrentCurrencyCode()),
            'index'     => 'price'
        ));

        $this->addColumn('in_products', array(
            'header_css_class' => 'a-center',
            'type'      => 'checkbox',
            'name'      => 'in_products',
            'values'    => $this->_getSelectedProducts(),
            'align'     => 'center',
            'index'     => 'entity_id',
        ));

        if($this->helper('giftmessage/message')->getIsMessagesAvailable(
            'main', $this->getQuote(), $this->getStore()
        )) {
            $this->addColumn('giftmessage', array(
                'filter'    => false,
                'sortable'  => false,
                'header'    => Mage::helper('sales')->__('Gift'),
                'renderer'  => 'adminhtml/sales_order_create_search_grid_renderer_giftmessage',
                'field_name'=> 'giftmessage',
                'inline_css'=> 'checkbox',
                'align'     => 'center',
                'index'     => 'entity_id',
                'values'    => $this->_getGiftmessageSaveModel()->getAllowQuoteItemsProducts(),
                'width'     => '1',
            ));
        }
     $this->addColumn('qty2', array(
            'header'    => Mage::helper('sales')->__('# in Stock'),
            'width'     => '80',
            'name'      => 'qty2',
            'index'     => 'qty2',

        ));



        $this->addColumn('qty', array(
            'filter'    => false,
            'sortable'  => false,
            'header'    => Mage::helper('sales')->__('# To Add'),
            'name'        => 'qty',
            'inline_css'=> 'qty',
            'align'     => 'right',
            'type'      => 'input',
            'validate_class' => 'validate-number',
            'index'     => 'qty',
            'width'     => '1',
        ));


      // return parent::_prepareColumns();
      if ($this->getCollection()) {
        $this->_preparePage();

            $columnId = $this->getParam($this->getVarNameSort(), $this->_defaultSort);
            $dir      = $this->getParam($this->getVarNameDir(), $this->_defaultDir);
            $filter   = $this->getParam($this->getVarNameFilter(), null);

            if (is_null($filter)) {
                $filter = $this->_defaultFilter;
            }

            if (is_string($filter)) {
                $data = array();
                $filter = base64_decode($filter);
                parse_str(urldecode($filter), $data);
                $this->_setFilterValues($data);
            } else if ($filter && is_array($filter)) {
                $this->_setFilterValues($filter);
            } else if(0 !== sizeof($this->_defaultFilter)) {
                $this->_setFilterValues($this->_defaultFilter);
            }

            if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
                $dir = (strtolower($dir)=='desc') ? 'desc' : 'asc';
                $this->_columns[$columnId]->setDir($dir);
                $column = $this->_columns[$columnId]->getFilterIndex() ?
                    $this->_columns[$columnId]->getFilterIndex() : $this->_columns[$columnId]->getIndex();
                $this->getCollection()->setOrder($column , $dir);
            }

            $this->getCollection()->load();
            $this->_afterLoadCollection();
        } 
        
       
    }
     public function getGridUrl()
    {
        return $this->getUrl('*/*/loadBlock', array('block'=>'search_grid', '_current' => true, 'collapse' => null));
    }

    protected function _getSelectedProducts()
    {
        $products = $this->getRequest()->getPost('products', array());

        return $products;
    }

    /**
     * Retrieve gift message save model
     *
     * @return Mage_Adminhtml_Model_Giftmessage_Save
     */
    protected function _getGiftmessageSaveModel()
    {
        return Mage::getSingleton('adminhtml/giftmessage_save');
    }

}

Then we need to add our own module declaration:

So, add a file Fws_All.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>

The final file to amend is magento/etc/local.xml. Here you are informing mage to use your own search order grid for the default. Add the following

<blocks> <adminhtml> <rewrite> <sales_order_create_search_grid> Fws_Adminhtml_Block_Sales_Order_Create_Search_Grid </sales_order_create_search_grid> </rewrite> </adminhtml> </blocks>

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.

Eddie




 

Magento 2 GitHub Repository

Magento Job Board - Some sort of tag line goes here

Latest Posts| View all Jobs