views:

74

answers:

4

I want to pre-filter* data in the invoice grid visible in Magento's admin panel.

Here is a question that I asked earlier, and this one is related to the solution presented for that, hence it might act as a good explanation.

So, I am modifying the Mage_Adminhtml_Block_Sales_Invoice_Grid::_prepareCollection method so that it first fetches customer referred by the logged in admin. Then it will fetch orders from these customer(s) - ideally only the order id's - Then join this collection to *sales/order_invoice_grid*, to get invoices to be listed for this admin.

Based on the last answer and using these docs, following are 3 ways I have tried joining this information: (Code Sample 1)

$collection = Mage::getResourceModel('customer/customer_collection');        
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('*'));
$collection->joinTable('sales/invoice_grid', 'order_id=main_table.entity_id', array('*'));

When I do the above, I see the following error:

A joint field with this alias (0) is already declared.

#0 /var/www/magento/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php(706): Mage::exception('Mage_Eav', 'A joint field w...')
#1 /var/www/magento/app/code/local/Myproject/Adminhtml/Block/Sales/Invoice/Grid.php(41): Mage_Eav_Model_Entity_Collection_Abstract->joinTable('sales/invoice_g...', 'order_id=main_t...', Array)
#2 /var/www/magento/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(576): Myproject_Adminhtml_Block_Sales_Invoice_Grid->_prepareCollection()
#3 /var/www/magento/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(582): Mage_Adminhtml_Block_Widget_Grid->_prepareGrid()

If I remove the second call to joinTable, the above code works, but it is not what I want.

The other method I tried is with this code:

$collection = Mage::getResourceModel('customer/customer_collection');        
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('entity_id as order_entity_id'));
$collection->joinTable('sales/invoice_grid', 'order_id=main_table.entity_id', array('*'));

Here the error appears in the second line, where I am actually trying to alias the field order.entity_id so that it does not conflict with invoice tables entity_id. However that produces an error like:

Item (Mage_Customer_Model_Customer) with the same id "1" already exist

I only need order id's so that I can get related invoices, which suggests that I can also use joinField function, which I tried as follows:

$collection = Mage::getResourceModel('customer/customer_collection');
$collection->joinField('order_entity_id', 'sales/order_grid', 'entity_id', 'customer_id=entity_id' , null, 'left');

But it gives me the following error:

Item (Mage_Customer_Model_Customer) with the same id "1" already exist

I am looking for a solution that joins customer->invoices.


By pre-filter I mean that data listed in the grid is filtered even before anything is presented in the grid.


Ok, now my code looks like:

$collection = 
Mage::getResourceModel('customer/customer_collection');
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('entity_id' => 'order_entity_id'));

And the error that I get is:

SELECT `e`.*, `sales_flat_order_grid`.`order_entity_id` AS `entity_id` FROM `customer_entity` AS `e`
 INNER JOIN `sales_flat_order_grid` ON (sales_flat_order_grid.customer_id=e.entity_id) WHERE (e.entity_type_id = '1') ORDER BY `e`.`created_at` desc, `e`.`created_at` desc LIMIT 20

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sales_flat_order_grid.order_entity_id' in 'field list'

+1  A: 

It gives you this error "Item (Mage_Customer_Model_Customer) with the same id "1" already exist" because a customer can have multiple orders and so could have two or more entries with the same customer id - you are creating a collection of customers and you must have unique entries in the collection. You have to start from invoices and join them with the customers.

Anda B
I tried with your suggestion, as follows:"$collection = Mage::getResourceModel($this->_getCollectionClass());$collection->joinTable('sales/order', 'entity_id=order_id', array('*'));"And this time the error is:Fatal error: Call to undefined method Mage_Sales_Model_Mysql4_Order_Invoice_Grid_Collection::joinTable() in /var/www/magento/app/code/local/Myproject/Adminhtml/Block/Sales/Invoice/Grid.php on line 41
Ozair Kafray
It's because Mage_Sales_Model_Mysql4_Order_Grid_Collection inherits from Mage_Core_Model_Mysql4_Collection_Abstract, it doesn't use the eav model; you have to use join($table, $cond, $cols='*'). The customer collection inherits from Mage_Eav_Model_Entity_Collection_Abstract and you use joinTable
Anda B
+1  A: 

The error "A joint field with this alias (0) is already declared." occurs because it uses array keys as aliases. Since you have two joinTable() calls, each with an array, it is trying to use the zero-based index of both and obviously having a conflict.
So instead of

array('entity_id as order_entity_id')

try

array('entity_id' => 'order_entity_id')

to avoid the conflict.

clockworkgeek
I have added a section in my question under the second horizontal partition. I understand the error itself, but unfortunately I do not know Magento's ORM well, and can't figure out a solution.
Ozair Kafray
Whoops, I got the key and value the wrong way round. I should have said `array('order_entity_id' => 'entity_id')`
clockworkgeek
I already tried that way, and the error is:"Item (Mage_Customer_Model_Customer) with the same id "1" already exist#0 /var/www/magento/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php(236): Varien_Data_Collection->addItem(Object(Mage_Customer_Model_Customer))#1 /var/www/magento/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php(963): Mage_Eav_Model_Entity_Collection_Abstract->addItem(Object(Mage_Customer_Model_Customer))"
Ozair Kafray
When I do a test I get no error like that. In fact I cannot find that error in "Abstract.php(236)" nor in any other file in Magento. Are you using a really old version or do you have any extensions that modifies the core EAV?
clockworkgeek
Yes, I am using an extension Sweettooth, and while its there the error mentions a class from that module (TBT_Rewards_Model_Customer) having the problem, but I had uninstalled it to see if the error goes away. Unfortunately, it doesn't, the error then appears with Mage's core class.
Ozair Kafray
+1  A: 

Here is the total of my test script. To use put it in a file at the Magento root and type it's URL directly in your browser, it is not handled by Magento's controllers. This is a good way of experimenting as it is not as influenced by other modules, page layouts, etc.

<pre><?php

require 'app/Mage.php';
Mage::app();

$collection = Mage::getResourceModel('customer/customer_collection');
$collection->getSelect()->reset('columns');        
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('order_entity_id' => 'entity_id'));
$collection->joinTable('sales/invoice_grid', 'order_id=order_entity_id', array('*'));

foreach ($collection as $invoice)
    print_r($invoice->debug());

?></pre>

As with your previous question I choose to reset the initial columns because I don't believe in giving the database more work than necessary. However it's not essential, the test still succeeds without it.

If this doesn't work in your installation then we need to consider what that outside influence could be.

clockworkgeek
A: 

I finally did achieve this by going from invoice->order->customer as 'Anda B' suggested. I am just pasting my solution here as a reference, but will be using this solution from clockworkgeek, since it seems much cleaner. And my solution still needs to be made cleaner by getting the 'id' of eav_attribute (agent_id) from the database at runtime, instead of hard coding it, as pasted here:

class Myproject_Adminhtml_Block_Sales_Invoice_Grid extends Mage_Adminhtml_Block_Sales_Invoice_Grid
{
    const AGENT_ID_ATTRIBUTE_ID = 118;

    protected function _prepareCollection()
    {

$collection = Mage::getResourceModel($this->_getCollectionClass());

        $collection->join('order_grid', 'order_id = order_grid.entity_id', array ('order_entity_id' => 'order_grid.entity_id'));
        $collection->getSelect()->join( 'customer_entity', 'customer_id = customer_entity.entity_id', array('customer_entity_id' => 'entity_id', 'email'));
        $collection->getSelect()->joinLeft( 'customer_entity_int', 'customer_entity_int.entity_id = customer_entity.entity_id AND attribute_id = ' . Myproject_Adminhtml_Block_Sales_Invoice_Grid::AGENT_ID_ATTRIBUTE_ID, 
                                        array('attribute_entity_id' => 'customer_entity_int.entity_id', 'attribute_id' , 'value'));

//Apply Desired Data Filters here

$this->setCollection($collection);

return $collection;
Ozair Kafray