Ajouter ou supprimer des colonnes de la grille commandes sans surcharge

  • De le 14 octobre 2014
  • Difficulté : 2/4

Ajouter ou supprimer des colonnes de la grille commandes sans surcharge L'objectif est d'ajouter de nouvelles colonnes à la grille des commandes du backoffice, sans surcharge. Nous ajoutons 2 nouvelles colonnes : la méthode de livraison et le pays de livraison. Par la même occasion, nous verrons comment désactiver les colonnes de la grille de base.

L'objectif est d'ajouter de nouveaux attributs à la grille des produits, sans surcharger la classe Mage_Adminhtml_Block_Sales_Order_Grid, et en évitant les jointures assez lourdes entre les tables.

Depuis Magento 1.4, le modèle utilisé n'est plus de type sales/order, mais sales/order_grid. Il m'arrive souvent de trouver des jointures entre les différentes tables pour afficher les colonnes souhaitées. Cela va un peu à l'encontre de ce qu'a souhaité faire Magento en implémentant ce système : alléger la grille.

Nous afficherons dans la grille 2 nouveaux attributs : shipping_description et shipping_country_id.

Order Grid

Architecture du module

Développement du module

De la même manière que pour la grille des produits (Ajouter des colonnes à la grille produits sans surcharge), nous utiliserons l'événement core_block_abstract_to_html_before pour ajouter les colonnes.

La petite particularité pour les commandes est que l'information à afficher doit être présente dans la table sales_flat_order_grid, puisque c'est le modèle de type sales/order_grid qui est utilisée. Il va ainsi falloir ajouter des colonnes dans cette table.

Le principe est assez simple, si la colonne du même nom est présente dans la table sales_flat_order, il n'y a rien d'autre à faire que d'ajouter la colonne : un "INSERT FROM SELECT" est réalisé entre les 2 tables. C'est le cas par exemple pour shipping_description.

Dans le cas où la donnée provient d'une autre table, un observer sur l'événement sales_order_resource_init_virtual_grid_columns est obligatoire dans le but de récupérer la colonne depuis la table souhaitée. Pour la colonne shipping_country_id l'information provient de la table sales_flat_order_address, il faut donc ajouter une jointure au moment où Magento alimente la table sales_flat_order_grid (c'est à dire à la création ou modification de la commande).

Pour schématiser :

Order Grid Schema

Un dernier événement nous permettra de désactiver les colonnes non désirées.

Nous pouvons alimenter le fichier de configuration du module :

app/code/local/Magentix/OrderColumns/etc/config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Magentix_OrderColumns>
            <version>0.1.0</version>
        </Magentix_OrderColumns>
    </modules>
    <global>
        <models>
            <order_columns>
                <class>Magentix_OrderColumns_Model</class>
                <resourceModel>order_columns_setup</resourceModel>
            </order_columns>
        </models>
        <resources>
            <order_columns_setup>
                <setup>
                    <module>Magentix_OrderColumns</module>
                    <class>Mage_Core_Model_Resource_Setup</class>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </order_columns_setup>
        </resources>
        <events>
            <!-- Add virtual grid column -->
            <sales_order_resource_init_virtual_grid_columns>
                <observers>
                    <order_columns_add_virtual_grid_column>
                        <model>order_columns/observer</model>
                        <method>addVirtualGridColumn</method>
                    </order_columns_add_virtual_grid_column>
                </observers>
            </sales_order_resource_init_virtual_grid_columns>
        </events>
    </global>
    <adminhtml>
        <events>
            <!-- Add columns -->
            <core_block_abstract_to_html_before>
                <observers>
                    <sales_order_add_columns_to_order_grid>
                        <class>order_columns/observer</class>
                        <method>addColumnsToOrderGrid</method>
                    </sales_order_add_columns_to_order_grid>
                </observers>
            </core_block_abstract_to_html_before>
            <!-- Remove columns -->
            <adminhtml_block_html_before>
                <observers>
                    <sales_order_remove_columns>
                        <class>order_columns/observer</class>
                        <method>removeOrderGridColumns</method>
                    </sales_order_remove_columns>
                </observers>
            </adminhtml_block_html_before>
        </events>
    </adminhtml>
</config>

Il nous faut ensuite ajouter les nouvelles colonnes à la table sales_flat_order_grid :

app/code/local/Magentix/OrderColumns/sql/order_columns_setup/mysql4-install-0.1.0.php

<?php

$installer = $this;

$installer->startSetup();

/* Shipping Description */
$installer->getConnection()->addColumn(
    $this->getTable('sales/order_grid'), 'shipping_description', 'VARCHAR(255) NULL'
);
$installer->getConnection()->addKey(
    $this->getTable('sales/order_grid'), 'shipping_description', 'shipping_description'
);

/* Shipping Country Id */
$installer->getConnection()->addColumn(
    $this->getTable('sales/order_grid'), 'shipping_country_id', 'VARCHAR(2) NULL'
);
$installer->getConnection()->addKey(
    $this->getTable('sales/order_grid'), 'shipping_country_id', 'shipping_country_id'
);

$installer->endSetup();

La suite se passe dans la classe Magentix_OrderColumns_Model_Observer, où nous ajoutons 4 méthodes :

app/code/local/Magentix/OrderColumns/Model/Observer.php

<?php

class Magentix_OrderColumns_Model_Observer
{

    protected function _getColumns()
    {
        /* Afficher */
    }

    public function addColumnsToOrderGrid(Varien_Event_Observer $observer)
    {
        /* Afficher */
    }

    public function removeOrderGridColumns(Varien_Event_Observer $observer)
    {
        /* Afficher */
    }

    public function addVirtualGridColumn(Varien_Event_Observer $observer)
    {
        /* Afficher */
    }

}

_getColumns

Cette méthode contient les données des colonnes à ajouter.

app/code/local/Magentix/OrderColumns/Model/Observer.php

    /**
     * Retrieve new columns information
     *
     * @return array
     */
    protected function _getColumns()
    {
        return array(
            'shipping_description' => array( // Column name
                'data' => array( // Column data
                    'header' => Mage::helper('sales')->__('Shipping'),
                    'index'  => 'shipping_description',
                ),
                'after' => 'shipping_name', // After column code (string or null)
            ),
            'shipping_country_id' => array( // Column name
                'data' => array( // Column data
                    'header' => Mage::helper('sales')->__('Country'),
                    'index'  => 'shipping_country_id',
                    'type'   => 'country',
                ),
                'after' => 'shipping_description', // After column code (string or null)
            ),
        );
    }

addColumnsToOrderGrid

Cette méthode ajoute au bloc chargé du rendu de la grille les colonnes définies dans la méthode _getColumns.

app/code/local/Magentix/OrderColumns/Model/Observer.php

    /**
     * Add columns to order grid
     *
     * @param Varien_Event_Observer $observer
     *
     * @return Magentix_OrderColumns_Model_Observer
     */
    public function addColumnsToOrderGrid(Varien_Event_Observer $observer)
    {
        /* @var $block Mage_Core_Block_Abstract */
        $block = $observer->getEvent()->getBlock();

        if ($block instanceof Mage_Adminhtml_Block_Sales_Order_Grid) {
            /* @var $block Mage_Adminhtml_Block_Sales_Order_Grid */

            $columns = $this->_getColumns();

            foreach($columns as $attribute => $column) {

                /* Add Column */
                if($column['after']) {
                    $block->addColumnAfter($attribute, $column['data'], $column['after']);
                } else {
                    $block->addColumn($attribute, $column['data']);
                }

            }

        }

        return $this;
    }

Nous avions déjà utilisé cette technique dans un précédent article pour la grille des produits. Elle peut être adaptée à n'importe quelle grille.

addVirtualGridColumn

Nous pouvons ensuite réaliser la jointure entre les tables pour que la colonne shipping_country_id puisse être correctement alimentée.

app/code/local/Magentix/OrderColumns/Model/Observer.php

    /**
     * Add virtual Grid columns
     *
     * @param Varien_Event_Observer $observer
     *
     * @return Magentix_OrderColumns_Model_Observer
     */
    public function addVirtualGridColumn(Varien_Event_Observer $observer)
    {
        /* @var $resource Mage_Sales_Model_Resource_Order_Abstract */
        $resource = $observer->getEvent()->getResource();

        $resource->addVirtualGridColumn(
            'shipping_country_id',
            'sales/order_address',
            array(
                'shipping_address_id' => 'entity_id'
            ),
            'country_id'
        );

        return $this;
    }

A ce stade, pour chaque nouvelle commande, les nouvelles informations seront affichées dans la grille des commandes.

Prenez garde au nom de l'alias et au nom de la colonne, respectivement shipping_country_id et country_id. Une erreur bloque tout simplement l'ajout d'une nouvelle commande.

removeOrderGridColumns

Cette méthode appelée sur l'événement adminhtml_block_html_before est utile si vous souhaitez désactiver des colonnes proposées de base par Magento. La méthode est simpliste.

Vous trouverez le nom des colonnes de la grille dans la classe Mage_Adminhtml_Block_Sales_Order_Grid : real_order_id, store_id, created_at, billing_name, shipping_name, base_grand_total, grand_total, status.

app/code/local/Magentix/OrderColumns/Model/Observer.php

    /**
     * Remove column from order grid
     *
     * @param Varien_Event_Observer $observer
     *
     * @return Magentix_OrderColumns_Model_Observer
     */
    public function removeOrderGridColumns(Varien_Event_Observer $observer)
    {
        /* @var $block Mage_Core_Block_Abstract */
        $block = $observer->getEvent()->getBlock();

        if ($block instanceof Mage_Adminhtml_Block_Sales_Order_Grid) {
            /* @var $block Mage_Adminhtml_Block_Sales_Order_Grid */

            $block->removeColumn('billing_name');
            $block->removeColumn('base_grand_total');

        }

        return $this;
    }

Cette technique peut être également utilisée pour la suppression de colonnes de n'importe quelle grille.

Pour finir, le fichier de déclaration du module :

app/etc/modules/Magentix_OrderColumns.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Magentix_OrderColumns>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Adminhtml />
                <Mage_Sales />
            </depends>
        </Magentix_OrderColumns>
    </modules>
</config>

Bonus : alimenter les colonnes des commandes existantes

Une fois le module en place, les nouvelles informations n'apparaîtront que pour les nouvelles commandes. Pour alimenter la table sales_flat_order_grid avec les données des commandes existantes, vous pouvez vous inspirer des requêtes suivantes :


UPDATE `sales_flat_order_grid` g
    SET `shipping_description` = (
        SELECT `shipping_description`
        FROM `sales_flat_order` o
        WHERE o.`entity_id` = g.`entity_id`
    );

UPDATE `sales_flat_order_grid` g
    SET `shipping_country_id` = (
        SELECT `country_id`
        FROM `sales_flat_order_address` d
        WHERE d.`parent_id` = g.`entity_id` AND d.`address_type` = 'shipping'
    );

A exécuter une fois, directement dans la base ou depuis un setup.

commentaires

Commentez cet article : Ajouter ou supprimer des colonnes de la grille commandes sans surcharge