How to add column in sales_order_grid also want to get that attribute from sales_order collection?
-
18-03-2021 - |
Question
I want to a column in sales_order_grid
I successfully did that but I also want to get
my custom attribute from sales_order
collection because I want to set value on some action, my problem is a can't get that attribute...
Thanks.
Solution
I found a way to do that:
Step 1
First of all it's better to make you own custom module make app/code/[Vendor]/[Module]/registration.php
also app/code/[Vendor]/[Module]/etc/module.xml
.
Step 2
Add your custom column in DB
mine is custom_print_status
, also I made an UPDATE
script to set default value in my custom attribute in all existing orders, so create app/code/[Vendor]/[Module]/Setup/InstallData.php
<?php
namespace [Vendor]\[Module]\Setup;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Sales\Model\Order;
class InstallData implements InstallDataInterface
{
/**
* @var \Magento\Sales\Setup\SalesSetupFactory
*/
protected $salesSetupFactory;
protected $_resourceConnection;
/**
* @param \Magento\Sales\Setup\SalesSetupFactory $salesSetupFactory
*/
public function __construct(
\Magento\Sales\Setup\SalesSetupFactory $salesSetupFactory,
\Magento\Framework\App\ResourceConnection $resourceConnection
) {
$this->salesSetupFactory = $salesSetupFactory;
$this->_resourceConnection = $resourceConnection;
}
/**
* {@inheritDoc}
*/
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
$salesSetup = $this->salesSetupFactory->create(['resourceName' => 'sales_setup', 'setup' => $installer]);
$salesSetup->addAttribute(Order::ENTITY, 'custom_print_status', [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
'length'=> 11,
'visible' => false,
'nullable' => false
]);
/* UPDATE CUSTOM PRINT STATUS TO 'No' By PartbSaif */
$updateData = array('custom_print_status' => 0);
$connection = $this->_resourceConnection->getConnection();
$connection->update(
$connection->getTableName('sales_order'),
$updateData
);
/* ========================================= */
$installer->endSetup();
}
}
Step 3
Add your custom column in sales_order_grid
, create 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="custom_print_status" class="[Vendor]\[Module]\Ui\Component\Listing\Column\CustomPrintStatus" component="Magento_Ui/js/grid/columns/select">
<settings>
<filter>select</filter>
<options class="[Vendor]\[Module]\Ui\Component\Listing\Column\CustomPrintStatus\Options"/>
<dataType>select</dataType>
<label translate="true">Print Status</label>
</settings>
</column>
</columns>
</listing>
Step 4
For render your custom column from sales_order
table. e.g 0/1 in sales_order_grid
, create app/code/[Vendor]/[Module]/Ui/Component/Listing/Column/CustomPrintStatus.php
<?php
namespace [Vendor]\[Module]\Ui\Component\Listing\Column;
use \Magento\Sales\Api\OrderRepositoryInterface;
use \Magento\Framework\View\Element\UiComponent\ContextInterface;
use \Magento\Framework\View\Element\UiComponentFactory;
use \Magento\Ui\Component\Listing\Columns\Column;
use \Magento\Framework\Api\SearchCriteriaBuilder;
use \Magento\Framework\App\ResourceConnection;
class CustomPrintStatus extends Column
{
protected $_orderRepository;
protected $_searchCriteria;
protected $_resourceConnection;
public function __construct(
ContextInterface $context,
UiComponentFactory $uiComponentFactory,
OrderRepositoryInterface $orderRepository,
SearchCriteriaBuilder $criteria,
ResourceConnection $resourceConnection,
array $components = [],
array $data = [])
{
$this->_orderRepository = $orderRepository;
$this->_searchCriteria = $criteria;
$this->_resourceConnection = $resourceConnection;
parent::__construct($context, $uiComponentFactory, $components, $data);
}
public function prepareDataSource(array $dataSource)
{
if (isset($dataSource['data']['items'])) {
foreach ($dataSource['data']['items'] as & $item) {
$order = $this->_orderRepository->get($item['entity_id']);
$customPrintStatus = $order->getCustomPrintStatus();
$item['custom_print_status'] = $customPrintStatus;
}
}
return $dataSource;
}
}
Step 5
In DB
value will store as 0 and 1 e.g 0 => 'No' & 1 => 'Yes', so to show value as Yes/No, create file.
app/code/[Vendor]/[Module]/Ui/Component/Listing/Column/CustomPrintStatus/Options.php
<?php
namespace [Vendor]\[Module]\Ui\Component\Listing\Column\CustomPrintStatus;
class Options implements \Magento\Framework\Option\ArrayInterface
{
/**
* @return array
*/
public function toOptionArray()
{
$options = [
[
'value' => 1,
'label' => __('Yes')
],
[
'value' => 0,
'label' => __('No')
]
];
return $options;
}
}
Step 6
BTW when you try to filter value in sales_order_grid
, you'll get an error, to do that you have to map your value in Order Grid Collection
, to do that you have to override Collection
file of Order Grid, create file
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>
app/code/[Vendor]/[Module]/Model/ResourceModel/Order/Grid/Collection.php
<?php
namespace [Vendor]\[Module]\Model\ResourceModel\Order\Grid;
use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as OriginalCollection;
/**
* Order grid extended collection
*/
class Collection extends OriginalCollection
{
protected function _initSelect()
{
$this->addFilterToMap('created_at', 'main_table.created_at');
$this->addFilterToMap('increment_id', 'main_table.increment_id');
$this->addFilterToMap('base_grand_total', 'main_table.base_grand_total');
$this->addFilterToMap('grand_total', 'main_table.grand_total');
$this->addFilterToMap('store_id', 'main_table.store_id');
$this->addFilterToMap('billing_name', 'main_table.billing_name');
$this->addFilterToMap('shipping_name', 'main_table.shipping_name');
$this->addFilterToMap('status', 'main_table.status');
parent::_initSelect();
}
protected function _renderFiltersBefore()
{
$joinTable = $this->getTable('sales_order');
$this->getSelect()->joinLeft($joinTable, 'main_table.entity_id = sales_order.entity_id', ['custom_print_status']);
parent::_renderFiltersBefore();
}
}
Step 7
Now to set value as No
when new order created you have to make event
called sales_order_save_before
, so create
app/code/[Vendor]/[Module]/etc/event.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="sales_order_place_after">
<observer name="set_order_attribute" instance="[Vendor]\[Module]\Observer\SetOrderAttribute"/>
</event>
</config>
app/code/[Vendor]/[Module]/Observer/SetOrderAttribute.php
<?php
namespace [Vendor]\[Module]\Observer;
class SetOrderAttribute implements \Magento\Framework\Event\ObserverInterface
{
/**
* @param \Magento\Framework\Event\Observer $observer
* @return $this
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{
/** @var \Magento\Sales\Model\Order $order */
$order = $observer->getEvent()->getOrder();
$order->setCustomPrintStatus(0);
return $this;
}
}
Step 8
For set value on in DB
for your custom column, add below code in Model
, this code set 1
value on action.
/* CHANGE PRINT STATUS TO 'Yes' By PartbSaif */
$yes = 1;
$order->setCustomPrintStatus($yes)->save();
/* ========================================= */
Explanation What this module does ?
I want to create column in sales_order_grid
column name is custom_print_status
, when user select order and click on Print Invoices
Or Print All
under Action
drop-down, the custom_print_status
changed to Yes
, otherwise it's value is by default set to No
, for set value to Yes
on above 2 action you need to override /[root]/vendor/magento/module-sales/Model/Order/Pdf/Invoice.php
, I hope you know how to override Model
file from vendor, if not refer to this link => How to override Model file
In this file you'll find getPdf()
function, put above code at the end of foreach
loop like this:
foreach ($invoices as $invoice) {
/* Code to set value */
}
Thank You.