Añadir campo a la tabla de pedidos en #Prestashop

publicado en: Prestashop, Tutoriales | 31

Era un tutorial que la verdad tenia pensado traer pronto porque me parece muy interesante, pero van saliendo novedades que quiero comentar y siempre lo iba dejando de lado, hasta que finalmente una petición a través de un comentario me ha hecho ponerme manos a la obra y traeros esta modificación.

La idea es muy sencilla, tenemos nuestra sección de pedidos dentro de nuestro backoffice en la que hay una lista con todos los pedidos que nos han realizado y lo que necesitamos es incluir el telefono del cliente en esa lista para poderlo consultar de una forma muy sencilla y rápida.

Antes de ponernos manos a la obra recordaros la importancia de que realiceis copias de seguridad de todo lo que vayamos a tocar para evitarnos problemas y sorpresas indeseadas, borrar o modificar algo donde no debemos va a provocar que nuestra tienda deje de funcionar.

Dicho esto vamos al lío. El archivo en cuestión que queremos modificar es /controllers/admin/AdminOrdersController.php como no queremos perder la funcionalidad en caso de actualizar nuestra tienda lo que vamos a hacer es crear un override para sobreescribir justo lo que vamos buscando.

Cogemos el archivo /controllers/admin/AdminOrdersController.php y lo copiamos en nuestra carpeta de overrides /override/controllers/admin/AdminOrdersController.php

Una vez lo tenemos en la carpeta de overrides vamos a modificarlo. Abrís el archivo y editais la definición de la clase para que se quede como sigue:

class AdminOrdersController extends AdminControllerCore

Con esto le decimos que extendemos la clase AdminControllerCore con las funciones que vamos a describir a continuación. Dentro del constructor buscais estas lineas

$this->_select = '
		a.id_currency,
		a.id_order AS id_pdf,
		CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) AS `customer`,
		osl.`name` AS `osname`,
		os.`color`,
		IF((SELECT COUNT(so.id_order) FROM `'._DB_PREFIX_.'orders` so WHERE so.id_customer = a.id_customer) > 1, 0, 1) as new';

Y las modificais de forma que se queden como a continuación

$this->_select = '
		a.id_currency,
		a.id_order AS id_pdf,
		CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) AS `customer`,
		osl.`name` AS `osname`,
		os.`color`,
		ad.phone_mobile as telefono,
		IF((SELECT COUNT(so.id_order) FROM `'._DB_PREFIX_.'orders` so WHERE so.id_customer = a.id_customer) > 1, 0, 1) as new';

Un poco más abajo buscais lo siguiente

$this->_join = '
		LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = a.`id_customer`)
		LEFT JOIN `'._DB_PREFIX_.'order_state` os ON (os.`id_order_state` = a.`current_state`)
		LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$this->context->language->id.')';

Y lo añadis una nueva linea que unirá las tablas para poder seleccionar el teléfono

$this->_join = '
		LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = a.`id_customer`)
		LEFT JOIN `'._DB_PREFIX_.'address` ad ON (ad.`id_address` = a.`id_address_delivery`)
		LEFT JOIN `'._DB_PREFIX_.'order_state` os ON (os.`id_order_state` = a.`current_state`)
		LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$this->context->language->id.')';

De esta forma ya hemos seleccionado el teléfono del cliente. Una apreciación que hay que tener en cuenta es que de esta forma si dispone de más de un teléfono únicamente veriamos en nuestra lista la primera ocurrencia que se recupere de la base de datos y no todos.

Con nuestro teléfono ya seleccionado de la base de datos vamos a mostrar los datos en nuestra lista de pedidos. Para ello tenemos que añadir ese campo teléfono a la lista de campos que ya hay. En este caso vamos a buscar el nombre del cliente para incluir el teléfono justo a continuación. Buscamos estas lineas

'customer' => array(
			'title' => $this->l('Customer'),
			'havingFilter' => true,
		),

Y justo seguido le añadimos nuestro campo teléfono tal y como sigue

'telefono' => array(
            'title' => $this->l('Telefono Ent.'),
            'width' => 220,
            'align' => 'ocultar'
        ),

De esta forma ya nos aparecerá en la lista de pedidos justo al lado del nombre del cliente.

 

Como no queremos sobreescribir nada más yo he eliminado las funciones que no estaba modificando de este archivo para que no se vean afectadas. Por lo tanto mi archivo dentro de la carpeta de overrides se ha quedado como os voy a enseñar, mucho más corto que el original

<?php
class AdminOrdersController extends AdminControllerCore
{
	public $toolbar_title;

	public function __construct()
	{
		$this->table = 'order';
		$this->className = 'Order';
		$this->lang = false;
		$this->addRowAction('view');
		$this->explicitSelect = true;
		$this->allow_export = true;
		$this->deleted = false;
		$this->context = Context::getContext();

		$this->_select = '
		a.id_currency,
		a.id_order AS id_pdf,
		CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) AS `customer`,
		osl.`name` AS `osname`,
		os.`color`,
		ad.phone_mobile as telefono,
		IF((SELECT COUNT(so.id_order) FROM `'._DB_PREFIX_.'orders` so WHERE so.id_customer = a.id_customer) > 1, 0, 1) as new';

		$this->_join = '
		LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = a.`id_customer`)
		LEFT JOIN `'._DB_PREFIX_.'address` ad ON (ad.`id_address` = a.`id_address_delivery`)
		LEFT JOIN `'._DB_PREFIX_.'order_state` os ON (os.`id_order_state` = a.`current_state`)
		LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$this->context->language->id.')';
		$this->_orderBy = 'id_order';
		$this->_orderWay = 'DESC';

		$statuses_array = array();
		$statuses = OrderState::getOrderStates((int)$this->context->language->id);

		foreach ($statuses as $status)
			$statuses_array[$status['id_order_state']] = $status['name'];

		$this->fields_list = array(
		'id_order' => array(
			'title' => $this->l('ID'),
			'align' => 'center',
			'width' => 25
		),
		'reference' => array(
			'title' => $this->l('Reference'),
			'align' => 'center',
			'width' => 65
		),
		'new' => array(
			'title' => $this->l('New'),
			'width' => 25,
			'align' => 'center',
			'type' => 'bool',
			'tmpTableFilter' => true,
			'icon' => array(
				0 => 'blank.gif',
				1 => array(
					'src' => 'note.png',
					'alt' => $this->l('First customer order'),
				)
			),
			'orderby' => false
		),
		'customer' => array(
			'title' => $this->l('Customer'),
			'havingFilter' => true,
		),
		'telefono' => array(
                    'title' => $this->l('Telefono Ent.'),
                    'width' => 220,
                    'align' => 'ocultar'
                 ),
		'total_paid_tax_incl' => array(
			'title' => $this->l('Total'),
			'width' => 70,
			'align' => 'right',
			'prefix' => '<b>',
			'suffix' => '</b>',
			'type' => 'price',
			'currency' => true
		),
		'payment' => array(
			'title' => $this->l('Payment: '),
			'width' => 100
		),
		'osname' => array(
			'title' => $this->l('Status'),
			'color' => 'color',
			'width' => 280,
			'type' => 'select',
			'list' => $statuses_array,
			'filter_key' => 'os!id_order_state',
			'filter_type' => 'int',
			'order_key' => 'osname'
		),
		'date_add' => array(
			'title' => $this->l('Date'),
			'width' => 130,
			'align' => 'right',
			'type' => 'datetime',
			'filter_key' => 'a!date_add'
		),
		'id_pdf' => array(
			'title' => $this->l('PDF'),
			'width' => 35,
			'align' => 'center',
			'callback' => 'printPDFIcons',
			'orderby' => false,
			'search' => false,
			'remove_onclick' => true)
		);

		$this->shopLinkType = 'shop';
		$this->shopShareDatas = Shop::SHARE_ORDER;

		if (Tools::isSubmit('id_order'))
		{
			// Save context (in order to apply cart rule)
			$order = new Order((int)Tools::getValue('id_order'));
			if (!Validate::isLoadedObject($order))
				throw new PrestaShopException('Cannot load Order object');
			$this->context->cart = new Cart($order->id_cart);
			$this->context->customer = new Customer($order->id_customer);
		}

		parent::__construct();
	}
	public function printPDFIcons($id_order, $tr)
	{
		$order = new Order($id_order);
		$order_state = $order->getCurrentOrderState();
		if (!Validate::isLoadedObject($order_state) || !Validate::isLoadedObject($order))
			return '';

		$this->context->smarty->assign(array(
			'order' => $order,
			'order_state' => $order_state,
			'tr' => $tr
		));

		return $this->createTemplate('_print_pdf_icon.tpl')->fetch();
	}

}

De esta forma lograriamos mostrar el teléfono para tenerlo mucho más accesible.

Espero que esta modificación os haya servido de ayuda y no os hata costado mucho realizarla. Como siempre os espero por aqui para nuevos trucos y recordaros que vuestros comentarios son bienvenidos.

31 comentarios

  1. Juan Pablo

    Hola! Muchas gracias!! Lo acabo de probar y funciona perfectamente! hay que tener en cuenta que, como tu dices, en el campo nuevo aparece el primer teléfono que ponga el cliente (el principal), si el cliente se registra y solo pone uno secundario (como un numero de móvil) debes modificarlo tu desde el backoffice y ponerlo como principal para que aparezca.

    Otra vez gracias, eres un crack, me gustaría saber hacer estas cosas por mi mismo, estudiare php 🙂

    Una duda, ¿como sabes que archivo hay que modificar? porque antes de pedirtelo intente hacerlo yo, pero no sabia ni siquiera en que archivo de prestashop se creaba la tabla de pedidos…

    Gracias!

    PD: Se te puede pedir una cosa mas?

    • dwalins

      Me alegra que te funcione tan bien y sobre todo que le hayas pillado el truco por si tiene más números de teléfono.
      Saber que archivo hay que modificar si es más dificil de explicar, tienes sobre todo que conocerte como está hecho en este caso Prestashop y a partir de ahi por los nombres de los archivos vas viendo, eso sumado a tener conocimientos de programación te va a permitir encontrar donde realizar las modificaciones.

      Viendo que tu anterior petición era bastante interesante para la mayoria de tiendas pide y veremos que se puede hacer 😉

    • Juan Pablo

      Vale pues mira, en el mismo prestashop, el 1.5.6, cuando vas a la pestaña pedidos->facturas te da la opción de descargar un PDF con todas las facturas, ya sea por fecha o por estado. El problema es que lo que prestashop hace es poner un PDF enorme donde cada pagina es una factura y yo necesito que haga un PDF de 1 sola página con una tabla donde aparezca los datos de la factura. Tengo una tienda antigua donde me daba esta opción de listado, pero no la cree yo esa tienda y no se como lo hicieron..

      Te agrego un link de un tema de abrí en la comunidad de prestashop, donde me explico mejor (creo) y hay fotos.

      http://www.prestashop.com/forums/topic/384187-generar-un-listado-de-facturas-ps-156/?p=1881995

      Aver si puedes hacer algo! Gracias por ayudarme tanto 🙂

    • dwalins

      Bueno viendo el enlace entiendo que quieres conseguir. Yo te recomendaria la solución que te comenta ventura, es bastante cómoda y te da bastante libertad, puedes ver como hacerla aqui -> http://wp.me/p3tErX-s4
      Por otro lado veo que lo que tenias hera un archivo supongo que especialmente hecho para ti ubicado dentro de la carpeta de administración, llamado pdf.php. Si tienes acceso podrías acceder a ese archivo y tal vez puedas usarlo, aunque es posible que haya cambiado mucho y cueste adaptarlo.

      Depende un poco de que vayas necesitando, si no precisas que el listado sea un PDF como te digo la solución de ventura es muy buena y al tener los datos exportados a CSV te permite poder tratarlos, si por el contrario quieres que sea un PDF hay que modificar bastante para lograrlo y que se quede bien integrado.

      Por otro lado te recomendaría que editases tu hilo creado en prestashop y que no se vieran los datos de los clientes en la factura de ejemplo que has subido, ya que esto no es muy correcto y podria ocasionarte algún problema. Con eliminar esa imagen o simplemente recortarla para que sólo se vea la cabecera de la tabla es suficiente.

      Espero haberte sido de ayuda 😉

  2. Juan Pablo

    Hola de nuevo! Tengo un problema urgente y lo escribo aquí porque a lo mejor tiene algo que ver con esto. Tengo un tema abierto en el foro de prestashop:

    http://www.prestashop.com/forums/topic/391555-urgente-no-me-funciona-el-apartado-de-pedidos/

    Me había funcionado bien hasta ahora, no se si es porque modifique el archivo AdminOrdersControllers mal o algo (que no creo, seguí el tutorial paso a paso y con cuidado) pero por si acaso te lo enseño y si sabes como solucionarlo mejor!

    Gracias y Feliz año 2015!

    • dwalins

      Hola Juan Pablo,

      ¿Que error te aparece cuando activas el modo debug? Te recomiendo que pruebes a volver a subir un archivo «limpio» para comprobar si el error es de ahi o viene por otro lado; baja la misma versión que tengas instalada y resube ese archivo en concreto a ver que pasa.

      Ya nos cuentas si se resuelve.

      Un saludo y feliz año!!

    • Juan Pablo

      Cuando activo el modo debug no me aparece nada, en otros lugares de la pagina si me aparecen algunos errores, pero cuando clico en pedidos no sale nada, esta igual, todo en blanco y con el texto «volver a pedidos». He probado de subir un archivo sin modificar (guardo una copia de antes de modificar un archivo) y no se soluciona, lo raro es que subo el archivo AdminOrdersControllers sin modificar pero sigue apareciendo la columna de teléfono, no se si eso es normal… pero bueno llamare a mi hosting a ver si pueden hacer algo.

      Gracias por tu atencion!

    • dwalins

      No es normal que te siga apareciendo cuando supuestamente ya no está esa modificación, puede tratarse sin duda de la caché. Con el archivo original subido te recomiendo que abras tu FTP y dentro de la carpeta cache elimines un archivo que se llama class_index.php para eliminar la caché.
      Con esto si es problema de ese archivo, se debería solucionar al momento, pruebalo y me comentas a ver que tal.

      Un saludo!

    • Juan Pablo

      Sigue apareciendo, he eliminado el archivo que dices y en el backoffice también esta desactivado el uso de cacho y la he limpiado desde ahí, no se porque sera. Me ha contestado mi hosting y me han dado esta información:
      ///
      Hemos revisado el error que nos comenta, y todo apunta a un fallo en la
      template, es probable que en el archivo order-detail.tpl.

      Revisad este punto, es muy probable que sea el cierre de alguna línea o
      función (que falte un } o un comilla simple, por ejemplo).

      Lo más fácil es restaurar los archivos originales de la template para
      localizar el fallo.
      ///

      Que quiere decir los archivos de la template? He puesto el archivo order-details.tpl original (aunque no lo había modificado) y el error sigue, no se que hacer 🙁

    • Juan Pablo

      Vale, Error mio, estaba suiendo el archivo sin editar AdminOrdersControllers pero en la carpeta equivocada (Admin/controllers/AdminOrdersControllers) y el archivo modificado estaba en otra (overrides/controllers/..)

      Al modificar el archivo el error a desaparecido, ahora solo queda saber porque con el archivo modificado pasa ese error y porque ha pasado casi 1 mes despues de modificarlo.

      Gracias por tu ayuda!

    • Juan Pablo

      He subido el archivo modificado directamente a controllers/admin y parece que funciona todo correctamente otra vez, con la columna del telefono y tal, pero bueno, si vuelve a pasar ya se arreglarlo 🙂

    • Juan Pablo

      Y Feliz año a ti tambien ! 😀 , se me olvidaba jaja

  3. Juan Pablo

    Hola Dwalins! Sabes si esto funciona igual para prestashop 1.6?? aun no lo he probado, lo probare pronto.

    • dwalins

      Hola Juan Pablo,
      Pues acabo de revisarlo y han simplificado el tutorial. Ahora no es necesario hacer la parte los LEFT JOINS. Únicamente hay que añadir a la consulta que ya hay de serie esto address.phone, se quedaria algo asi:
      $this->_select = '
      a.id_currency,
      a.id_order AS id_pdf,
      CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) AS `customer`,
      osl.`name` AS `osname`,
      os.`color`,
      address.phone,
      IF((SELECT COUNT(so.id_order) FROM `'._DB_PREFIX_.'orders` so WHERE so.id_customer = a.id_customer) > 1, 0, 1) as new,
      country_lang.name as cname,
      IF(a.valid, 1, 0) badge_success';

      Y acabar con la parte que añades el campo telefono a la lista. Pruebalo y si tienes dudas me comentas.

      Un saludo

    • Juan Pablo

      Podrías hacer un tutorial para PS 1.6?? es que no me queda claro 🙁 y en esta versión de prestashop en la tabla de pedidos aparece un campo «Entrega» donde, por lo menos a mi, me aparece el País del cliente que no me sirve de mucho ya que solo vendemos en España, prefiero que me aparezca la provincia por ejemplo y no se muy bien donde modificar esto.

      Gracias!

    • dwalins

      Hola Juan Pablo,

      Voy a echar un vistazo a ver que cambia en la versión 1.6 y os lo comento 😉

    • Juan Pablo

      Ya lo he conseguido 🙂

      Como me habías puesto en un comentario, he puesto el address.phone y luego directamente lo he añadido en la tabla y ya aparece, al principio no me funcionaba y cuando lo he vuelto a intentar me ha funcionado perfectamente, el único cambio que veo con respecto el primer intento es que en la primera linea tenia esto: «class AdminOrdersControllerCore extends AdminControllerCore» y ahora tengo esto «class AdminOrdersControllerCore extends AdminController» he quitado el segundo Core, no se si tendría algo que ver, pero así funciona xD

      Con respecto a lo del campo Entrega, lo que he hecho a sido eliminar esa columna y agregar una nueva con address.city, donde me aparece la ciudad del cliente y eso si que es información mas útil

      Gracias!

    • dwalins

      Hola Juan Pablo,

      Veo que te me has adelandato, yo estaba intentando dejarlo todo integrado en un módulo pero me está dando problemas. Efectivamente el segundo Core sobra.

      Me alegra ver que has podido solucionar el problema 😀

      Un saludo

  4. Carlos

    Hola dwalins, muchas gracias por el tutorial.
    He seguido al pie de la letra todo, pero no me funciona en PS 1.6.0.8.
    También he probado a simplificar el archivo como paso final, al igual que has hecho tú, dejando las mismas líneas que tú. Pero nada.
    Activando el modo debug [define(‘_PS_MODE_DEV_’, true);] me arroja el siguiente error:

    syntax error, unexpected ‘as’ (T_AS) in AdminOrdersController.php on line 29:
    Call Stack
    # Time Memory Function Location
    1 0.0004 265288 {main}( ) ..\index.php:0
    2 0.1570 10402400 DispatcherCore->dispatch( ) ..\index.php:54
    3 0.1662 10778000 ControllerCore::getController( ) ..\Dispatcher.php:366
    4 0.1662 10778472 PrestaShopAutoload->load( ) ..\Dispatcher.php:0

    ¿Sabes a qué puede ser debido?
    Muchas gracias de nuevo.

    • dwalins

      Hola Carlos,

      Revisa la consulta por que no se si te está cogiendo algo más o te está cerrando antes de tiempo dejando algo fuera, de todas formas voy a comprobarlo en la versión última que haya de Prestashop a ver si funciona bien o si es necesario incluir algún cambio.

      Un saludo!

  5. Miguel Angel

    Hola, magnifico tutorial, me ha servido de mucho. Pero tengo un pequeño problema, al hacer las modificaciones me sale el mismo pedido del mismo cliente repetido varias veces y con varios teléfonos.

    • Miguel Angel

      Haciendo varias pruebas el error debe ser en la linea

      LEFT JOIN `’._DB_PREFIX_.’address` ad ON (c.`id_customer` = ad.`id_customer`)

      el porque escapa de mis conocimientos, jaja.

    • dwalins

      Hola Miguel Angel,
      Si estás usando la versión 1.6 de Prestashop es muy posible que esta consulta la hayan modificado un poco y por eso al unir las tablas para sacar los datos te saca varios resultados iguales, ¿te sucede con todos o sólo con los que tienen varios teléfonos?

    • Miguel Angel

      Hola dwalins,
      Estoy usando la version 1.5.4.1 y me pasa solo con algunos clientes da igual que tengan dos teléfonos que uno. He probado incluso a quitar la linea ad.phone, hace la consulta sin mostrar datos pero sigue duplicando algunos pedidos.

    • dwalins

      Hola Miguel Ángel,

      El error parecía estar en el número de direcciones, he realizado unos cambios y ya no debería darte problema, pruebalo y me comentas!

    • Miguel Angel

      Hola dwalins,

      Muchas gracias, simplemente cambiando la linea que has puesto ahora
      LEFT JOIN `’._DB_PREFIX_.’address` ad ON (ad.`id_address` = a.`id_address_delivery`)
      funciona todo perfecto.

      Gracias de nuevo, un saludo.

  6. Gerardo

    Hola! Muchas gracias, me ha sido muy util para entender el funcionamiento del feedback entre el back y la bd. Ahora, en base a la experiencia de uso le haría otras modificaciones más. A ver si me puedes hechar una mano con hacerle más cambios..

    A mi criterio, el listado debería tener información primaria, para poder hacer el despacho más ágil. Por ejemplo, que el cliente sea nuevo, o los ítems ENTREGA y PAGO, son secundarios. Y por otra parte, si el transporte es en 24 horas, eso es información primaria. Entonces, propongo lo siguiente como información de primera vista:

    ID | Referencia | Cliente | Total | TRANSPORTISTA | Estado | Fecha | PDF

    De esta manera, se ve a simple vista los envíos prioritario que son en 24 horas por ejemplo.
    Entrega es reemplazado por Transportista, y Pago es innecesario, ya que nos informamos por el estado -«PAGO ACEPTADO» por ejemplo-.

    Ahora bien, como eliminio Entrega y pago; y como agrego la información de Transportista?
    Gracias!
    Gerardo

    • dwalins

      Hola Gerardo,

      Me alegra que te sea de utilidad. En el caso que propones sería necesario modificar la consulta a la base de datos para solicitar el transportista, en este caso en concreto deberias hacer un JOIN con la tabla order_carrier para que te diga el id del transportista que tiene asignado el pedido, si en lugar de aparecer el id del transportista quieres que salga su nombre además deberas unir esa tabla con carrier para asi obtener el campo name. Para que te aparezca el transportista puedes hacerlo siguiendo el método que explico aqui para añadir el teléfono.

      En cuanto a eliminar la parte de pago tan solo tienes que quitar la definición de payment de la lista.

      No debería resultarte dificil conseguirlo.

      Un saludo

  7. EgorTrunc

    Вечером изучал контент инет, случайно к своему удивлению заметил прекрасный ресурс. Это он: https://omoikiri-japan.ru/ . Для нас данный ресурс явился довольно неплохим. Успехов всем!

  8. elena

    Hola, ¿alguien sabría cómo añadir el EAN13 del producto o combinación en la tabla del pedido del BO??

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *