I want to add total at the end of Magento grid, so i use getTotals function. This function working fine for all the column. But some column has renderer, in that case i am not getting totals for renderer column, Please give any idea, how can i achieve this? For calcification, Please see the attach image:
Set a getTotals function in your Grid.php
public function getTotals()
{
$totals = new Varien_Object();
$fields = array(
'subtotal' => 0, //actual column index, see _prepareColumns()
'productargin' => 0
);
foreach ($this->getCollection() as $item) {
foreach($fields as $field=>$value){
$fields[$field]+=$item->getData($field);
}
}
//First column in the grid
$fields['entity_id']='Totals';
$totals->setData($fields);
return $totals;
}
Related
I want to add a custom field in Attribute option in Manage Attribute Options menu in admin. Like value column beside the position column in admin. I have attached an image.
What I have done ... (Magento 1.8)
created a new field in eav_attribute_option table named value after sort_order filed.
changed magento\app\design\adminhtml\default\default\template\eav\attribute\options.phtml this file to show the Value column beside the Position column.
changed getOptionValues() method in this file magento\app\code\core\Mage\Eav\Block\Adminhtml\Attribute\Edit\Options\Abstract.php to get data for my custom value column from database and show in admin side. It shows the default value of db in admin form.
But when I want to save from admin panel the data doesn’t save in db.
I've been trying to find the model or controller that actually handles writing into the database to make sure my new field saves too.
Any help would be appreciated.
(I'd post an image to make you understand, but I can't since I need 10 points to be able to do it.)
Got it!
Update: Mage/Eav/Model/Resource/Entity/Attribute.php
in function: _saveOption(Mage_Core_Model_Abstract $object)
change:
$sortOrder = !empty($option[’order’][$optionId]) ? $option[’order’][$optionId] : 0;
if (!$intOptionId) {
$data = array(
‘attribute_id’ => $object->getId(),
‘sort_order’ => $sortOrder,
);
$adapter->insert($optionTable, $data);
$intOptionId = $adapter->lastInsertId($optionTable);
} else {
$data = array(’sort_order’ => $sortOrder);
$where = array(’option_id =?’ => $intOptionId);
$adapter->update($optionTable, $data, $where);
}
for this:
$sortOrder = !empty($option[’order’][$optionId]) ? $option[’order’][$optionId] : 0;
$yourAttribute = (isset($option[’your_attr_field’]) && !empty($option[’your_attr_field’][$optionId])) ? $option[’your_attr_field’][$optionId] : ‘’;
if (!$intOptionId) {
$data = array(
‘attribute_id’ => $object->getId(),
‘sort_order’ => $sortOrder,
‘your_attr_field’ => $yourAttribute
);
$adapter->insert($optionTable, $data);
$intOptionId = $adapter->lastInsertId($optionTable);
} else {
$data = array(’sort_order’ => $sortOrder, ‘your_attr_field’ => $yourAttribute);
$where = array(’option_id =?’ => $intOptionId);
$adapter->update($optionTable, $data, $where);
}
I could use some help in making all this changes 'the Magento way'
I have been doing frontend magento for a while but have only just started building modules. This is something i know how to do frontend but i am struggling with in my module. What i am trying to achieve for now, is populating a multiselect in the admin with all available product attributes. Including custom product attributes across all product attribute sets. I'm not entirely sure what table this will require because i don't want to assume that Flat Category Data is enabled.
I have created my admin area in a new tab in system config, i have created a multiselect field that is currently just being populated with three static options. This much works. Could anyone help me by pointing a finger in the right direction... currently this is what i have so far (for what it's worth).
<?php
class test_test_Model_Source
{
public function toOptionArray()
{
return array(
array('value' => 0, 'label' =>'First item'),
array('value' => 1, 'label' => 'Second item'),
array('value' => 2, 'label' =>'third item'),
);
}
}
///////////////////////////// EDIT /////////////////////////////////////
I feel like i might be onto something here, but it's only returning the first letter of every attribute (so i'm not sure if its even the attributes its returning)
public function toOptionArray()
{
$attributes = Mage::getModel('catalog/product')->getAttributes();
$attributeArray = array();
foreach($attributes as $a){
foreach($a->getSource()->getAllOptions(false) as $option){
$attributeArray[$option['value']] = $option['label'];
}
}
return $attributeArray;
}
///////////////////////////////// EDIT //////////////////////////////////////
I am not extremely close as i now know that the array is returning what i want it to, all attribute_codes. However it is still only outputting the first letter of each... Anyone know why?
public function toOptionArray()
{
$attributes = Mage::getModel('catalog/product')->getAttributes();
$attributeArray = array();
foreach($attributes as $a){
foreach ($a->getEntityType()->getAttributeCodes() as $attributeName) {
$attributeArray[$attributeName] = $attributeName;
}
break;
}
return $attributeArray;
}
I have answered my own question. I have found a way that worked however i'm not sure why, so if someone could comment and explain that would be useful. So although having $attributeArray[$attributeName] = $attributeName; worked when it came to a print_r when you returned the array it was only providing the first letter. However if you do the following, which in my opinion seems to be doing exactly the same thing it works. I can only imagine that when rendering it wasn't expecting a string but something else. Anyway, here is the code:
public function toOptionArray()
{
$attributes = Mage::getModel('catalog/product')->getAttributes();
$attributeArray = array();
foreach($attributes as $a){
foreach ($a->getEntityType()->getAttributeCodes() as $attributeName) {
//$attributeArray[$attributeName] = $attributeName;
$attributeArray[] = array(
'label' => $attributeName,
'value' => $attributeName
);
}
break;
}
return $attributeArray;
}
No need to do additional loops, as Frank Clark suggested. Just use:
public function toOptionArray()
{
$attributes = Mage::getResourceModel('catalog/product_attribute_collection')->addVisibleFilter();
$attributeArray = array();
foreach($attributes as $attribute){
$attributeArray[] = array(
'label' => $attribute->getData('frontend_label'),
'value' => $attribute->getData('attribute_code')
);
}
return $attributeArray;
}
You can try to get attributes in other way, like this
$attributes = Mage::getSingleton('eav/config')
->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getAttributeCollection();
Once you have attributes you can get options in this way (copied from magento code)
$result = array();
foreach($attributes as $attribute){
foreach ($attribute->getProductAttribute()->getSource()->getAllOptions() as $option) {
if($option['value']!='') {
$result[$option['value']] = $option['label'];
}
}
}
I have created a grid in Magento and there is a column which is not coming from database instead I have computed it's value from other columns using renderer.
lets say custom column in grid is total = columnA from DB - columnB from DB, have to sort the grid based on custom column.
I overrided setCollectionToOrder function in my grid., sorted the collection received from prepareCollection function and put the sorted collection in new collection object but I then my grid doesnt show any row , though I can echo the sorted collection and it works fine but no rows come in grid.
protected function _setCollectionOrder($column)
{
$collection = $this->getCollection();
if ($collection) {
switch ($column->getId()) {
case 'total':
$arr = array();
foreach($collection as $item) {
$colA= $item->getcolumnA();
$colB= $item->getcolumnB()
$total= $colA- $colB
$item->setTotal($total);
$arr[$i] = $item; $i++ ;
}
if($column->getDir()=='asc') {
$sorted = usort($arr, array('Grid_Class', '_cmpAscTotal'));
} else {
$sorted = usort($arr, array('Grid_Class', '_cmpDescTotal'));
}
$collection = $this->_tempCollection(); // A blank collection
for($i=0;$i<count($arr);$i++) {
$arr[$i]->setTotal(1);
$collection->addItem($arr[$i]);
}
$this->setCollection($collection);
break;
default:
parent::_setCollectionOrder($column);
break;
}
}
return $this;
}
tempCollection function just gives me a blank collection object (same what prepare collection function gives)
_cmpAscTotal is callback function which defines my custom sorting.
protected function _prepareCollection()
{
$collection = Mage::getModel('module/model')->getCollection();
$collection->getSelect()->joinLeft(array('table1' => 'table1'),
'table1.sku = main_table.sku_id',
Array('columnA, columnB, (1) as total')
);
$this->setCollection($collection);
return parent::_prepareCollection();
}
Is there a better way of achieving sorted collection on a custom column, if not what I am doing wrong while modifying the collection that grid becomes empty
Actually, you should extend collection class and add your custom sorting in your collection _afterLoad method. If for some reason it isn't possible - you should do it in your grid _afterLoadCollection method. In any case, you can't/shouldn't/haven't do it in collection _setCollectionOrder method. Because if you look into Mage_Adminhtml_Block_Widget_Grid::_prepareCollection() code - you will see that _setCollectionOrder is called before collection load.
Updated:
protected function _afterLoadCollection()
{
foreach ($this->getCollection() as $item) {
$item->setTotal($item->getcolumnA() - $item->getcolumnB());
}
usort($this->getCollection()->getIterator(), array('Grid_Class', '_cmpAscTotal'));
return $this;
}
Thanks Zyava
I had to do it like -
$arr = $this->getCollection()->getItems();
if($dir=='asc') {
$sorted = usort($arr, array('Grid_Class', '_cmpAscSuggestion'));
} else {
$sorted = usort($arr, array('Grid_Class', '_cmpDescSuggestion'));
}
$this->getCollection()->setItems($arrt); // created a set item function in collection class for this module.
It sorts the items in collection.
In Magento Grid
a) While preparing collection I did some calculations in query and got those values as extra column-
ex - select 1 as extracolumn
Now how can I set filter_index and sorting on this column
OR
b) I am using rendering to show custom data in a column, How can I set filter_index and sorting on this column
I tried the suggestion from shadowice222 but it didn't allow me to filter on the field. Looked at the core code and it complains about the 'my_column' not being defined. Using the addExpressionAttributeToSelect does the same as thing internally but also adds the column.
The empty array is to bypass the code which does the variable replacement as that would try to cast the Zend_Db_Expr to a string. Perhaps a better approach would be to extend the class to have an addZendDbExptToSelect method.
protected function _prepareCollection()
{
...
$collection->addExpressionAttributeToSelect('my_column', new Zend_Db_Expr("(some expression)"), array());
....
}
protected function _getFlatExpressionColumn($key) {
switch ($key) {
case 'my_column':
$result = new Zend_Db_Expr("(some expression)");
break;
}
}
protected function _prepareCollection()
{
...
$col->getSelect()
->columns(array(
'my_column' => $this->_getFlatExpressionColumn('my_column'),
))
;
...
}
protected function _prepareColumns()
{
...
$this->addColumn('my_column', array(
'header' => $hlp->__('My Column Title'),
'index' => 'my_column',
'filter_index' => $this->_getFlatExpressionColumn('my_column'),
));
...
}
show how can work this function :
Mage_Adminhtml_Block_Widget_Grid::_addColumnFilterToCollection
Is here you can make your filter for the renderers data
I am wondering if anyone out there has had much luck joining the order items table to the sale order grid and being able to filter correctly?
I have already been able to complete the join, like so:
protected function _prepareCollection()
{
parent::_prepareCollection();
$collection = Mage::getResourceModel($this->_getCollectionClass())
->join(
'sales/order_item',
'`sales/order_item`.order_id=`main_table`.entity_id',
array(
'skus' => new Zend_Db_Expr('group_concat(`sales/order_item`.sku SEPARATOR ",")'),
'names' => new Zend_Db_Expr('group_concat(`sales/order_item`.name SEPARATOR ",")'),
)
);
$collection->getSelect()->group('entity_id');
$this->setCollection($collection);
return Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();
}
But I am now trying to add the column filter like so:
protected function _addColumnFilterToCollection($column)
{
if($this->getCollection() && $column->getFilter()->getValue())
{
if($column->getId() == 'skus')
{
$this->getCollection()->join(
'sales/order_item',
'`sales/order_item`.order_id=`main_table`.entity_id',
array(
'skus' => new Zend_Db_Expr('group_concat(`sales/order_item`.sku SEPARATOR "|")'),
)
)->getSelect()
->group('`main_table`.entity_id')
->having('find_in_set(?, `main_table`.skus)', $column->getFilter()->getValue());
return $this;
}
if($column->getId() == 'names')
{
$this->getCollection()->join(
'sales/order_item',
'`sales/order_item`.order_id=`main_table`.entity_id',
array(
'names' => new Zend_Db_Expr('group_concat(`sales/order_item`.name SEPARATOR ",")'),
)
)->getSelect()
->group('`main_table`.entity_id')
->having('find_in_set(?, names)', $column->getFilter()->getValue());
return $this;
}
}
return parent::_addColumnFilterToCollection($column);
}
Each time I try to filter I get this error:
"Column not found: 1054 Unknown column 'main_table.names' in 'having clause...".
Please let me know if you have experienced this before and it you have any pointers?
I had the same problem, when i took al closer look at the problem I did see that the pagination query was causing the error. Alter the getSelectCountSql() in your model, add the following
$countSelect->reset(Zend_Db_Select::HAVING);
Your page will be shown, but you have to alter the getSelectCountSql() tot get the correct number of pages and results.