Magento 2 – Adding Mass Action to Sales Order Grid

magento2order-gridorder-statusorderssales-order-grid

I am trying to apply a mass action to sales_order_grid but there is nothing happening. I have done so for is:

vendor_name/module_name/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">
<container name="listing_top">
<massaction name="listing_massaction">
  <action name="nameofaction">
          <argument name="data" xsi:type="array">
              <item name="config" xsi:type="array">
                  <item name="type" xsi:type="string">testing</item>
                  <item name="label" xsi:type="string" translate="true">My Label</item>
                  <item name="url" xsi:type="url" path="multiorderinvoice/index/massorder"/>
              </item>
          </argument>
      </action>
</massaction>
</container>
</listing>

And vendor_name/module_name/Controller/Adminhtml/Index

<?php

namespace Vendor_Name\Module_Name\Controller\Adminhtml\Index;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;

class MassOrder extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
{
/**
 * Authorization level of a basic admin session
 */

/**
 * @param Context $context
 * @param Filter $filter
 * @param CollectionFactory $collectionFactory
 */
public function __construct(Context $context, Filter $filter, CollectionFactory $collectionFactory)
{
    parent::__construct($context, $filter);
    $this->collectionFactory = $collectionFactory;
}

/**
 * Cancel selected orders
 *
 * @param AbstractCollection $collection
 * @return \Magento\Backend\Model\View\Result\Redirect
 */
protected function massAction(AbstractCollection $collection)
{
    $countCancelOrder = 0;
    print_r($collection->getAllIds()); //to check the ids
    foreach ($collection->getItems() as $order) {

        //do your logic here
        $countCancelOrder++;
    }
    $countNonCancelOrder = $collection->count() - $countCancelOrder;

    if ($countNonCancelOrder && $countCancelOrder) {
        $this->messageManager->addError(__('%1 order(s) cannot be done it .', $countNonCancelOrder));
    } elseif ($countNonCancelOrder) {
        $this->messageManager->addError(__('You done it  the order(s).'));
    }

    if ($countCancelOrder) {
        $this->messageManager->addSuccess(__('We done it %1 order(s).', $countCancelOrder));
    }
    $resultRedirect = $this->resultRedirectFactory->create();
    $resultRedirect->setPath($this->getComponentRefererUrl());
    return $resultRedirect;
}
}

Actually I want to get print of specific fields from all order invoices as a single invoice for admin but my first concern is triggering some action, for this I am using above code for now.

And in Vendor_Name/Module_Name/etc/adminhtml/routes.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
    <route id="abc" frontName="abc">
        <module name="VendorName_ModuleName" before="Magento_Backend" />
    </route>
</router>

Any help will be appreciated.

Best Answer

Create a module with name Vendor_Module by following steps:

Step 1: Create registration.php under:

app/code/Vendor/Module/registration.php

with below content:

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_Module',
    __DIR__
);

Step 2: Create composer.json under:

app/code/Vendor/Module/composer.json

with below content:

{
    "name": "vendor/module",
    "description": "Vendor Module",
    "require": {
      "php": "~5.6.0|7.0.2|~7.0.6",
      "magento/magento-composer-installer": "*"
    },
    "type": "magento2-module",
    "version": "1.0.0",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "extra": {
        "map": [
            [
                "*",
                "Vendor/Module"
            ]
        ]
    }
}

Step 3: Create module.xml under:

app/code/Vendor/Module/etc/module.xml

with below content:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Vendor_Module" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Sales"/>
        </sequence>
    </module>
</config>

Step 4: Create routes.xml under:

app/code/Vendor/Module/etc/adminhtml/routes.xml

with below content:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="ordermass" frontName="ordermass">
            <module name="Vendor_Module" />
        </route>
    </router>
</config>

Step 5: Create MassDelete.php under:

app/code/Vendor/Module/Controller/Adminhtml/Order/MassDelete.php

with below content:

<?php

namespace Vendor\Module\Controller\Adminhtml\Order;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Sales\Api\OrderManagementInterface;

class MassDelete extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
{

    protected $orderManagement;

    public function __construct(
        Context $context,
        Filter $filter,
        CollectionFactory $collectionFactory,
        OrderManagementInterface $orderManagement
    ) {
        parent::__construct($context, $filter);
        $this->collectionFactory = $collectionFactory;
        $this->orderManagement = $orderManagement;
    }

    protected function massAction(AbstractCollection $collection)
    {
        $countDeleteOrder = 0;
        $model = $this->_objectManager->create('Magento\Sales\Model\Order');
        foreach ($collection->getItems() as $order) {
            if (!$order->getEntityId()) {
                continue;
            }
            $loadedOrder = $model->load($order->getEntityId());
            $loadedOrder->delete();
            $countDeleteOrder++;
        }
        $countNonDeleteOrder = $collection->count() - $countDeleteOrder;

        if ($countNonDeleteOrder && $countDeleteOrder) {
            $this->messageManager->addError(__('%1 order(s) cannot be done it .', $countNonDeleteOrder));
        } elseif ($countNonDeleteOrder) {
            $this->messageManager->addError(__('You done it  the order(s).'));
        }

        if ($countDeleteOrder) {
            $this->messageManager->addSuccess(__('We done it %1 order(s).', $countDeleteOrder));
        }

        $resultRedirect = $this->resultRedirectFactory->create();
        $resultRedirect->setPath($this->getComponentRefererUrl());
        return $resultRedirect;
    }
}

Step 6: Create sales_order_grid.xml under:

app/code/Vendor/Module/view/adminhtml/ui_component/sales_order_grid.xml

with below content:

<?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">
    <listingToolbar name="listing_top">
            <massaction name="listing_massaction">
                <action name="order_delete">
                    <argument name="data" xsi:type="array">
                        <item name="config" xsi:type="array">
                            <item name="type" xsi:type="string">order_mass</item>
                            <item name="label" xsi:type="string" translate="true">Label</item>
                            <item name="url" xsi:type="url" path="ordermass/order/massDelete"/>
                            <item name="confirm" xsi:type="array">
                                <item name="title" xsi:type="string" translate="true">Label</item>
                                <item name="message" xsi:type="string" translate="true">Are you sure to do selected items?</item>
                            </item>
                        </item>
                    </argument>
                </action>
            </massaction>
    </listingToolbar>
</listing>

Run the required commands and test.