How to show Sum of Two fields in Grid in Magento Admin Panel - magento

I am working on a extension in which user enter different price for " Stamp Cost, Ink Cost,
Form Cost ". currently in data grid i am showing value of one field
$this->addColumn('stamp_cost', array(
'header' => Mage::helper('imprint')->__('Stamp Cost'),
'width' => '100px',
'type' => 'price',
'currency_code' => $store->getBaseCurrency()->getCode(),
'index' => 'stamp_cost'
));
But Now I Need to show sum of all these fields in one column
How can we show sum of two fields in one column in magento admin data grid ?

Essentially, there are two ways to do it. Add the field to the collection and get the data from the database, or calculate it in PHP based on the 3 values returned from the DB. Doing the first way with the Magento Collection would, in my opinion, be too complex. instead, you want to use a Renderer (Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract)
First, inside of the Block/Adminhtml folder of your plugin, make a new folder called Renderer. Inside of it make a new file called CostSum.php with the following contents:
<?php
class Company_Module_Block_Adminhtml_Renderer_CostSum extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
public function render(Varien_Object $row)
{
return $row->getStampCost() + $row->getInkCost() + $row->getFormCost();
}
}
Then, in the grid, make a new column
$this->addColumn('cost_total', array(
'header' => Mage::helper('imprint')->__('Stamp Cost'),
//'index' => 'Im not sure this is necessary',
'type' => 'price',
'currency_code' => $store->getBaseCurrency()->getCode(),
'renderer' => new Company_Module_Block_Adminhtml_Renderer_CostSum()
));
Hope that helps!

The more right way is 'renderer' => 'company_module/adminhtml_renderer_costSum'
As #Zyava says, the correct option is this. But actually, is not 'company_module'. Instead you should call it as you have declared your blocks in the config.xml file.
<blocks>
<declaration>
<class>Company_Module_Block</class>
</declaration>
</blocks>
So, in this case you should create the 'renderer' as:
'renderer' => 'declaration/adminhtml_renderer_costSum'

Related

Add custom column to Magento report and sales dashboard

I've been searching for a module or a way to deal with the fallowing situation:
A customer orders a product that is 100$ and pays shipping of 10$. That would charge him a total amount of 110$. By the time the product arrives he notices that the product is a little scratched and instead of sending it back he accepts to receive a discount.
For this to happen properly I would make a credit memo with an adjustment refund of let's say 30$.
I need to see the total amount that remains after this operation is done (80$) in a separate column in either reports or the sales dashboard.
For this particular task we have also installed a module called "Advanced Orders Manager by Iksanika" but this appears to only get the data that already exists in the database and is not allowing us to use variable for let's say a substraction.
Also in Magento reports we use Reports > Sales > Orders but that gives us only the total figures and we cannot find anywhere a "total amount charged" that would give us the exact final figure (80$).
This is a particular request of the accounting dpt of an online store.
What you want to do is to add a custom grid column to the sales order grid.
Magento uses the database table sales_flat_order to fill the values in the sales order grid. Unfortunately the sales_flat_order table doesn't provide the information you need (grandtotal minus refunded amount) but both values separately (grand_total and total_refunded). Because of that you have multiple options:
Extend the table sales_flat_order.
Add a custom renderer for your custom sales order grid column.
As everything in this world both methods have advantages and disadvantages.
If you extend the sales_flat_order table you have to make sure the value of your new database column is set when creating new orders. On the other hand, as the value is persisted in your database, you can use the column for other extensions.
With a custom renderer you don't have to care about persistence. You have the opportunity to do operations and return your result which will be displayed in your custom sales order grid column. As we have both grand_total and total_refunded saved already you can return the grandtotal minus refunded amount.
I'll describe how to add a custom sales order grid column and add a custom renderer to return the value of grandtotal minus refund amount.
Part 1: How to add custom column to sales order grid in backend?
To add a custom column to sales order grid first add your own sales order grid block XX_ModuleName_Block_Adminhtml_Order_Grid.
Rewrite magentos *Mage_Adminhtml_Block_Sales_Order_Grid (app/code/core/Mage/Adminhtml/Block/Sales/Order/Grid.php) and extend it with your sales order grid.
To add your custom column override _prepareColumns() method. Inside the overwritten _prepareColumns() you want to first add the column from parent class. Finally, add your custom column:
note: you can download the example module.
$this->addColumn('my_column', array(
'header' => Mage::helper('sales')->__('My Column'),
'index' => 'my_column',
'type' => 'text',
'renderer' => 'XX_ModuleName_Block_Adminhtml_Order_Grid'
));
Example etc/config.xml:
<?xml version="1.0"?>
<config>
<modules>
<EG_AdminSalesOrder>
<version>1.0.0</version>
</EG_AdminSalesOrder>
</modules>
<global>
<blocks>
<eg_adminsalesorder>
<class>EG_AdminSalesOrder_Block</class>
</eg_adminsalesorder>
<adminhtml>
<rewrite>
<sales_order_grid>EG_AdminSalesOrder_Block_Adminhtml_Order_Grid</sales_order_grid>
</rewrite>
</adminhtml>
</blocks>
<helpers>
<eg_adminsalesorder>
<class>EG_AdminSalesOrder_Helper</class>
</eg_adminsalesorder>
</helpers>
</global>
</config>
Example custom sales order grid block:
class EG_AdminSalesOrder_Block_Adminhtml_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid
{
/**
* Add custom column to sales order grid
*
* #return Mage_Adminhtml_Block_Widget_Grid
* #throws Exception
*/
protected function _prepareColumns()
{
$this->addColumn('real_order_id', array(
'header'=> Mage::helper('sales')->__('Order #'),
'width' => '80px',
'type' => 'text',
'index' => 'increment_id',
));
if (!Mage::app()->isSingleStoreMode()) {
$this->addColumn('store_id', array(
'header' => Mage::helper('sales')->__('Purchased From (Store)'),
'index' => 'store_id',
'type' => 'store',
'store_view'=> true,
'display_deleted' => true,
));
}
$this->addColumn('created_at', array(
'header' => Mage::helper('sales')->__('Purchased On'),
'index' => 'created_at',
'type' => 'datetime',
'width' => '100px',
));
$this->addColumn('billing_name', array(
'header' => Mage::helper('sales')->__('Bill to Name'),
'index' => 'billing_name',
));
$this->addColumn('shipping_name', array(
'header' => Mage::helper('sales')->__('Ship to Name'),
'index' => 'shipping_name',
));
$this->addColumn('base_grand_total', array(
'header' => Mage::helper('sales')->__('G.T. (Base)'),
'index' => 'base_grand_total',
'type' => 'currency',
'currency' => 'base_currency_code',
));
$this->addColumn('grand_total', array(
'header' => Mage::helper('sales')->__('G.T. (Purchased)'),
'index' => 'grand_total',
'type' => 'currency',
'currency' => 'order_currency_code',
));
$this->addColumn('refunded', array(
'header' => Mage::helper('sales')->__('Total - Refund'),
'index' => 'refunded',
'type' => 'text',
'renderer' => 'EG_AdminSalesOrder_Block_Adminhtml_Sales_Order_Grid_Widget_Renderer_Refunded'
));
parent::_prepareColumns();
}
}
Part 2: How to add a custom renderer for my custom column?
Now you can add your custom renderer to fill the values into your custom sales order grid column.
First add a cusom renderer class XX_ModuleName_Block_Adminhtml_Sales_Order_Grid_Widget_Renderer_MyColumn.
Then extend Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract.
Override the render(Varien_Object $row) method. Here you can do your specific operation and return the string that should be displayed in your grid. In your case you want to load the order collection for the current $row param, get the total refunded amount, subtract the grandtotal with the refunded amount and return the value.
Example custom renderer block:
class EG_AdminSalesOrder_Block_Adminhtml_Sales_Order_Grid_Widget_Renderer_Refunded
extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
/**
* #param Varien_Object $row
* #return string
*/
public function render(Varien_Object $row)
{
$currentOrderId = $row->getId();
$currentOrderGrandTotal = $row->getGrandTotal();
$orderCollection = Mage::getModel('sales/order')->getCollection();
$orderCollection->addFieldToSelect('total_refunded');
$orderCollection->addFieldToFilter('entity_id', array('eq' => $currentOrderId));
$orderCollectionItem = $orderCollection->getFirstItem();
$refundedAmount = $orderCollectionItem->getTotalRefunded();
$grandTotalWithoutRefundedAmount = (float)$currentOrderGrandTotal - (float)$refundedAmount;
$grandTotalWithoutRefundedAmount = Mage::helper('core')->currency($grandTotalWithoutRefundedAmount);
return (string)$grandTotalWithoutRefundedAmount;
}
}
You can download the example module.

Magento: Add Custom Attribute to Order Grid

I have a custom attribute in my product that i want it to appears in the orders grid, the attribute is added to mg_catalog_product_flat_1 table but when i try to make the above join i get an error, all other built in attributes like name, sku works fine so how can i get this done
Please check my code below
$collection->join(
'sales/order_item',
'`sales/order_item`.order_id=`main_table`.entity_id',
array(
'Productid' => new Zend_Db_Expr('group_concat(`sales/order_item`.product_id SEPARATOR ",")'),
//'manufacturer' => new Zend_Db_Expr('group_concat(`sales/order_item`.manufacturer_value SEPARATOR ",")'),
'name' => new Zend_Db_Expr('group_concat(`sales/order_item`.name SEPARATOR ",")'),
)
);
$collection->getSelect()->group('main_table.entity_id');
parent::setCollection($collection);
$this->addColumn('manufacturer', array(
'header' => Mage::helper('sales')->__('manufacturer'),
'width' => '100px',
'index' => 'manufacturer',
'type' => 'text',
));
If i uncomment manufacturer part i get an error a
An item is not the equivalent of a product. If you want to get attribute of a product in an item, you need to call the $item->getProduct() function to be able to get all the attributes of the product that are not defined in the item.
Then, you need to apply it to your collection. To do that, you can use the function walk of the collection object to apply a function on each element. The problem, in my opinion, is that you need to loop over you collection of order and then on the collection of items to get the attribute you need.
Another solution is to follow the recommandation of custom prdoduct's attribute to quote/order item. This mean the attribute will be added to all items all the time but will be avaiable like sku...
Hope it helps,

Magento Admin formfield multiselect selected

I´m currently developing a custom module for magento thats going to list employees.
I have figured out almost everything. The only thing I got left is how the selected values is going to be highlighted.
The problem I´m having is for the backend.
I got 2 tabs per employee, one for employee data and one tab for magento categories.
1 employee can have 1 or more categories.
The database table that the categories are stored in are a non-eav table.
So my question is
What in a multiselect determines which values are selected? As it is now, only one value is selected.
I think you can do this by simply passing in an array of the id's to be selected into the 'value' attribute of the field being added for the multiselect in the _prepareForm() method. Something like the following.
$fieldset->addField('category_id', 'multiselect', array(
'name' => 'categories[]',
'label' => Mage::helper('cms')->__('Store View'),
'title' => Mage::helper('cms')->__('Store View'),
'required' => true,
'values' => Mage::getSingleton('mymodule/mymodel')->getMymodelValuesForForm(),
'value' => array(1,7,10),
));
The id of the form element (e.g. category_id) must not be an attribute in your model, otherwise when the form values get set with $form->setValues() later on, the attribute value will be overwritten.
I normally store multiple selections as a text column separated by commas much like most magento modules handles stores which requires a slightly different approach as shown below.
In the form block for the tab with the multiselect, you firstly define the element to be displayed like so in the _prepareForm() method. You then get the values from the model and set put them into the form data.
protected function _prepareForm()
{
...
$fieldset->addField('store_id', 'multiselect', array(
'name' => 'stores[]',
'label' => Mage::helper('cms')->__('Store View'),
'title' => Mage::helper('cms')->__('Store View'),
'required' => true,
'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, true),
));
...
if ( Mage::getSingleton('adminhtml/session')->getMymodelData() )
{
$data = Mage::getSingleton('adminhtml/session')->getMymodelData();
} elseif ( Mage::registry('mymodel_data') ) {
$data = Mage::registry('mymodel_data')->getData();
}
$data['store_id'] = isset($data['stores']) ? explode(',', $data['stores']) : array();
$form->setValues($data);
}
I normally store the selected stores (categories as in your case) in the main model as a text column and comma separated values of ids, hence the explode.
In the controller for for the edit action, I put the model being edited into the mage registry so we can load it and it's values in the step above.
Mage::register('mymodel_data', $model);
Thanks for answering.
This is how my field looks like:
$fieldset->addField('npn_CatID', 'multiselect', array(
'label' => Mage::helper('employeelist')->__('Kategori'),
'class' => 'required-entry',
'required' => true,
'name' => 'npn_CatID',
'values' => $data,
'value' => array(3,5)
));
npn_CatID is the value in my db where the category id is saved.
I have tried to change the name and field ID but cant get it working.
When its the field id is like above ONE value is selected and its the last one inserted for the chosen employee
My data array looks likes
array(array('value' => '1', 'label' => 'USB'), array('value' => '2', 'label' => 'Memories'))

Adding custom columns in order grid (Magento 1.7.0.0)

I'm having this problem with adding custom columns in the order grid in Magento 1.7.0.0 and I was hoping you'd be able to give me a hand in here.
Basically I followed this guide http://www.atwix.com/magento/customize-orders-grid/ which explained I had to make a local version of /app/code/core/Mage/Adminhtml/Block/Sales/Order/Grid.php and make a couple of changes to have the extra columns I want. By following said guide, it said that I had to edit the function _prepareCollection() to add this line (specifying the fields I want to extract in the array)
$collection->getSelect()->join('magento_sales_flat_order_address', 'main_table.entity_id = magento_sales_flat_order_address.parent_id',array('telephone', 'email'));
Before
return parent::_prepareCollection();
And add the two columns in _prepareColumns() like this:
$this->addColumn('telephone', array(
'header' => Mage::helper('sales')->__('Telephone'),
'index' => 'telephone',
));
$this->addColumn('email', array(
'header' => Mage::helper('sales')->__('Email'),
'index' => 'email',
));
And that was it, apparently... Or maybe not, since it throws the following error when I do that:
Item (Mage_Sales_Model_Order) with the same id "XXXX" already exist
To which the solution, according to the comments underneath, was to add the following line in _prepareCollection before $this->setCollection($collection):
$collection->getSelect()->group('main_table.entity_id');
After adding the line, the Order Grid now shows the Email and Phone columns just like I want it, but turns out the pagination stopped working, it only shows the most recent 20 and it says "Pages 1 out of 1", "2 records found" on top. I can't seem to figure out why this is happening and every comment I see around doesn't go beyond the last instruction above. What could possibly be the cause of this issue?
I assume it could be replicated since I haven't made any other modifications of this model.
Alright, solved it. This is what I did:
Inspired by this answer https://stackoverflow.com/a/4219386/2009617, I made a copy of the file lib/Varien/Data/Collection/Db.php, placed it under app/core/local/Varien/Data/Collection/Db.php and copied the modifications suggested on that answer to fix the group select count error that was giving me problems above. So far it seemed to work.
However, there was a problem in the rows, when I clicked on the orders it said the Order "no longer exists", so I checked the actual url and turns out the order_id in the url was the same as the "entity_id" in the order_address table, which didn't correspond with the actual associative id of the order (parent_id). After tweaking for a long time with the MySQL query, I realized the issue was in the functions called by the _prepareColumns() and getRowUrl() functions in the /app/code/local/Mage/Adminhtml/Block/Sales/Order/Grid.php I made, since they were retrieving the wrong Id. So I made the following changes:
In _prepareColumns(), within the code corresponding to the Action column, I changed the 'getter' to 'getParentId', like this:
if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/view')) {
$this->addColumn('action',
array(
'header' => Mage::helper('sales')->__('Action'),
'width' => '50px',
'type' => 'action',
//~ 'getter' => 'getId',
'getter' => 'getParentId',
'actions' => array(
array(
'caption' => Mage::helper('sales')->__('View'),
'url' => array('base'=>'*/sales_order/view'),
'field' => 'order_id',
)
),
'filter' => false,
'sortable' => false,
'index' => 'stores',
'is_system' => true,
));
}
And in the getRowUrl() function, I changed the $row statement within the getUrl() function like this:
public function getRowUrl($row)
{
if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/view')) {
//~ return $this->getUrl('*/sales_order/view', array('order_id' => $row->getId()));
return $this->getUrl('*/sales_order/view', array('order_id' => $row->getParentId()));
}
return false;
}
And now it works like a charm. I hope this helps somebody else.
The problem is in query. Instead of this query:
$collection->getSelect()->join('magento_sales_flat_order_address', 'main_table.entity_id = magento_sales_flat_order_address.parent_id',array('telephone', 'email'));
You should use this:
$collection->getSelect()->join('sales_flat_order_address', 'main_table.entity_id = sales_flat_order_address.parent_id AND sales_flat_order_address.address_type = "shipping" ',array('telephone', 'email'));
In the table sales_flat_order_address, parent_id is duplicated. The first is for billing and the second one is for shipping. So you just need to select one of this: billing or shipping. This values are in column address_type...
Try using filter_index in the addColumn function:
$this->addColumn('telephone', array(
'header' => Mage::helper('sales')->__('Telephone'),
'index' => 'telephone',
'filter_index' => 'tablename.telephone'
));
You can find out the table name with printing out the sql query:
var_dump((string)$collection->getSelect())

Adding Stock Status column to Manage Product Admin Page

I'm trying to add 'stock status' column to the Admin Manage Product Grid.
Stock status is either "In Stock" or "Out of Stock".
Seems like I need to edit Adminhtml/Block/Catalog/Product/Grid.php 's _prepareColumns().
I added this line
$this->addColumn('stock',
array(
'header'=> Mage::helper('catalog')->__('Stock Avail.'),
'width' => '70px',
'index' => 'status',
'type' => 'options',
'options' => Mage::getSingleton('cataloginventory/source_stock')->toOptionArray()
which just prints out Array,Array.
I'm guessing it's just printing out the type, so I would need to access the array value to get options. Am I on the right path? I can't find any good coding docs for magento, if anyone can share with me how they figured out magento, that would be really nice.
You should use a renderer: in the array of the addColumn, add:
'renderer' => 'YourNamespace_YourModule_Path_To_Renderer_File',
And the renderer file would be something like:
class YourNamespace_YourModule_Path_To_Renderer_File extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
public function render(Varien_Object $row)
{
//let's see what you have to work with
Zend_Debug::dump($row->getData(), 'debug');
$stockStatus = $row->getSomething();
return $stockStatus;
}
}
Let me know if that ain't clear

Resources