views:

138

answers:

1

I have extended Magento’s customer information form to store an additional attribute for customer. Lets call it ‘customer_referrer_id’.

I have a role ‘referrer ‘ who has access to customer grid and order grid only. But, I want to restrict a referrer to see only those customers in the grid who have the customer_referrer_id set as the referrer’s id who has logged in. Similarly for orders, the logged in referrer shall be able to see only those orders made by customers who have customer_referrer_id = loggedin_referrer_id.

I already know how to override a module and that I have to mainly override Adminhtml/Block/Customer/Grid::_prepareCollection and Adminhtml/Block/Sales/Order/Grid::_prepareCollection

I am using Magento 1.4.1.1

This is my module declaration file in app/etc/modules/Myproject_Adminhtml

<?xml version="1.0"?>

<config>
    <modules>
        <Myproject_Adminhtml>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Sales />
            </depends>
        </Myproject_Adminhtml>
    </modules>
</config>

And my modules config.xml in local/Myproject/Adminhtml/etc/ is as follows:

<config>
    <modules>
        <Myproject_Adminhtml>
            <version>1.0.0</version>
        </Myproject_Adminhtml>    
    </modules>

    <global>
          <blocks>
            <adminhtml>
                <rewrite>
                <sales_order_grid>Myproject_Adminhtml_Block_Sales_Order_Grid</sales_order_grid>
                <customer_grid>Myproject_Adminhtml_Block_Customer_Grid</customer_grid>
                </rewrite>
            </adminhtml>
        </blocks>
    </global>
</config>

And

class Myproject_Adminhtml_Block_Customer_Grid extends Mage_Adminhtml_Block_Customer_Grid
{
    protected function _prepareCollection()
    {
        $collection = Mage::getResourceModel('customer/customer_collection')
        ->addNameToSelect()
        ->addAttributeToSelect('email')
        ->addAttributeToSelect('created_at')
        ->addAttributeToSelect('group_id')
        ->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
        ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
        ->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
        ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
        ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');    

        $this->setCollection($collection);

        $referrer_id = Mage::getSingleton('admin/session')->getUser()->getId();
        Mage::log('Logged in admin has id: ' . $referrer_id);

        return parent::_prepareCollection();
    }  
}
+1  A: 

My first attempt would be (for both files mentioned),

$collection->addAttributeToFilter('customer_referrer_id', $referrer_id);

Where $referrer_id is the value you must retrieve from the logged in user. Since you appear to be using admin users - which are separate entities from customers - this is one way of retrieving;

$referrer_id = Mage::getSingleton('admin/session')->getUser()->getId();

Note the currently logged in admin user is not apparent from the database alone so it cannot be a table join.

On another point I would use the frontend for referrers instead of the admin. I would have the new customers and their orders shown in the referrer's customer account, similar to their own "My Orders" page. Of course I don't know what other requirements you have to attend to.

Second part

Override Mage_Adminhtml_Block_Sales_Order_Grid::_prepareCollection() to look like this:

protected function _prepareCollection()
{
    $collection = Mage::getResourceModel('customer/customer_collection');
    $collection->getSelect()->reset('columns'); // remove all customer columns
    $collection->addAttributeToFilter('entity_id', $referrer_id);
    $collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('*'));

    $this->setCollection($collection);
    return parent::_prepareCollection();
}

This is necessary because the original table sales/order_grid is flat, not an entity collection, and so cannot be joined with attributes. The above works in reverse, by starting with a customer collection and then joining the flat table after.

A possibly neater method would be to override sales/order_grid_collection with your own collection class which performs all this. Although it better follows coding conventions it is more work and no more functional in the end.

clockworkgeek
The preceding was posted before I saw the question had been updated with examples. I see now you had already tried something similar.
clockworkgeek
ok, the customers are being filtered correctly now. And, even though it seems obvious that same two lines would not work for filtering the orders table, I already tried adding those line in Sales_Order_Grid::_prepareCollection. How should I filter Orders that are made by Customers whose customer_referrer_id = loggedin_referrer_id
Ozair Kafray
I also removed the _prepareColumn override, which is there in my original question, that was just to validate that correct results are showing.
Ozair Kafray
Thank you for the interesting question Ozair. I enjoy the challenge very much. To take advantage of code formatting I have appended my answer for the order grid problem.
clockworkgeek
@clockworkgeek: Thanks it worked for me finally, after I replaced last line "return parent::_prepareCollection" to "Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();" in the overwritten function. Its easy to see why if you look at "Mage_Adminhtml_Block_Sales_Order_Grid::_prepareCollection" function. I would appreciate if you correct this in your answer, that would be of great benefit to others.I have one question though, its working even without "$collection->getSelect()->reset('columns'); " in your code. Can you please explain why did you put it in there?
Ozair Kafray
I chose to reset columns partly because of efficiency, and partly because the customer entity will return it's own "store_id" value which might be in conflict with the order's value. Potentially this might have caused the wrong orders to show in the table when being filtered by "Purchased from (Store)".
clockworkgeek
I understand what you mean about the return call, since the class is overridden then parent is no longer the parent you were expecting. But how does calling the correct class statically help? Wouldn't that be affecting a completely different collection?
clockworkgeek
The parent of the my custom class i.e. "Mage_Adminhtml_Block_Sales_Order_Grid::_prepareCollection()" creates a collection in itself and sets that to be rendered. You are right about the static calling though, I don't have a good reason why it works right now, but it is working like a breeze.
Ozair Kafray
It works fine if I wrtie`return $collection;`instead of:`return parent::_prepareCollection();`
Ozair Kafray
Does clicking on the column headers still cause the list to sort correctly? I doubt it since that parent method is responsible.
clockworkgeek