I want to add a column to sales order invoice grid, that should be exported as it is shown in the grid.The column is a calculated column, based on the row data, so there is no explicit database entry for the column value.
Those questions already had similar issues: Magento 2 + Custom column added sku on grid not showing data in export file and Magento 2 Add Custom Sale Order Grid Column and Export in CSV.
But the answers to those question either suggest to alter ConvertToCsv.php
and ConvertToXml.php
or are based on a database entry that is joined.
Altering one of the ConvertToXXX.php
files in IMHO not the right way, since the generation and calculation of the column data has nothing to do with either csv or xml. Nor do I have da database entry, so the answer does not hold.
Currently I got the following solution, which shows the data in the grid but does not get exported:
File {vendor}\{module}\view\adminhtml\ui_component\sales_order_invoice_grid.xml
with 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">
<columns name="sales_order_invoice_columns">
<column name="custom_column" class="{vendor}\{module}\Ui\Component\Listing\Column\CustomColumn">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="visible" xsi:type="boolean">true</item>
<item name="label" xsi:type="string" translate="true">Custom Column</item>
</item>
</argument>
</column>
</columns>
</listing>
and {vendor}\{module}\Ui\Component\Listing\Column\CustomColumn.php
with content:
class CustomColumn extends Column
{
protected $orderRepository;
public function __construct(...)
{
...
}
public function prepareDataSource(array $dataSource)
{
if (isset($dataSource['data']['items'])) {
foreach ($dataSource['data']['items'] as & $item) {
$order = $this->orderRepository->get($item["order_id"]);
// $value = calculate value based on order data
$item[$this->getData('name')] = $value;
}
}
return $dataSource;
}
}
This is a perfectly fine and easy solution, it respects the Single Responsibility Principle and the Open Closed Principle. I can add multiple additional columns by just adding code, without modifying code. Drawback: The calculated value does not get exported.
In Magento core code in vendor/magento/module-sales/Ui/Component/DataProvider/Document.php
they use a switch-case statement to alter some database values to export values. First, I don't know how to intercept/extend this behavior, and secondly, I don't like that switch-case statement, which does not quite adhere to the OCP.
So what is the recommended or best way to show data in the grid and get it exported (independent on which export format was chosen), in best case without doing it twice for grid and export separately.
MetaDataProvider
I have overriden thegetRowData
method and used the parsed data source instead of the data provider. This way the already modified values are used. I will try post an answer with my solution during the course of the day.