Deepak Mankotia
Deepak Mankotia

Reputation: 4564

Magento 2 : How to customise admin sales order grid collection?

I am trying to customise the admin sale order grid collection. I have created an custom sale_order attribute store_manager. These store managers are the admin users eg: 'manager1', 'manager2'.

1) Orders are manually assigned to 'manager1' or 'manager2' -- this part is done

2) Now I am trying to set filter on sale order grid collection, so when manager logged in to there system they can only see there orders.

In Magento 1 we have sales_order_grid_collection_load_before, sales_order_grid_collection_load_after for this requirement .

Is tried to such event for Magento 2 but didn't get any success.

My Queries :

Is there any such event like (sales_order_grid_collection_load_after) in magento 1 which full fill my requirement?

Is there any other way where I can set filter to sale order grid collection?

Note : I already search for this on google but didn't get any perfect solution.

Upvotes: 5

Views: 14910

Answers (4)

I was searching for the events sales_order_grid_collection_load_after and sales_order_grid_collection_load_before to customise the sales order grid.

My findings are, there are no such events in Magento 2. A general event core_collection_abstract_load_after or core_collection_abstract_load_before dispatch to render all of the grids in Magento 2 Admin.

We can override _renderFiltersBefore() function to add a column in sales order grid or to join table with sales_order_grid. Here are the steps:

Step 1: Specify class for sales order grid data source in app/code/Vendor/Module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="sales_order_grid_data_source" xsi:type="string">Vendor\Module\Model\ResourceModel\Order\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
</config>

Step 2: Add a Collection class in app/code/Vendor/Module/Model/ResourceModel/Order/Grid.php to override _renderFiltersBefore()

<?php

namespace Vendor\Module\Model\ResourceModel\Order\Grid;

use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as OriginalCollection;
use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy;
use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory;
use Magento\Framework\Event\ManagerInterface as EventManager;
use Psr\Log\LoggerInterface as Logger;

class Collection extends OriginalCollection
{
    protected $_authSession;

    public function __construct(
       EntityFactory $entityFactory,
       Logger $logger,
       FetchStrategy $fetchStrategy,
       EventManager $eventManager,
       \Magento\Backend\Model\Auth\Session $authSession
    ) {        
       $this->_authSession = $authSession;
       parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager);
    }

    protected function _renderFiltersBefore() 
    {
        $user = $this->_authSession->getUser();
        $joinTable = $this->getTable('your_table');
        $this->getSelect()->joinLeft($joinTable, 'main_table.entity_id = your_table.order_id', ['user_id']);
        parent::_renderFiltersBefore();
    }
}

Step 3 - Optional: To show a new column of user id in Sales order grid, modify standard grid component in app/code/Vendor/Module/view/adminhtml/ui_component/sales_order_grid.xml

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="sales_order_columns">
        <column name="user_id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">User ID</item>
                </item>
            </argument>
        </column>
    </columns>
</listing>

A reference is here

Upvotes: 5

Ajay
Ajay

Reputation: 458

This might be late but below is working and tested solution with Magento-2.3 for adding any filter to sales order grid.

Step 1: override Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml to Vendor/Module/view/adminhtml/ui_component/sales_order_grid.xml and update dataProvider class(in overriden sales_order_grid.xml file) with your custom class say Vendor/Module/Ui/Component/DataProvider/MyDataProvider.php.

Step 2: Add following code to it

<?php

namespace Vendor\Module\Ui\Component\DataProvider;

use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\Search\ReportingInterface;
use Magento\Framework\Api\Search\SearchCriteriaBuilder;
use Magento\Framework\App\RequestInterface;

class MyDataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider
{

    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        ReportingInterface $reporting,
        SearchCriteriaBuilder $searchCriteriaBuilder,
        RequestInterface $request,
        FilterBuilder $filterBuilder,
        array $meta = [],
        array $data = []
    ) {
        parent::__construct($name, $primaryFieldName, $requestFieldName, $reporting, $searchCriteriaBuilder, $request, $filterBuilder, $meta, $data);
        $this->myDefaultFilter();
    }

    protected function myDefaultFilter()
    {
        //do your stuff here get admin user id and apply filter accordingly

        //here is sample filtering
        $this->addFilter(
            $this->filterBuilder->setField('my_column_name')->setValue('value_to_be_filtered')->setConditionType('eq')->create()
        );
    }
    
}

Now in this myDefaultFilter function call your block to get current user detail and add logic accordingly to filter grid data.

Upvotes: 2

We usually need to execute these commands after any di.xml changes:

php -dmemory_limit=6G /[MAGENTO2_ROOT]/bin/magento setup:di:compile
php -f /[MAGENTO2_ROOT]/bin/magento setup:upgrade
rm -rf /[MAGENTO2_ROOT]/var/view_preprocessed/ /[MAGENTO2_ROOT]/var/cache/ /[MAGENTO2_ROOT]/var/page_cache/ /[MAGENTO2_ROOT]/var/generation/
rm -rf  /[MAGENTO2_ROOT]/pub/static/frontend/
php -dmemory_limit=6G /[MAGENTO2_ROOT]/bin/magento setup:static-content:deploy
php -f /[MAGENTO2_ROOT]/bin/magento cache:flush
php -f /[MAGENTO2_ROOT]/bin/magento cache:clean
sudo chmod -R 777 /[MAGENTO2_ROOT]/var /[MAGENTO2_ROOT]/pub

Use these as per your requirements.

Upvotes: 2

Dhrumin
Dhrumin

Reputation: 381

For our customized Grid, we’ll change the default data source with our own. Its parent is the standard class of the grid collection, which will let the third-party extensions effortlessly process modifications (if needed) using observers and plugins.

To implement that, in the di.xml file of our module, specify that another class should be used for the sales_order_grid data source.

app/code/Vendor/ExtendGrid/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="sales_order_grid_data_source" xsi:type="string">Vendor\ExtendGrid\Model\ResourceModel\Order\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
</config>

As you can see, we’ll need an extension class for the collection. Let’s create it here:

app/code/Vendor/ExtendGrid/Model/ResourceModel/Order/Grid/Collection.php

<?php

namespace Vendor\ExtendGrid\Model\ResourceModel\Order\Grid;

use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as OriginalCollection;
use Vendor\ExtendGrid\Helper\Data as Helper;

/**
* Order grid extended collection
*/
class Collection extends OriginalCollection
{
}

We modify the method _renderFiltersBefore so that it could connect to our table and select the necessary column there.

To do that,

<?php

namespace Vendor\ExtendGrid\Model\ResourceModel\Order\Grid;

use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as OriginalCollection;
use Vendor\ExtendGrid\Helper\Data as Helper;

/**
* Order grid extended collection
*/
class Collection extends OriginalCollection
{
    protected function _renderFiltersBefore()
    {
        $joinTable = $this->getTable('sales_order');
        $this->getSelect()->joinLeft($joinTable, 'main_table.entity_id = sales_order.entity_id', ['coupon_code']);
        //or filter in sale_order_grid collection then use like that
        $this->getSelect()->where("main_table.your_attribute is NULL");
        parent::_renderFiltersBefore();
    }
}

Upvotes: 2

Related Questions