Module Magento : Ajouter un commentaire à une commande

Pour mon premier billet sur ce blog, je vais aborder un sujet qui revient souvent sur les forums Magento, mais restant cependant sans réponse satisfaisante :

Comment permettre aux clients d'ajouter un commentaire (ou tout autre information) à une commande ?

Commentaire de la commande

Pour cela, il y a trois étapes :

  1. Stocker l'information en base de données (et la récupérer...) ;
  2. Ajouter une étape dans le processus de validation de la commande (checkout) ;
  3. Ajouter un onglet dans la visualisation de la commande, côté administration.

Création d'un module

Architecture du module

Les sources sont disponibles à la fin de cette article sous licence WTFPL.

Stocker l'information en base de données

Stockage des données

Notre module utilise une table, "netapsys_ordercom", dans la base de données. Cette table est créée via le fichier d'installation mysql4-install-0.1.0.php dans "sql/ordercom_setup".

$installer = $this;
$installer->startSetup();

$installer->run("
-- DROP TABLE IF EXISTS {$this->getTable('netapsys_ordercom')};
CREATE TABLE {$this->getTable('netapsys_ordercom')} (
  `order_id` int(10) unsigned NOT NULL,
  `content` text NOT NULL default '',
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
");

$installer->endSetup();

Modifiez ce script sql si vous voulez ajouter d'autres informations à votre commande.
Pour forcer la réinstallation d'un module, supprimer la ligne correspondante dans la table "core_resource".

On doit ensuite définir notre modèle dans "Model/Mysql4/Ordercom.php". Dans cette classe, on indique quelle est la table à utiliser (définie dans le config.xml), et la clé primaire (ici "order_id");

class Netapsys_Ordercom_Model_Mysql4_Ordercom extends Mage_Core_Model_Mysql4_Abstract {
	public function _construct(){
		$this->_init('ordercom/ordercom', 'order_id');
		$this->_isPkAutoIncrement = false;		
	}
}

L'attribut "isPkAutoIncrement" est ici essentiel, car nous voulons nous même définir la valeur de cette clé, à savoir l'id de la commande. Cette attribut doit donc être défini à "false".

Ajouter une étape dans le checkout

Checkout

Notre étape est définie dans "Block/Onepage/Ordercom.php". C'est dans cette classe que l'id et le nom de l'étape est indiqué ("ordercom" et "Commentaire").

class Netapsys_Ordercom_Block_Onepage_Ordercom extends Mage_Checkout_Block_Onepage_Abstract
{
    protected function _construct()
    {    	
        $this->getCheckout()->setStepData('ordercom', array(
            'label'     => Mage::helper('checkout')->__('Commentaire'),
            'is_show'   => true
        ));
        
        parent::_construct();
    }
}

Une fois l'étape créée, il faut encore l'insérer dans le checkout. On surcharge donc la classe "Mage_Checkout_Block_Onepage" dans le fichier "Block/Onepage.php"

class Netapsys_Ordercom_Block_Onepage extends Mage_Checkout_Block_Onepage
{
    public function getSteps()
    {
        $steps = array();

        if (!$this->isCustomerLoggedIn()) {
            $steps['login'] = $this->getCheckout()->getStepData('login');
        }
		
        //Ajouter notre étape 'ordercom'
        $stepCodes = array('billing', 'shipping', 'shipping_method', 'payment', 'ordercom', 'review');

        foreach ($stepCodes as $step) {
            $steps[$step] = $this->getCheckout()->getStepData($step);
        }
        
        return $steps;
    }
}

Nous allons maintenant surcharger le controleur de cette page checkout pour deux raisons :

  1. rediriger vers notre étape après "Informations de paiement" ;
  2. sauvegarder nos informations en sessions.

Notre nouveau contrôleur se situe dans le fichier "Ordercom/Block/controllers/OnepageController.php".

La redirection se fait via la méthode savePaymentAction :

public function savePaymentAction()
{
  parent::savePaymentAction();

  //Rediriger vers notre étape Ordercom
  $redirectUrl = $this->getOnePage()->getQuote()->getPayment()->getCheckoutRedirectUrl();

  if (empty($result['error']) && !$redirectUrl) {
    $this->loadLayout('checkout_onepage_ordercom');
    $result['goto_section'] = 'ordercom';
  }
  if ($redirectUrl) {
    $result['redirect'] = $redirectUrl;
  }
  $this->getResponse()->setBody(Zend_Json::encode($result));
}

Pour la sauvegarde, avec le Onepage Checkout, les données de chaque étape sont stockées en session via ajax. Nous allons donc créer une méthode "saveOrdercomAction", qui récupère les données envoyées en POST :

public function saveOrdercomAction()
{
		$this->_expireAjax();
		if ($this->getRequest()->isPost()) {

			//Récuprer la valeur du formulaire
			$orderComment = $this->getRequest()->getPost('comment');
			Mage::getSingleton('core/session')->setNetapsysOrdercom(trim($orderComment));

			$result = array();

			$redirectUrl = $this->getOnePage()->getQuote()->getPayment()->getCheckoutRedirectUrl();
			if (!$redirectUrl) {
				$this->loadLayout('checkout_onepage_review');

				$result['goto_section'] = 'review';
				$result['update_section'] = array(
                    'name' => 'review',
                    'html' => $this->_getReviewHtml()
				);

			}

			if ($redirectUrl) {
				$result['redirect'] = $redirectUrl;
			}

			$this->getResponse()->setBody(Zend_Json::encode($result));
		}
}

Les données maintenant en session, il ne reste plus qu'à les sauvegarder dans la table une fois la commande validée ! Nous allons créer un hook lors de l'enregistrement de la commande.

public function hookToOrderSaveEvent()
{
  //Récupérer l'id de la commande
  $orderId = Mage::getSingleton('checkout/session')->getLastOrderId();

  //Lire nos données depuis la session
  $content = Mage::getSingleton('core/session')->getNetapsysOrdercom();
  $code = Mage::getSingleton('core/session')->getNetapsysOrdercode();

  if (($content != '') || ($code != '')){
    // Enregistrer tout le toutim en base
    $orderCom = Mage::getModel('ordercom/ordercom');
    $orderCom->setId($orderId);
    $orderCom->setData('content', $content );
    $orderCom->save();
  }
}

C'est presque fini, il faut encore créer le front de notre étape.
Pour cela, je vous laisse regarder les fichiers "/design/frontend/default/default/layout/ordercom.xml" et "/design/frontend/default/default/template/checkout/onepage/ordercom.phtml".

Enfin, une étape très importante pour que tout ça fonctionne ensemble : la configuration du fichier "etc/config.xml".
Vous devez définir le modèle, les blocks, la surchage du checkout, etc. Le fichier étant assez long, je ne le décris pas ici.

Passons maintenant à l'affichage de ces données dans le back office.

Ajouter un onglet dans la visualisation de la commande, côté administration.

Menu

Pour gérer le back office de notre module, nous avons besoin de 3 fichiers :

Le layout

Nous décrivons ici l'emplacement de notre onglet et le block le définissant :
"/app/design/adminhtml/default/default/layout/ordercom.xml"

<?xml version="1.0"?>
<layout version="0.1.0">

	<adminhtml_sales_order_view>
		<reference name="sales_order_tabs">
			<action method="addTab">
				<name>order_coms</name>
				<block>ordercom/adminhtml_sales_order_view_tab_view</block>
			</action>
		</reference>
	</adminhtml_sales_order_view>

</layout>

Le block

Ce block va récupérer la commande en cours de visualisation et permettre à la vue d'afficher le commentaire correspondant.
"/app/code/local/Netapsys/Ordercom/Block/Adminhtml/Sales/Order/View/Tab/View.php"

class Netapsys_Ordercom_Block_Adminhtml_Sales_Order_View_Tab_View
extends Mage_Adminhtml_Block_Template
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
	private $_orderCom = null;
	private $_order = null;

	protected function _construct()
	{
		parent::_construct();
		$this->setTemplate('sales/order/view/tab/ordercom.phtml');

		//Récupérer la commande en cours
		$this->_order = Mage::getModel('sales/order')->load($this->getRequest()->getParam('order_id'));

		//Récupérer les données de notre table selon l'id de la commande en cours
		$this->_orderCom = Mage::getModel('ordercom/ordercom')->load( $this->_order->getId() )->getData();
	}

	/**
	 * Récupérer le commentaire de la commande en cours
	 */
	public function getComment(){
		$comment = null;
		if ($this->_orderCom != null){
			$comment = $this->_orderCom["content"];
		}
		return  $comment;
	}

	/**
	 * ######################## TAB settings #################################
	 */
	public function getTabLabel(){return Mage::helper('sales')->__('Commentaire');}
	public function getTabTitle(){return Mage::helper('sales')->__('Commentaire');}
	public function canShowTab(){	return true;}
	public function isHidden(){return false;}
}

La vue

Notre vue va tout simplement afficher le commentaire donné par notre block.
"/app/design/adminhtml/default/default/template/sales/order/view/tab/ordercom.phtml"

<div class="entry-edit">
	<div class="entry-edit-head">
		<h4 class="icon-head head-edit-form fieldset-legend">
		<?php echo $this->getTabLabel() ?>
		</h4>
	</div>

	<div id="group_fields4" class="fieldset fieldset-wide">
		<div class="hor-scroll">
			<table class="form-list" cellspacing="0">
				<tbody>
					<tr>
						<td class="label"><label>Commentaire :</label></td>
						<td class="value"><textarea id="order_comment" style="height: 20em; width: 99%;" cols="5" rows="10" name="order[comment]" readonly="readonly"><?php echo $this->getComment(); ?></textarea>
						</td>
					</tr>
				</tbody>
			</table>

		</div>
	</div>
</div>

Vous avez maintenant le commentaire dans votre commande !

Commentaire de la commande

14 commentaires

  1. Bonjour, je souhaite afficher le champ commentaire dans le mail de commande, comment dois-je m’y prendre ? merci

  2. Fantastic items from you, man. I’ve remember your stuff previous to and you’re just extremely fantastic. I really like what you’ve obtained right here, certainly like what you’re saying and the way wherein you assert it. You’re making it enjoyable and you still take care of to keep it sensible. I can’t wait to learn much more from you. That is really a tremendous site.

  3. Fantastic items from you, man. I’ve remember your stuff previous to and you’re just extremely fantastic. I really like what you’ve obtained right here, certainly like what you’re saying and the way wherein you assert it. You’re making it enjoyable and you still take care of to keep it sensible. I can’t wait to learn much more from you. That is really a tremendous site.

  4. Superior day cool internet site! Guy. Outstanding. Outstanding. I most certainly will take note of your web site along with go ahead and take provides nourishment to also? I am fulfilled to look for loads of tips listed here in the posting, we really wish for figure out a lot more associated with this kind of regard, appreciate your expressing.

  5. Superior day cool internet site! Guy. Outstanding. Outstanding. I most certainly will take note of your web site along with go ahead and take provides nourishment to also? I am fulfilled to look for loads of tips listed here in the posting, we really wish for figure out a lot more associated with this kind of regard, appreciate your expressing.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.