Como associar a coleção de grade de pedidos à tabela personalizada no Magento2?

12

Estou tentando adicionar uma nova coluna para ordenar grade no Magento 2.0. Então, eu preciso fazer a junção para solicitar a coleta da grade. Como posso conseguir isso? Porque, no magento2, a grade usa o componente da interface do usuário.

Pradeep Kumar
fonte

Respostas:

12

O Magento 2 adiciona colunas personalizadas à grade de pedidos de vendas,

Juntar-se

Magento \ Vendas \ Pedido \ Grade \ Coleção

para qualquer tabela, usar o plugin seria a melhor opção, pois isso não depende de reescritas e torna o código mais enxuto.

Crie o plug-in no arquivo etc / di.xml do seu módulo

<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
    <plugin name="sales_order_additional_columns" type="Vendor\ModuleName\Plugins\AddColumnsSalesOrderGridCollection" sortOrder="100" disabled="false" />
</type>

Então, nós estamos interceptando

Magento \ Framework \ Visualizar \ Elemento \ UiComponent \ DataProvider \ CollectionFactory

porque se você der uma olhada no

Magento \ Vendas \ etc \ di.xml

você veria

Magento \ Vendas \ Pedido \ Grade \ Coleção

foi injetado em

Magento \ Framework \ Visualizar \ Elemento \ UiComponent \ DataProvider \ CollectionFactory

Crie uma pasta Plugin e uma classe plugin no seu módulo

<?php namespace Vendor\ModuleName\Plugins;

use Magento\Framework\Message\ManagerInterface as MessageManager;
use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as SalesOrderGridCollection;

class AddColumnsSalesOrderGridCollection
{
    private $messageManager;
    private $collection;

    public function __construct(MessageManager $messageManager,
        SalesOrderGridCollection $collection
    ) {

        $this->messageManager = $messageManager;
        $this->collection = $collection;
    }

    public function aroundGetReport(
        \Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory $subject,
        \Closure $proceed,
        $requestName
    ) {
        $result = $proceed($requestName);
        if ($requestName == 'sales_order_grid_data_source') {
            if ($result instanceof $this->collection
            ) {
                $select = $this->collection->getSelect();
                $select->join(
                    ["soi" => "sales_order_item"],
                    'main_table.entity_id = soi.order_id AND soi.product_type="simple"',
                    array('weight', 'product_type')
                )
                    ->distinct();

                $select->join(
                    ["soa" => "sales_order_address"],
                    'main_table.entity_id = soa.parent_id AND soa.address_type="shipping"',
                    array('email', 'country_id', 'postcode', 'city', 'telephone')
                )
                    ->distinct();
            }

        }
        return $this->collection;
    }
}

Aqui estamos observando em torno de eventos do método getReport ().

cópia de

fornecedor / magento / module-sales / view / adminhtml / ui_component / sales_order_grid.xml

ao escopo do seu módulo

Fornecedor / nome do módulo / view / adminhtml / ui_component / sales_order_grid.xml

Exclua todo o conteúdo do seu sales_order_grid.xml copiado, pois não queremos substituir todo o conteúdo.

Digite o seguinte código no sales_order_grid.xml do seu módulo

    <?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">

        <!-- sales_order_item weight -->
        <column name="weight">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Weight</item>
                    <item name="sortOrder" xsi:type="number">222</item>
                    <item name="align" xsi:type="string">right</item>
                    <item name="filter" xsi:type="string">text</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <!--<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>-->
                </item>
            </argument>
        </column>

        <!-- sales_order_item product_type-->
        <column name="product_type">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\ModuleName\Ui\Component\Listing\Column\ProductTypes</item>
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Product Type</item>
                    <item name="sortOrder" xsi:type="number">232</item>
                    <item name="align" xsi:type="string">right</item>
                    <!--<item name="filter" xsi:type="string">select</item>-->
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
                    <item name="dataType" xsi:type="string">select</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <!--<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>-->
                </item>
            </argument>
        </column>

        <!-- sales_order_address country_id -->
        <column name="country_id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Country ID</item>
                    <item name="sortOrder" xsi:type="number">242</item>
                    <item name="align" xsi:type="string">right</item>
                    <item name="filter" xsi:type="string">text</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <!--<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>-->
                </item>
            </argument>
        </column>

        <!-- sales_order_address post_code -->
        <column name="postcode">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Postcode</item>
                    <item name="sortOrder" xsi:type="number">252</item>
                    <item name="align" xsi:type="string">right</item>
                    <item name="filter" xsi:type="string">text</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <!--<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>-->
                </item>
            </argument>
        </column>

        <!-- sales_order_address city -->
        <column name="city">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">City</item>
                    <item name="sortOrder" xsi:type="number">252</item>
                    <item name="align" xsi:type="string">right</item>
                    <item name="filter" xsi:type="string">text</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <!--<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>-->
                </item>
            </argument>
        </column>

        <!-- sales_order_address telephone -->
        <column name="telephone">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Telephone</item>
                    <item name="sortOrder" xsi:type="number">252</item>
                    <item name="align" xsi:type="string">right</item>
                    <item name="filter" xsi:type="string">text</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <!--<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>-->
                </item>
            </argument>
        </column>

    </columns>

</listing>

Agora, exclua o cache da pasta var / cache ou atualize seu cache. Você poderá ver suas colunas adicionadas na grade da ordem do cliente.

Asrar
fonte
Muito obrigado por esse, meu único problema (com Magento 2.2.0) foi que eu tive que adicionar prefixo de tabela nas linhas ["soi" => "sales_order_item"]e ["soa" => "sales_order_address"].
David
Eu pensei que estava funcionando bem, mas parece mexer com a grade da fatura também .. Com o módulo ativado, o ID e o status do pedido estão estranhamente vazios na grade da fatura. Alguma idéia do que poderia estar errado?
David
Obrigado por essas informações, ele me ajudou a adicionar o nome da empresa. Mas como eu mostraria as informações de cobrança e envio em vez de apenas o envio? Eu posso mostrar 1 ou o outro, mas não consigo renomear 'empresa' para dizer 'empresa_de_ faturamento' e 'empresa-expedição' para usar em sales_order_grid.xml
RLTcode
1
Obtendo erros nas grades CMS Page, CMS Block, Customer e Creditmemo ao usar a classe de plug-in. Informe-me se houver alguma solução alternativa para modificar a coleção de grade.
Vishal
Quais erros você pode ver na grade da fatura e etc.?
Asrar
9

Quando você olha para o \Magento\Framework\Data\Collection\AbstractDbpróprio magento2, fornece operação de gancho para sua coleção.

protected function _renderFilters()
{
    if ($this->_isFiltersRendered) {
        return $this;
    }

    $this->_renderFiltersBefore(); // Hook for operations before rendering filters

    ....................
}

Então, o que você precisa fazer é adicionar apenas sua coleção [ NAMESPACE\MODULENAME\Model\ResourceModel\YOUR_CLASSNAME\Grid\Collection]

protected function _renderFiltersBefore() {
    $joinTable = $this->getTable('catalog_product_entity_varchar');
    $this->getSelect()->join($joinTable.' as cpev','main_table.entity_id = cpev.entity_id', array('*'));
    parent::_renderFiltersBefore();
}
Keyur Shah
fonte
Eu preciso mostrar o meu campo de tabela personalizada na grade de ordem, neste caso, ho para mostrá-lo?
Pradeep Kumar
@Keyur Shah Obrigado, isso ajuda muito para mim.
Rohit Goel
Fico feliz em ouvir que ele ajuda você :) Manter @RohitGoel ajuda o outro membro da comunidade
Keyur Shah
Claro :) @KeyurShah eu amo ajudar a comunidade. Estou criando uma grade sem componente de interface do usuário, você pode me dizer como posso adicionar um recurso de exportação nisso?
Rohit Goel
1
Em vez de _renderFiltersBefore, você também pode substituir / estender _initSelect.
Jānis Elmeris 28/11
3

Criei a grade de administração que possui junção de duas tabelas personalizadas. você não pode fazer isso usando o tipo virtual is di.xml, portanto, siga estas etapas e atualize seu

etc / di.xml,

Model / Resource / Modulename / Collection.php adiciona junção a este arquivo,

Model / Resource / Modulename / Grid / Collection.php,

NO seu etc / di.xml

<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="namespace_modulename_listing_data_source" xsi:type="string">Namespace\Modulename\Model\Resource\Modulename\Grid\Collection</item>
            </argument>
        </arguments>
</type>
<type name="Namespace\Modulename\Model\Resource\Modulename\Grid\Collection">
    <arguments>
        <argument name="mainTable" xsi:type="string">tablename</argument>
        <argument name="eventPrefix" xsi:type="string">namespace_modulename_grid_collection</argument>
        <argument name="eventObject" xsi:type="string">namespace_grid_collection</argument>
        <argument name="resourceModel" xsi:type="string">Namespace\Modulename\Model\Resource\Modulename</argument>
    </arguments>
</type>

EM seu Modelo / Recurso / Nome do módulo / Collection.php

<?php
namespace Namespace\Modulename\Model\Resource\Modulename;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;

class Collection extends AbstractCollection
{
    /**
     * Define model & resource model
     */
    const YOUR_TABLE = 'tablename';

    public function __construct(
        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
        \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
    ) {
        $this->_init(
            'Namespace\Modulename\Model\Modulename',
            'Namespace\Modulename\Model\Resource\Modulename'
        );
        parent::__construct(
            $entityFactory, $logger, $fetchStrategy, $eventManager, $connection,
            $resource
        );
        $this->storeManager = $storeManager;
    }
    protected function _initSelect()
    {
        parent::_initSelect();

        $this->getSelect()->joinLeft(
                ['secondTable' => $this->getTable('tablename')],
                'main_table.columnname = secondTable.columnname',
                ['columnname1','columnname2','columnname3']
            );
    }
}
?>

NO seu modelo / recurso / nome do módulo / grade / coleção.php

<?php
namespace Namespace\Modulename\Model\Resource\Modulename\Grid;

use Magento\Framework\Api\Search\SearchResultInterface;
use Magento\Framework\Search\AggregationInterface;
use Namespace\Modulename\Model\Resource\Modulename\Collection as ModulenameCollection;

/**
 * Class Collection
 * Collection for displaying grid
 */
class Collection extends ModulenameCollection implements SearchResultInterface
{
    /**
     * Resource initialization
     * @return $this
     */
   public function __construct(
        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        $mainTable,
        $eventPrefix,
        $eventObject,
        $resourceModel,
        $model = 'Magento\Framework\View\Element\UiComponent\DataProvider\Document',
        $connection = null,
        \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
    ) {
        parent::__construct(
            $entityFactory,
            $logger,
            $fetchStrategy,
            $eventManager,
            $storeManager,
            $connection,
            $resource
        );
        $this->_eventPrefix = $eventPrefix;
        $this->_eventObject = $eventObject;
        $this->_init($model, $resourceModel);
        $this->setMainTable($mainTable);
    }

    /**
     * @return AggregationInterface
     */
    public function getAggregations()
    {
        return $this->aggregations;
    }

    /**
     * @param AggregationInterface $aggregations
     *
     * @return $this
     */
    public function setAggregations($aggregations)
    {
        $this->aggregations = $aggregations;
    }


    /**
     * Get search criteria.
     *
     * @return \Magento\Framework\Api\SearchCriteriaInterface|null
     */
    public function getSearchCriteria()
    {
        return null;
    }

    /**
     * Set search criteria.
     *
     * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
     *
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function setSearchCriteria(
        \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null
    ) {
        return $this;
    }

    /**
     * Get total count.
     *
     * @return int
     */
    public function getTotalCount()
    {
        return $this->getSize();
    }

    /**
     * Set total count.
     *
     * @param int $totalCount
     *
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function setTotalCount($totalCount)
    {
        return $this;
    }

    /**
     * Set items list.
     *
     * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items
     *
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function setItems(array $items = null)
    {
        return $this;
    }
}

?>
Ekta Puri
fonte
Ele não estava funcionando
saravanavelu
funciona bem para mim .. qual é o erro para você?
Ekta Puri
Erro do Servidor Interno. você pode verificar e reformatar seu código
saravanavelu
posso ver seus arquivos em algum lugar? porque isso funcionou perfeitamente para mim, ainda vou novamente tentar reformatar
Ekta Puri
etc / di.xml Modelo / ModuleName / coleção / Resource não há nada como neste em di.xml
saravanavelu
2

No xml de definição de interface do usuário, há um nó de fonte de dados semelhante a este

<dataSource name="listing_name_data_source">
    <argument name="dataProvider" xsi:type="configurableObject">
        <argument name="class" xsi:type="string">UniqueNameGridDataProvider</argument>
        <argument name="name" xsi:type="string">listing_name_data_source</argument>

onde listing_name_data_sourcepode ser definido no seu di.xmlou apenas referenciar uma classe diretamente. A própria classe deve estender Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactorye ter como collectionsargumento sua coleção personalizada. No _initSelect()método dessa classe de coleção, você pode juntar suas tabelas.

Kristof na Fooman
fonte
1
em sales di.xml, ele mostra Magento \ Sales \ Model \ ResourceModel \ Order \ Grid \ Collection onde esse arquivo não sai; nesse caso, não podemos reescrever o plug-in ou evento, ou como fazê-lo, verifique sales di e order código da coleção grid, eu espero que irá limpar mais
Pradeep Kumar
É definido aqui github.com/magento/magento2/blob/develop/app/code/Magento/Sales/… e é um tipo virtual que se estende de Magento \ Framework \ View \ Element \ UiComponent \ DataProvider \ SearchResult
Kristof em Fooman
em seguida, ho para adicionar juntar-se a esse class.can você dá exemplo de código
Pradeep Kumar
aqui como um exemplo de associação github.com/magento/magento2/blob/develop/app/code/Magento/… conforme usado neste initSelecione github.com/magento/magento2/blob/develop/app/code/Magento/…
Kristof em Fooman
@KristofatFooman você deu um exemplo errado porque é um tipo virtual. Você poderia dar um exemplo para a coleção de grades definida como tipo virtual?
LucScu
2

Para qualquer pessoa que tenha problemas com a solução @Asrar , faça o seguinte:

public function aroundGetReport(
    \Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory $subject,
    \Closure $proceed,
    $requestName
) {
    $result = $proceed($requestName);
    if ($requestName == 'sales_order_grid_data_source_firsty') {
        if ($result instanceof $this->collection
        ) {
            $select = $this->collection->getSelect();
            $select->join(
                ["soi" => "sales_order_item"],
                'main_table.entity_id = soi.order_id',
                array('sku', 'name','item_id')
            )
                ->distinct();
            return $this->collection;
        }

    }
    return $result;
}

Isso parece estar funcionando bem para mim.

vbak
fonte