Necesitas mi libro "Claves para abrir una tienda online y que venda" y lo sabes...


¿Quieres comprarlo en otro sitio?

Amazon | Casa del Libro

Error Prestashop al aplicar descuentos en categorias

PROBLEMA: los descuentos por categoría en grupos de clientes no se aplican en Prestashop.

Si hay un descuento aplicado de forma general a un grupo de clientes sí se aplican, pero si se quiere segmentar todavía más estableciendo un descuento específico por categoría para un grupo de clientes, este descuento no se aplica.

Parece que es un bug común a varias versiones pero que no es muy conocido debido aparentemente a que este nivel de parametrización no lo demandan muchos usuarios.

En el caso de la versión 1.4.7 no me han servido las soluciones propuestas en (las incluyo también por si a alguien sí le sirvieran...):


Aunque sí me pusieron en la pista para crear mi propio parche, modificar classes/Product.php (lineas 1901-1912)

// Group reduction
if ($use_groupReduction)
{
//Descuentos por categoria
$sql = 'SELECT `reduction` FROM `'._DB_PREFIX_.'group_reduction`
WHERE `id_group` = '.$id_group.' AND `id_category` = '.$_GET["id_category"];
if ($row = Db::getInstance()->getRow($sql))
   $price = $price *= ((100 - $row['reduction']) / 100);
else // apply group reduction if there is no group reduction for this category
$price *= ((100 - Group::getReductionByIdGroup($id_group)) / 100);
}

Con esta modificación, todo funciona como debería:

  • Grupo con descuento sin especificar categorías -> Se aplica el descuento general del grupo
  • Grupo con o sin descuento general pero especificando categorías -> Sólo se aplica el descuento de categoría

Como curiosidad, el error salió al revisar un mantenimiento externo de grupos de clientes para asociarles un código de apadrinamiento que pudieran utilizar en el momento del registro, y así asociarlos desde el inicio al grupo y por tanto que pudiera beneficiarse de los descuentos del mismo en su primera compra, sin esperar a que tener que ser asociado "a mano" a un grupo posteriormente desde el backoffice.



Organización de las categorías en Prestashop

Las categorías en Prestashop se organizan internamente con el "nested set model"  o modelo de conjunto anidado.

Es un algoritmo de recorrido de árbol o jerarquías y es una forma de almacenamiento de datos jerárquicas dentro de bases de datos relacionales.

Un árbol es una estructura de datos que contiene un número de nodos vinculados y un nodo padre puede conectarse a varios nodos secundarios, repitiéndose esta organización a través de varios niveles.

Cada nueva inserción, borrado o modificación implicar volver a numerar los nodos.

En versiones anteriores a Prestashop 1.6, se podían dejar en blanco los campos nLeft y nRight de la tabla ps_category, respetando el resto de campos imprescindibles como el id_parent y el level_depth, pero en la versión 1.6 si no se completan estos campos, las categorías no aparecerán en el frontoffice o parte pública, ni tampoco saldrán organizadas desde el backoffice en el formulario de alta de un artículo cuando se asocia a una categoría desde la opción de "Expand" o mostrar todo el árbol de categorías.

Cada elemento del árbol termina con dos valores, nLeft para la izquierda y nRight para la derecha, que se puede utilizar para identificarlos e indicar su relación con los otros elementos del árbol o estructura jerárquica. 

Por ejemplo, si una subcategoría X tiene un valor de 2 y 15 para nLeft y nRight respectivamente todos los nodos que con valores superiores a 2 y los valores inferiores a 15 son dependientes de la subcategoría X. 


Todo esto es un aspecto importante a tener en cuenta siempre que existan procesos externos de actualización o importación de artículos (en mi caso más de 2.000 categorías desde un ERP).

Si la inserción es puntual (ej: una importación de una estructura de catálogo), al modificar cualquier categoría desde el backoffice (aunque no se haya modificado realmente nada), se regeneran los valores de los campos nLeft y nRight, la función que se utiliza en este proceso es "regenerateEntireNtree"

El código de esta función "regenerateEntireNtree" está en classes/Category.php:

/**
              * Re-calculate the values of all branches of the nested tree
              */
            public static function regenerateEntireNtree()
            {
                       $id = Context::getContext()->shop->id;
                       $id_shop = $id ? $id: Configuration::get('PS_SHOP_DEFAULT');
                       $categories = Db::getInstance()->executeS('
                       SELECT c.`id_category`, c.`id_parent`
                       FROM `'._DB_PREFIX_.'category` c
                       LEFT JOIN `'._DB_PREFIX_.'category_shop` cs
                       ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.')
                       ORDER BY c.`id_parent`, cs.`position` ASC');
                       $categories_array = array();
                       foreach ($categories as $category)
                                   $categories_array[$category['id_parent']]['subcategories'][] = $category['id_category'];
                       $n = 1;

                       if (isset($categories_array[0]) && $categories_array[0]['subcategories'])
                                   Category::_subTree($categories_array, $categories_array[0]['subcategories'][0], $n);
            }

            protected static function _subTree(&$categories, $id_category, &$n)
            {
                       $left = $n++;
                       if (isset($categories[(int)$id_category]['subcategories']))
                                   foreach ($categories[(int)$id_category]['subcategories'] as $id_subcategory)
                                               Category::_subTree($categories, (int)$id_subcategory, $n);
                       $right = (int)$n++;

                       Db::getInstance()->execute('
                       UPDATE '._DB_PREFIX_.'category
                       SET nleft = '.(int)$left.', nright = '.(int)$right.'
                       WHERE id_category = '.(int)$id_category.' LIMIT 1');
            }





Referencias:

http://www.slickpalm.com/cual-es-el-modelo-anidado-set/
http://en.wikipedia.org/wiki/Nested_set_model

Módulo Prestashop para bloquear enlaces y visitas spam

Refererblocker es un módulo Prestashop (compatible versión 1.6) para bloquear los enlaces y visitas spam en tus estadísticas.

¿Qué son los "bad", "spam" o "fake" referrers que aparecen como fuentes de tráfico "reales" en Google Analytics?

Esos datos están distorsionando los datos de tu web respecto a las visitas reales y su origen, afectando asimismo a los objetivos que tengas configurados (ej: el ratio de conversión sería siempre superior ya el número de visitas que debería contarse para el cálculo es inferior si no se tienen en cuenta estas visitas spam).

Algunos ejemplos: semalt.com, darodar.com, free-share-buttons.com, buy-cheap-online.info, event-tracking.com...

PULSA PARA AMPLIAR
La solución a esta situación es bloquear estas visitas a través del archivo .htaccess y sus directivas, entre ellas, las de permitir o denegar el acceso a la web desde los dominios spam.

El módulo Refererblocker para Prestashop facilita y agiliza la actualización de este archivo con el bloqueo a dominios que estén generando tráfico spam.


PULSA PARA AMPLIAR




Cómo se crean lotes o packs en Prestashop

Para vender un lote o pack de productos compuesto por varios artículos (ej: teléfono móvil, cargador para automóvil y funda) hay que usar la funcionarlidad

El proceso para crear un pack es similar al utilizado para la creación de un producto normal:

1. Ir a la página "Producto" y bajo el menú "Catálogo".

2. Hacer clic en el botón "Añadir nuevo".

3. En la pestaña "Información" a la izquierda, cambiar el tipo de producto a "Pack de productos existentes".



A continuación aparecerán aparecerán nuevos campos en el formulario:

  • El primer campo se utiliza para buscar los productos que ya están registrados en su tienda.
  • El segundo campo se utiliza para indicar qué cantidad del producto seleccionado debe ser añadido al paquete.
  • El botón añade el producto al pack.


Observaciones:


  • El pack o lote puede tener un precio distinto –normalmente inferior- a la suma total de los productos que lo componen
  • En el carrito y en el pedido aparece la descripción (y referencia en su caso) del nombre del pack, no los productos que lo componen
  • Actualmente no se puede añadir combinaciones o productos virtuales a un pack.
  • Si necesitas tener packs con combinaciones, tendrás que crear productos únicos para cada combinación (esta es una limitación que será corregida en una próxima versión de PrestaShop…).
  • Se puede añadir un paquete existente en un nuevo pack, o importar el contenido de un paquete existente dentro de un nuevo pack.

Imagen del contenido del pack en la parte pública de la tienda o front

¿Dónde se guarda esta información en la base de datos?


La información de los lotes o pack se guarda en la tabla “PREFIX_pack”(prefix sería el prefijo de las tablas, normalmente “ps”), que tiene la siguiente estructura:

NOMBRE CAMPO
Observaciones
id_product_pack
“ id_product” del pack  en la tabla “ps_product”*
id_product_item
“id_product” del artículo asociado al pack id_product_pack
quantity
Cantidad del id_product asociado  al pack id_product_pack


* La información que se guarda del pack como producto es idéntica a cualquier otro producto excepto que en el campo “cache_is_pack” de la tabla “ps_product” tiene el valor “1”.

Error Unable to allocate memory for pool en Prestashop

Tanto si tienes el modo debug activado en Prestashop como si no, y se muestran mensajes similares a este:

Warning on line 1384 en archivo /var/www/vhosts/httpdocs/tienda/tools/smarty/Smarty.class.php
[2] require_once(): Unable to allocate memory for pool.



Es probable que tenga que ver el módulo  APC (Alternative PHP Cache) como apuntan aquí.




En mi caso, lo he desactivado directamente porque estoy usando "memcache" en vez de APC, pero también se puede cambiar la configuración del módulo de APC en PHP editando el php.ini con estos valores:

apc.shm_size:128MB
apc.ttl: 7200
apc.user_ttl: 7200
apc.gc_ttl: 3600



2 libros por menos de 5€

En la Semana del Día del Libro (20-26 de abril) puedes conseguir mis dos libros "Claves para abrir una tienda online y que venda" y "El SEO ha muerto" por menos 5€ en la Casa del Libro.

¡Aprovecha esta oportunidad!


http://www.casadellibro.com/lectores/misLibrosPublicados?idusuario=5574513&lang=es

Ocultar subcategorías en menu horizontal Prestashop

Si tienes muchas subcategorías de tercer nivel (ej: Coches > Marcas > Marca n) que hacen que el menú horizontal superior no sea manejable al mostrar las distintas subcategorías, tendrás que ocultar las subcategorías en menu superior horizontal modificando la hoja de estilos de tu plantilla (global.css en el directorio "css" correspondiente a tu plantilla en "themes").

La línea a incluir es:

.pt_custommenu div.pt_menu .itemSubMenu { display: none !important; }




ANTES


DESPUÉS


Mi fragmento código se queda así (actualización 15/01/16):

.pt_custommenu div.pt_menu.active a, #pt_menu_pt_item_menu_custom_menu.active .parentMenu span,#pt_menu_link a:hover, .pt_custommenu div.pt_menu.active .parentMenu a:hover{background-color: #fdfdfd; color: #00945E;}.pt_custommenu div.pt_menu.act a{background-color: #fdfdfd; color: #00945E;}.pt_custommenu div.pt_menu .itemMenu .itemMenuName{font-size: 13px; font-family: 'Open Sans'; font-weight: normal; color: #444; background: none; padding: 0; border-bottom: 1px solid #d2d2d2;}.pt_custommenu div.pt_menu .itemMenu .itemMenuName{font-size: 16px; font-family: Open Sans Semibold; text-transform: uppercase; font-weight: normal; color: #444; background: none; padding: 0; border-bottom: 1px solid #d2d2d2;}.pt_custommenu div.pt_menu .itemMenu a:hover{color: #00945E;}/*  inicio modif para ocultar subcategorias */.pt_custommenu div.pt_menu .itemSubMenu { display: none !important; }/* fin modif para ocultar subcategorias */.pt_custommenu div.pt_menu .itemSubMenu a.itemMenuName{line-height: 28px; color: #000; padding-left: 13px; font-weight: normal; font-size: 15px; padding: 0; font-family: 'Open Sans'; border: none; }.pt_custommenu div.pt_menu .itemSubMenu a:hover{color: #00945E; }