22

Most Magento Report building forums, blogs, tutorials, etc all seem to focus on taking an existing Magento Report and either copying or extending it. Most of these are grids which link to a specific dataset and all of them include standard filters i.e. from/to date & period (plus extra filters on some reports).

However, there seems to be very little information out there about how to create a completely custom report with custom filters.

For instance, a customer would like a report with two custom filters which reports back on just two simple aggregated metrics.

2
  • 1
    Just a reference for resources: stackoverflow.com/questions/7030255/…
    – B00MER
    Commented Feb 10, 2014 at 17:25
  • even for me to showing same blank page, please suggest what to do.
    – user42146
    Commented Jul 14, 2016 at 13:36

2 Answers 2

23

First of all, you need to generate a custom module, create the following files:

/app/etc/modules/Mycompany_Mymodule.xml
/app/design/adminhtml/default/default/layout/mymodule.xml
/app/code/local/Mycompany/Mymodule/Block/Adminhtml/Mymodule/Grid.php
/app/code/local/Mycompany/Mymodule/Block/Adminhtml/Mymodule.php
/app/code/local/Mycompany/Mymodule/Block/Mymodule.php
/app/code/local/Mycompany/Mymodule/controllers/Adminhtml/MymoduleController.php
/app/code/local/Mycompany/Mymodule/etc/config.xml
/app/code/local/Mycompany/Mymodule/Helper/Data.php
/app/code/local/Mycompany/Mymodule/Model/Mymodule.php

Define your module on /app/etc/modules/Mycompany_Mymodule.xml:

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

Complete the layout file which will update the admin view (I always do this first because I don't want to forget it). /app/design/adminhtml/default/default/layout/mymodule.xml

<?xml version="1.0"?>
<layout version="0.1.0">
    <mymodule_adminhtml_mymodule_index>
        <reference name="content">
            <block type="mymodule/adminhtml_mymodule" name="mymodule" />
        </reference>
    </mymodule_adminhtml_mymodule_index>
</layout>

Create the config file with this content /app/code/local/Mycompany/Mymodule/etc/config.xml:

<?xml version="1.0"?>
<!-- 
/**
 * @category   Mycompany
 * @package    Mycompany_Mymodule
 * @author     Damian Alberto Pastorini
 */
 -->
<config>
    <modules>
        <Mycompany_Mymodule>
            <version>0.1.0</version>
        </Mycompany_Mymodule>
    </modules>
    <admin>
        <routers>
            <mymodule>
                <use>admin</use>
                <args>
                    <module>Mycompany_Mymodule</module>
                    <frontName>mymodule</frontName>
                </args>
            </mymodule>
        </routers>
    </admin>
    <adminhtml>
        <menu>
            <report>
                <children>
                    <mymodule translate="title" module="mymodule">
                        <title>Mymodule Report</title>
                        <action>mymodule/adminhtml_mymodule</action>
                    </mymodule>
                </children>
            </report>
        </menu>
        <acl>
            <resources>
                <all>
                    <title>Allow Everything</title>
                </all>
                <admin>
                    <children>
                        <report>
                            <children>
                                <mymodule translate="title" module="mymodule">
                                    <title>Mymodule Report</title>
                                    <action>mymodule/adminhtml_mymodule</action>
                                </mymodule>
                            </children>
                        </report>
                    </children>
                </admin>
            </resources>
        </acl>
        <layout>
            <updates>
                <mymodule>
                    <file>mymodule.xml</file>
                </mymodule>
            </updates>
        </layout>
    </adminhtml>
    <global>
        <models>
            <mymodule>
                <class>Mycompany_Mymodule_Model</class>
                <resourceModel>mymodule</resourceModel>
            </mymodule>
        </models>
        <resources>
            <mymodule_setup>
                <setup>
                    <module>Mycompany_Mymodule</module>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </mymodule_setup>
            <mymodule_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </mymodule_write>
            <mymodule_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </mymodule_read>
        </resources>
        <blocks>
            <mymodule>
                <class>Mycompany_Mymodule_Block</class>
            </mymodule>
        </blocks>
        <helpers>
            <mymodule>
                <class>Mycompany_Mymodule_Helper</class>
            </mymodule>
        </helpers>
    </global>
</config>

Here we define the controller, the menu access and permissions, the model, the blocks and the helper.

Create the grid and specify all the columns /app/code/local/Mycompany/Mymodule/Block/Adminhtml/Mymodule/Grid.php:

<?php
class Mycompany_Mymodule_Block_Adminhtml_Mymodule_Grid extends Mage_Adminhtml_Block_Report_Grid {

  public function __construct() {
    parent::__construct();
    $this->setId('mymoduleGrid');
    $this->setDefaultSort('created_at');
    $this->setDefaultDir('ASC');
    $this->setSaveParametersInSession(true);
    $this->setSubReportSize(false);
  }

  protected function _prepareCollection() {
    parent::_prepareCollection();
    $this->getCollection()->initReport('mymodule/mymodule');
    return $this;
  }

  protected function _prepareColumns() {
    $this->addColumn('ordered_qty', array(
        'header'    =>Mage::helper('reports')->__('Quantity Ordered'),
        'align'     =>'right',
        'index'     =>'ordered_qty',
        'total'     =>'sum',
        'type'      =>'number'
    ));
    $this->addColumn('item_id', array(
        'header' => Mage::helper('mymodule')->__('Item ID'),
        'align' => 'right',
        'index' => 'item_id',
        'type'  => 'number',
        'total' => 'sum',
    ));
    $this->addExportType('*/*/exportCsv', Mage::helper('mymodule')->__('CSV'));
    $this->addExportType('*/*/exportXml', Mage::helper('mymodule')->__('XML'));
    return parent::_prepareColumns();
  }

  public function getRowUrl($row) {
    return false;
  }

  public function getReport($from, $to) {
    if ($from == '') {
        $from = $this->getFilter('report_from');
    }
    if ($to == '') {
        $to = $this->getFilter('report_to');
    }
    $totalObj = Mage::getModel('reports/totals');
    $totals = $totalObj->countTotals($this, $from, $to);
    $this->setTotals($totals);
    $this->addGrandTotals($totals);
    return $this->getCollection()->getReport($from, $to);
  }
}

This file is clearest but I give you some tips about specific lines:

// this line indicates the model to use for get the data. 
$this->getCollection()->initReport('mymodule/mymodule');
// it's used to indicate that this field must be totalized at the end. 
'total' =>'sum',
// this is executed when you click on the rows grid, in case you return false (like the example) nothing will happen when you click on the rows grid. 
public function getRowUrl($row) {

For the next step, create the grid container block /app/code/local/Mycompany/Mymodule/Block/Adminhtml/Mymodule.php:

<?php
class Mycompany_Mymodule_Block_Adminhtml_Mymodule extends Mage_Adminhtml_Block_Widget_Grid_Container {

  public function __construct() {
    $this->_controller = 'adminhtml_mymodule';
    $this->_blockGroup = 'mymodule';
    $this->_headerText = Mage::helper('mymodule')->__('Mymodule Report');
    parent::__construct();
    $this->_removeButton('add');
  }
}

Here we add this line to remove the add button: // This must be always after the parent::__construct(); line. $this->_removeButton('add');

Create the block container /app/code/local/Mycompany/Mymodule/Block/Mymodule.php:

<?php
class Mycompany_Mymodule_Block_Mymodule extends Mage_Core_Block_Template {

  public function _prepareLayout() {
    return parent::_prepareLayout();
  }

  public function getMymodule() {
    if (!$this->hasData('mymodule')) {
        $this->setData('mymodule', Mage::registry('mymodule'));
    }
    return $this->getData('mymodule');
  } 
}

Create the controller /app/code/local/Mycompany/Mymodule/controllers/Adminhtml/MymoduleController.php:

<?php

class Mycompany_Mymodule_Adminhtml_MymoduleController extends Mage_Adminhtml_Controller_Action {

  protected function _initAction() {
    $this->loadLayout();
    return $this;
  }

  public function indexAction() {
    $this->_initAction()
           ->renderLayout();
  }

  public function exportCsvAction() {
    $fileName = 'mymodule.csv';
    $content = $this->getLayout()->createBlock('mymodule/adminhtml_mymodule_grid')
                    ->getCsv();
    $this->_sendUploadResponse($fileName, $content);
  }

  public function exportXmlAction() {
    $fileName = 'mymodule.xml';
    $content = $this->getLayout()->createBlock('mymodule/adminhtml_mymodule_grid')
                    ->getXml();
    $this->_sendUploadResponse($fileName, $content);
  }

  protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream') {
    $response = $this->getResponse();
    $response->setHeader('HTTP/1.1 200 OK', '');
    $response->setHeader('Pragma', 'public', true);
    $response->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true);
    $response->setHeader('Content-Disposition', 'attachment; filename=' . $fileName);
    $response->setHeader('Last-Modified', date('r'));
    $response->setHeader('Accept-Ranges', 'bytes');
    $response->setHeader('Content-Length', strlen($content));
    $response->setHeader('Content-type', $contentType);
    $response->setBody($content);
    $response->sendResponse();
    die;
  }
}

Then the empty helper /app/code/local/Mycompany/Mymodule/Helper/Data.php:

<?php
class Mycompany_Mymodule_Helper_Data extends Mage_Core_Helper_Abstract
{

}

And for the last we create the model that will bring the data /app/code/local/Mycompany/Mymodule/Model/Mymodule.php:

 <?php
 class Mycompany_Mymodule_Model_Mymodule extends Mage_Reports_Model_Mysql4_Order_Collection
{
   function __construct() {
     parent::__construct();
     $this->setResourceModel('sales/order_item');
     $this->_init('sales/order_item','item_id');
   }
 
   public function setDateRange($from, $to) {
      $this->_reset();
      $this->getSelect()
             ->joinInner(array(
                 'i' => $this->getTable('sales/order_item')),
                 'i.order_id = main_table.entity_id'
                 )
             ->where('i.parent_item_id is null')
             ->where("i.created_at BETWEEN '".$from."' AND '".$to."'")
             ->where('main_table.state = \'complete\'')
             ->columns(array('ordered_qty' => 'count(distinct `main_table`.`entity_id`)'));
        // uncomment next line to get the query log:
        // Mage::log('SQL: '.$this->getSelect()->__toString());
      return $this;
   }
 
   public function setStoreIds($storeIds)
   {
      return $this;
   }
}
?>

This is a custom model that get the data from Magento core models, here you can define any model or if you already got your own DB/tables you can get the report data from it. // this line reset the original query that comes by default. $this->_reset();

I tried to add all these files but once I click on the new menu item of the report a blank page appears.

7
  • 1
    It's showing blank page. Any idea to solve this?
    – 502_Geek
    Commented May 9, 2016 at 8:36
  • this cpomes up with a blank page any updates? Commented Jun 28, 2017 at 17:38
  • Just put in an edit and realised I'm an idiot! Please don't accept it :)
    – Wildcard27
    Commented Jul 8, 2017 at 23:43
  • Anyone solved this blank page issue ? Commented Feb 10, 2018 at 18:20
  • i wan to generate sales order item report what change i have to do ? Commented Jul 26, 2018 at 10:42
1

Just Rename the folder adminhtml to Adminhtml as per below path:

app/code/local/Mycompany/Mymodule/Block/adminhtml/Mymodule.php

Not the answer you're looking for? Browse other questions tagged or ask your own question.