Vous êtes sur la page 1sur 59

Índice de contenidos

Extensión imprescindible......................................................................................................................12
Cómo quitar la doble selección de atributo en productos configurables...............................................12
Traducir la etiqueta “Price from”...........................................................................................................14
Solucionando el problema con el código HTML en el precio en información adicional.........................14
Solucionando problema. El precio en la caja de añadir al carrito cuando se selecciona el atributo no
cambia..................................................................................................................................................15
Cambiar posición del símbolo de la moneda........................................................................................16
Hacer que las imágenes cambien más rápido en SCP.........................................................................16
Modificación en el listado de subcategorías. Mostrando a dos columnas............................................41
Incrementando la seguridad de la carpeta que contiene los PDF.........................................................47
Modificando Magento
Todos estos cambios se realizan sobre la plantilla Default de Magento 1.4.1
Versión 1.0 del Documento (octubre de 2010)

Cambiar Enlaces rápidos de horizontal a vertical


En la hoja de estilos de la plantilla que utilicemos (en nuestro caso Default), comentamos las siguientes
líneas:
En la sección de estilos de cabecera (HEADER)
/*.header .links li { float:left; font-size:11px; background:url(../images/bkg_pipe1.gif)
100% 60% no-repeat; padding:0 8px 0 7px; }*/

En la sección de Estilos MISC


/*.links li { display:inline; }*/

Y el menú de enlaces rápidos se despliega en vertical.

Quitar el mensaje de bienvenida de la cabecera


Buscamos en el archivo /app/design/frontend/default/mi_tema/template/page/html/header.phtml, y
localizamos el siguiente bloque:
<div class="quick-access">
<?php echo $this->getChildHtml('topSearch') ?>
<p class="welcome-msg"><?php echo $this->getWelcome()?></p>
<?php echo $this->getChildHtml('topLinks') ?>
<?php echo $this->getChildHtml('store_language') ?>
</div>

Eliminamos la línea:
<p class="welcome-msg"><?php echo $this->getWelcome()?></p>

Cambiar el texto del campo de Búsqueda


Abrimos el fichero //app/locale/es_ES/Mage_Core.csv
Búscamos el texto: Buscar en toda la tienda y lo cambiamos por el que deseemos.

Existe otro fichero en esta misma ruta Mage_CatalogSearch.csv que también contiene este texto, como de momento no
sabemos a que corresponde lo cambiaremos también por el mismo texto que hayamos cambiado en el archivo anterior.

Cambiar Top Links a columna derecha


Del enlace: http://www.magentocommerce.com/boards/viewthread/20267/
Abrimos el archivo /app/design/frontend/default/mi_tema/layout/page.xml Buscamos la referencia a los Top
Links que se encuentran en la siguiente línea de código:
<block type="page/template_links" name="top.links" as="topLinks"/>

Y lo ubicamos en el lugar donde se referencia la columna derecha quedando el código como sigue:
<block type="core/text_list" name="right" as="right" translate="label">
<label>Right Column</label>
<block type="page/template_links" name="top.links" as="topLinks"/>
</block>

Por si acaso:

Fómula para cambiar posición encontrada en el enlace:


http://www.magentocommerce.com/boards/viewthread/19748/

<?=$this->getLayout()->getBlock('top.links')->toHtml()?>

Ahora hay que darle el estilo para la columna derecha.

Quitar Quick Access de la Cabecera (header)


Editamos el archivo app/design/frontend/default/mi_tema/template/page/html/header.phtml y búscamos el
siguiente código:
<div class="header-container">
<div class="header">
<?php if ($this->getIsHomePage()):?>
<h1 class="logo"><strong><?php echo $this->getLogoAlt() ?></strong><a
href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><img src="<?php echo $this->getLogoSrc() ?>"
alt="<?php echo $this->getLogoAlt() ?>" /></a></h1>
<?php else:?>
<a href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><strong><?php echo $this->getLogoAlt() ?
></strong><img src="<?php echo $this->getLogoSrc() ?>" alt="<?php echo $this-
>getLogoAlt() ?>" /></a>
<?php endif?>
<div class="quick-access">
<?php echo $this->getChildHtml('topSearch') ?>
<?php echo $this->getChildHtml('topLinks') ?
<?php echo $this->getChildHtml('store_language') ?>
</div>
<?php echo $this->getChildHtml('topContainer'); ?>
</div>
</div>

Eliminamos las líneas que hacen referencia a la división quick access, que son esta:
<div class="quick-access">
<?php echo $this->getChildHtml('topSearch') ?>
<?php echo $this->getChildHtml('topLinks') ?
<?php echo $this->getChildHtml('store_language') ?>
</div>
con lo que el código nos quedaría del siguiente modo:
<div class="header">
<?php if ($this->getIsHomePage()):?>
<h1 class="logo"><strong><?php echo $this->getLogoAlt() ?></strong><a
href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><img src="<?php echo $this->getLogoSrc() ?>"
alt="<?php echo $this->getLogoAlt() ?>" /></a></h1>
<?php else:?>
<a href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><strong><?php echo $this->getLogoAlt() ?
></strong><img src="<?php echo $this->getLogoSrc() ?>" alt="<?php echo $this-
>getLogoAlt() ?>" /></a>
<?php endif?>
<?php echo $this->getChildHtml('topContainer'); ?>
</div>

Añadir una imagen en el lugar que ocupaban los Quick Access


Me ayudó el enlace: http://www.magentocommerce.com/boards/viewthread/51564/
Podemos hacerlo incluyendo una imagen que abarque el tamaño necesario que va desde donde acaba el
logo hasta el final derecho de la cabecera, pero esto nos presentará el problema de los ajustes cuando varían
los tamaños de pantalla.
La mejor forma de hacerlo es incluyendo una imagen más que se posicione en el lado derecho de la
cabecera (lugar que ocupaban los quick access). Para ello editamos el archivo:
app/design/frontend/default/mi_tema/template/page/html/header.phtml, y añadimos una etiqueta div del
siguiente modo (justo en el lugar que ocupanban los quick access:
<div class="logoright">
<img src="<?php echo $this->getSkinUrl('images/cabecera.gif') ?>"
alt="Alimentos de calidad" />
</div>

Bien la imagen incluida se llama en el ejemplo cabecera.gif, y además le hemos asignado un estilo de la hoja
de estilo que se llama logoright. De este modo también podremos controlar determinados aspectos sobre
como se muestra la imagen en la misma hoja de estilos. En el ejemplo el código lo hemos incluido en la
plantilla Default en la sección HEADER, justo entre el estilo .header h1.logo y el estilo .header .quick-access.
La línea que hemos incluido es tal y como sigue:
.header .logoright { float:right; margin:40px 0 3px 3px; }

Con lo que en el contexto el código de este archivo queda como sigue


<div class="header-container">
<div class="header">
<?php if ($this->getIsHomePage()):?>
<h1 class="logo"><strong><?php echo $this->getLogoAlt() ?></strong><a
href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><img src="<?php echo $this->getLogoSrc() ?>"
alt="<?php echo $this->getLogoAlt() ?>" /></a></h1>
<?php else:?>
<a href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><strong><?php echo $this->getLogoAlt() ?
></strong><img src="<?php echo $this->getLogoSrc() ?>" alt="<?php echo $this-
>getLogoAlt() ?>" /></a>
<?php endif?>
<div class="logoright">
<img src="<?php echo $this->getSkinUrl('images/cabecera.gif') ?>"
alt="Alimentos de calidad" />
</div>
<?php echo $this->getChildHtml('topContainer'); ?>
</div>
</div>
<?php echo $this->getChildHtml('topMenu') ?>

Poner el formulario de búsqueda en la Barra de navegación de


categorías
Tenemos que incluir la línea de código siguiente:
<?=$this->getLayout()->getBlock('top.search')->toHtml()?>

En el archivo: /app/design/frontend/default/mi_tema/template/catalog/navigation/top.phtml
Lo haremos de tal modo que el archivo mencionado quede así:
<div class="nav-container">
<ul id="nav">
<?php echo $_menu; ?>
<li class="mini-search"><?=$this->getLayout()->getBlock('top.search')->toHtml()?
></li>
</ul>
</div>

Si nos fijamos en la línea de código introducida le hemos asignado a la etiqueta <li> una nueva clase que
tendremos que crear dentro de la sección de Navigation de la hoja de estilos. Este nuevo estilo que
agregamos nos centrará verticalmente el formulario de búsqueda y lo alineará a la derecha.
#nav .mini-search {float:right; margin:0 auto; padding:3px 0 0 0; }

Fijémonos también dónde hemos ubicado esta línea:


.nav-container { border-bottom:3px solid #866b07; background:#d7a900
url(../images/bkg_nav0.jpg) 50% 0 repeat-y; }
#nav { width:918px; margin:0 auto; padding:0 16px; font-size:13px; }
#nav .mini-search {float:right; margin:0 auto; padding:3px 0 0 0; }

/* ALL Levels */ /* Style consistent throughout all nav levels */

Ahora vamos a perfeccionar nuestro formulario de búsqueda y elimnaremos la etiqueta (label) que además
aparece en inglés. Iremos al archivo:
/app/design/frontend/default/mi_tema/template/catalogsearch/form.mini.pahtml
y buscamos la siguiente línea:
<label for="search"><?php echo $this->__('Search:') ?></label>

La comentamos y listo:
<!-- <label for="search"><?php echo $this->__('Search:') ?></label> -->

Cambiar la posición de los bloques en la columna derecha (Enlaces,


Carrito de compra, Comparar Productos)
Lo haremos todo desde los archivos de layuot (xml).
Primero, en el archivo page.xml debemos añadir lo siguiente a la línea que incluimos previamente para
colocar los enlces en esta columna:
<block type="page/template_links" before="-" name="top.links" as="topLinks"/>
La instrucción before=”-” fuerza a que este bloque se coloque en primera posición en la columna. No obstante
si guardamos y actualizamos nuestra página nos damos cuenta de que no varía el orden. Hay que tocar un
par de archivos más.
Abrimos el archivo checkout.xml y buscamos el siguiente código:
<reference name="right">
<block type="checkout/cart_sidebar" name="cart_sidebar"
template="checkout/cart/sidebar.phtml" before="-">

Nos fijamos en la instrucción before=”-”, que también fuerza a que el carrito de compra se posicione el
primero, y además tendrá prioridad por tratarse de un módulo que dispone de su propio layout (o eso creo),
bien lo cambiamos para que el carrito quede por encima del modulo de comparación de productos, por lo que
el código nos queda:
<reference name="right">
<block type="checkout/cart_sidebar" name="cart_sidebar"
template="checkout/cart/sidebar.phtml" before="catalog.compare.sidebar">

El siguiente archivo es catalog.xml, buscamos el siguiente código:


<reference name="right">
<block type="catalog/product_compare_sidebar" before="cart_sidebar"
name="catalog.compare.sidebar" template="catalog/product/compare/sidebar.phtml"/>
<block type="core/template" name="right.permanent.callout"
template="callouts/right_col.phtml">

Bien pues aquí vemos que el comparar productos tiene la instrucción before, con lo que entra en
contradicción con la modificación que hicimos en el archivo checkout.xml, simplemente cambiamos la
instrucción por after... y listo.

Eliminar del pie el texto Ayúdenos a mantener sano a Magento


Editamos el archivo: /app/design/frontend/default/mi_tema/template/page/html/footer.phtml
y comentamos la siguiente línea:
<?php echo $this->getChildHtml() ?>
<!-- <p class="bugs"><?php echo $this->__('Help Us to Keep Magento
Healthy') ?> - <a href="http://www.magentocommerce.com/bug-tracking"
onclick="this.target='_blank'"><strong><?php echo $this->__('Report All
Bugs') ?></strong></a> <?php echo $this->__('(ver. %s)',
Mage::getVersion()) ?></p>-->
<address><?php echo $this->getCopyright() ?></address>

Pasar la suscripción del Boletín al lado derecho y Quitarlo del lado


izquierdo en el Dashboard de la Cuenta de usuario
Con lo que haremos a continuación pasaremos el bloque de suscripción a boletines (Newletters) a la columna
derecha, evidentemente aparecerá cuando la columna derecha aparezca. De este modo, por ejemplo, al
pasarlo a la columna derecha, las newletters nos desaparecerán de la página de inicio de la cuenta de
usuario puesto que este diseño está preparado para dos lumnas y una a la izquierda.
Para hacer esto procederemos del siguiente modo:
Editamos el archivo /app/design/frontend/default/mitema/layout/newsletter.xml y buscamos las siguientes
líneas:
<default>
<!-- Mage_Newsletter -->
<reference name="left">
<block type="newsletter/subscribe" after="_" name="right.newsletter"
template="newsletter/subscribe.phtml"/>
</reference>
</default>

Donde dice “left” ponemos “right”. Con este simple cambio hemos hecho todo lo dicho.

Quitar el enlace en el menú Mi cuenta (Dashboard) “Mis productos


Descargables”
Editamos el archivo app/design/frontend/default/mitema/layout/downloadable.xml
Y comentamos las siguientes líneas:
<layout version="0.1.0">
<!-- <customer_account>
<reference name="customer_account_navigation">
<action method="addLink" translate="label"
module="downloadable"><name>downloadable_products</name><path>downloadable/cu
stomer/products</path><label>My Downloadable Products</label></action>
</reference>
</customer_account>
-->
<downloadable_customer_products translate="label">

Quitar el enlace Mi Lista de Deseos de los Top Links


Editamos el archivo /app/design/frontend/default/mi_tema/layout/wishlist.xml.
Y comentamos el siguiente bloque de código que quedaría así:
<!--
<reference name="top.links">
<block type="wishlist/links" name="wishlist_link">
<action method="addWishlistLink"></action>
</block>
</reference>
-->

Quitar el enlace Mi Cuenta de los Top Links


Editamos el archivo /app/design/frontend/default/mi_tema/layout/customer.xml.
Y comentamos la siguiente línea de código que quedaría así (en negrita):
<default>
<!-- Mage_Customer -->
<reference name="top.links">
<!--<action method="addLink" translate="label title"
module="customer"><label>My Account</label><url
helper="customer/getAccountUrl"/><title>My
Account</title><prepare/><urlParams/><position>10</position></action>-->
</reference>
</default>

Cómo incluir enlace a formulario de Registro en el bloque Top Links


Editamos el fichero /app/design/frontend/default/mi_tema/layout/customer.xml
Buscamos el siguiente bloque de código:
<!--
Load this update on every page when customer is logged out
-->
<customer_logged_out>
<reference name="right">
<block type="customer/form_login" name="customer_form_mini_login"
before="-" template="customer/form/mini.login.phtml"/>
</reference>
<reference name="top.links">
<action method="addLink" translate="label title"
module="customer"><label>Log In</label><url
helper="customer/getLoginUrl"/><title>Log
In</title><prepare/><urlParams/><position>100</position></action>
</reference>
<remove name="wishlist_sidebar"></remove>
<remove name="reorder"></remove>
</customer_logged_out>

Y añadimos la siguiente línea justo en la ubicación que se indica, la línea está en negrita:
<reference name="top.links">
<action method="addLink" translate="label title"
module="customer"><label>Log In</label><url
helper="customer/getLoginUrl"/><title>Log
In</title><prepare/><urlParams/><position>100</position></action>
<action method="addLink" translate="label title"
module="customer"><label>Register</label><url
helper="customer/getRegisterUrl"/><title>Register</title><prepare/><urlParams
/><position>20</position></action>
</reference>

Como incluir un botón de registro en el formulario mini.login.phtml


El formulario mini-login por defecto no se publica, lo podemos encontrar en el fichero
/app/design/frontend/default/mi_tema/layout/customer.xml, y observaremos que viene comentado:
<!--

Load this update on every page when customer is logged out

-->

<customer_logged_out>

<reference name="right">

<block type="customer/form_login" name="customer_form_mini_login" before="-"


template="customer/form/mini.login.phtml"/>

</reference>

Bien, si queremos publicarlo (sobre todo para ver como queda la inclusión de un nuevo botón en este
bloque), simplmente descomentamos el código.
Para incluir el botón tenemos que editar el fichero de plantilla correspondiente a este mini formulario:
/app/design/frontend/default/mi_tema/template/customer/form
Y justo despues de la etiqueta que cierra el formulario (</form) y antes de la que etiqueta con la que finaliza el
fichero (</div>), incluimos el siguiente código:
<div class="actions">
<button class="button"
onclick="location.href='/customer/account/create'"><span><span><?php echo
$this->__('Register') ?></span></span></button>
</div>

Ahora solo tenemos que ajustar los estilos que le estamos aplicando al botón.

Cambiar de Derecha a Izquierda el carrito de compra


/app/design/frontend/default/mi_tema/layout/checkout.xml
Buscamos este código:
<reference name="right">
<block type="checkout/cart_sidebar" name="cart_sidebar"
template="checkout/cart/sidebar.phtml" before="catalog.compare.sidebar">
<action
method="addItemRender"><type>simple</type><block>checkout/cart_item_renderer<
/block><template>checkout/cart/sidebar/default.phtml</template></action>
<action
method="addItemRender"><type>grouped</type><block>checkout/cart_item_renderer
_grouped</block><template>checkout/cart/sidebar/default.phtml</template></act
ion>
<action
method="addItemRender"><type>configurable</type><block>checkout/cart_item_ren
derer_configurable</block><template>checkout/cart/sidebar/default.phtml</temp
late></action>
</block>
</reference>

Cambiamos “right” por “left”.

Cambiar de Derecha a Izquierda el bloque de comparación de productos


Editamos el fichero l/app/design/frontend/default/mi_tema/layout/catalog.xml
La línea que ubica el bloque está en el siguiente trozo de código (resalto la línea en negrita).
<reference name="right">

<block type="catalog/product_compare_sidebar" after="cart_sidebar"


name="catalog.compare.sidebar" template="catalog/product/compare/sidebar.phtml"/>

<block type="core/template" name="right.permanent.callout"


template="callouts/right_col.phtml">

<action
method="setImgSrc"><src>images/media/col_right_callout.jpg</src></action>

<action method="setImgAlt" translate="alt" module="catalog"><alt>Keep your


eyes open for our special Back to School items and save A LOT!</alt></action>

</block>

</reference>

Bien, cortamos esta línea (en negrita) y la ubicamos en el bloque izquierda, justo encima de este bloque,
quedaría así:
<reference name="left">
<block type="catalog/product_compare_sidebar" after="cart_sidebar"
name="catalog.compare.sidebar"
template="catalog/product/compare/sidebar.phtml"/>
<block type="core/template" name="left.permanent.callout"
template="callouts/left_col.phtml">
<action
method="setImgSrc"><src>images/media/col_left_callout.jpg</src></action>
<action method="setImgAlt" translate="alt"
module="catalog"><alt>Our customer service is available 24/7. Call us at
(555) 555-0123.</alt></action>
<action method="setLinkUrl"><url>checkout/cart</url></action>
</block>

Crear un bloque de contenido con los Top Links


Esto me llevó una semana entera dándome cabezazos. Para colmo en el foro pasaban de mis continuas
preguntas.
El problema es que los Top Links son referenciados llamando al archivo links.phtml y no top.links.phtml, como
se puede observar en el archivo page.xml del layout:
<block type="page/template_links" before="-" name="top.links" as="topLinks"/>

Pues bien, si modificaba el archivo links para incluirle aspecto de bloque resultaba que, como es normal, este
aspecto o estilo también se aplicaba a los enlaces del footer puesto que tanto estos como los top links tienen
el mismo archivo de origen en la plantilla, es decir, links.phtml.
Para solventar esto hay que replicar el archivo links.phtml de tal modo que cuando sea llamado por los Top
Links, el archivo referenciado sea diferente del archivo referenciado por el footer.
A esta réplica le aplicamos los estilos de un bloque de contenido mediante div´s y luego solo tenemos que
referenciar la réplica modificada y crear los estilos personalizados.
Así pues, vamos allá:
Primer paso: Creamos la réplica del archivo links.phtml y le aplicamos los estilos que posteriormente
crearemos. En la ruta de links.phtml creamos el archivo links2.phtml con el mismo contenido que el original y
con las siguientes modificaciones. Se muestra el archivo final:
<?php $_links = $this->getLinks(); ?>
<?php if(count($_links)>0): ?>
<div class="block block-account-per">
<div class="block-title-per">
<strong><span>OPCIONES DEL USUARIO</span></strong>
</div>
<div class="block-content-per">
<ul class=""block-content-per li""<?php if($this->getName()): ?> id="<?php
echo $this->getName() ?>"<?php endif;?>>
<?php foreach($_links as $_link): ?>
<li<?php if($_link->getIsFirst()||$_link->getIsLast()): ?> class="<?
php if($_link->getIsFirst()): ?>first<?php endif; ?><?php if($_link-
>getIsLast()): ?> last<?php endif; ?>"<?php endif; ?> <?php echo $_link-
>getLiParams() ?>><?php echo $_link->getBeforeText() ?><a href="<?php echo
$_link->getUrl() ?>" title="<?php echo $_link->getTitle() ?>" <?php echo
$_link->getAParams() ?>><?php echo $_link->getLabel() ?></a><?php echo
$_link->getAfterText() ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php endif; ?>

Nos fijamos en el archivo y observamos los siguiente:


1. Hemos incluido un div en el que indicamos que la clase de estilo a aplicar es “block block-account-
per”. Es un estilo que deberemos añadir a la hoja de estilos, y que contendrás el resto de estilos
declarados: block-title-per, block-content-per y block-content-per li
2. Hemos incluido un título de forma manual. Ojo con esto puesto que si tenemos la web en varios
idiomas hacerlo así no nos sirve, puesto que tendríamos que en lugar de incluir el título como quien
dice “a pelo”, tendríamos que declarar la variable correspondiente y hacerla traducible. No me
preguntes cómo, aún no lo se.
3. Por último cerramos los nuevos div´s que hemos creado.
Segundo paso: vamos a referenciar nuestro bloque desde el archivo page.xml del layout. Pero fijaos como
los hacemos porque me volví loco hasta dar con la clave:
<block type="page/template_links" before="-" name="top.links" as="topLinks"
template="page/template/links2.phtml"/>

Lo único que cambiamos respecto a la línea inicial es la ruta del archivo de la plantilla, el resto es igual. Es
decir en block type, pese a que referencia la ruta, no la cambiamos la dejamos como incialmente, tampoco
cambiamos el nombre (name) ni la forma de referenciarlo (as), sólo la ruta y el archivo al que apunta la
referencia.
Esta línea, en mi caso, la he incluido en el bloque derecho por lo que su ubicación es como sigue:
<block type="core/text_list" name="right" as="right" translate="label">
<label>Right Column</label>
<!-- <block type="page/template_links" before="-"
name="top.links" as="topLinks"/>-->
<block type="page/template_links" before="-"
name="top.links" as="topLinks" template="page/template/links2.phtml"/>
</block>

Hay que observar que la línea comentada es precisamente la original, que previamente se encontraba dentro
de la cabecera pero que yo la cambié al lboque derecho anteriormente.
Tercer paso: por último, debemos crear los estilos que hemos asignado a links2.phtml. Yo me he limitado a
copiar el estilo de la sección Block: Account, pegándolo como una nueva sección justo debajo de la orginal, y
posteriormente renombrándolo:
/* Block: Account Personalizado */
.block-account-per { border-color:#bbb; }
.block-account-per .block-title-per { background:#fc9d36 url(../images/bkg_block-
title-account.gif) 0 100% repeat-x; border:0; padding:3px 10px; }
.block-account-per .block-title-per strong { font-size:12px; color:#fff; }
.block-account-per .block-content-per { background:#fbfaf6; padding:7px 10px 7px; }
.block-account-per .block-content-per li a { display:block; border-bottom:1px solid
#ddd; padding:3px 0; color:#5f5d5c; text-decoration:none !important; }
.block-account-per .block-content-per li a:hover { color:#ea7900; }
.block-account-per .block-content-per li.last a { border-bottom:0; }
.block-account-per .block-content-per li.current { border-bottom:1px solid #ddd;
padding:3px 0; color:#ea7900; }
.block-account-per .block-content-per li.current.last { border-bottom:0; }

Y eso es todo. Cuánto trabajo me costó, cuánto tiempo, para algo que así visto parece muy simple.

Productos Configurables

Extensión imprescindible

Simple Configurable Products. Esta extensión permite que los productos configurables cojan el precio del
producto simple asociado y no el follón que monta Magento al respecto. Pero también permite que los datos
del producto simple asociado sean mostrados cuando se selecciona el atributo que le corresponde, inclusive
la imagen. Lo que la hace una extensión imprescindible.

Cómo quitar la doble selección de atributo en productos configurables

Si tenemos instalado el Simple Configurable Products puede ocurrir que al crear un producto configurable con
al menos un atributo para seleccionar por el cliente, nos aparezca dos veces el desplegable de la selección,
que además están relacionados porque mientras no seleccionemos la opción en el primero que nos parece,
no podremos hacer selección en el segundo, lo que lleva a confusión, además de suponer un aso inútil para
el cliente. Bien para quitar el que nos parece primero, lo que haremos es editar el archivo
//app/design/frontend/default/mitema/template/catalog/product/view/type/configurable.phtml
El contenido completo de este archivo es:
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE_AFL.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category design
* @package base_default
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien
(http://www.varien.com)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free
License (AFL 3.0)
*/
?>

<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this-
>getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<dt><label><?php echo $_attribute->getLabel() ?><span
class="required">&nbsp;*</span></label></dt>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<select name="super_attribute[<?php echo $_attribute-
>getAttributeId() ?>]" id="attribute<?php echo $_attribute-
>getAttributeId() ?>" class="required-entry super-attribute-select">
<option><?php echo $this->__('Choose an Option...') ?></option>
</select>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>

Pues borramos o comentamos las siguientes líneas con lo que el archivo no queda así (en el caso de
borrado):
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE_AFL.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category design
* @package base_default
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien
(http://www.varien.com)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free
License (AFL 3.0)
*/
?>

<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this-
>getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>

<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>

Traducir la etiqueta “Price from”

Editamos el archivo //app/design/frontend/default/mitema/locale/es_ES/translate.csv


Añadimos al final la siguiente línea:
"Price From:","Desde:"

Por ejemplo.

Solucionando el problema con el código HTML en el precio en información adicional

Primera opción: obtenida del foro http://www.magentocommerce.com/boards/viewthread/199860/#t253096


Empleo esta porque la segunda opción como veremos más adelante, aportada por Matt Dean, implica tocar
el core. Así que es más arriesgada.
Just created a simple solution to this problem
in /app/design/frontend/default/yourtemplate/template/catalog/product/view/attributes.phtml
replace line 47:
<td class="data"><?php echo $_helper->productAttribute($_product,
$_data['value'], $_data['code']) ?></td>

with:
<td class="data"><?php echo html_entity_decode($_helper-
>productAttribute($_product, $_data['value'], $_data['code'])); ?> </td>

the html_entity_decode will replace the > and other html special chars with < “ and >
Anyway it works for me now
Esta opción ha funcionado correctamente. La segunda ni siquiera la he probado, pero aquí está:
Segunda opción: De un correo recibido de Matt Dean.
For the display of Price in the additional attributes table it just looks like a Magento bug to me.
My quick fix would be to do the following:
in: app/code/core/Mage/Catalog/Helper/Output.php change line 106 from:
if ($attribute && ($attribute->getFrontendInput() != 'media_image')

to
if ($attribute && ($attribute->getFrontendInput() != 'media_image' &&
$attribute->getFrontendInput() != 'price')

Works for me so far.


Matt
Tercera opción: esta opción es una contestación a la pregunta que planteé en el foro.
http://www.magentocommerce.com/boards/viewthread/199860/#t255291
The actual cause of this issue is sort of a Rendering bug.
In the method ”productAttribute” located on line 101 for 1.4.0 and line 120 for 1.4.1.x in this fle
magento_install/app/code/core/Mage/Catalog/Helper/Output.php the value of the attribute is html escaped.
The real fix comes in adding “ && ($attribute->getFrontendInput() != ‘price’) “ to the if statement on line 106
in 1.4.0 and line 123 in 1.4.1.x in the Output.php file.
It has been filed as a bug here:
http://www.magentocommerce.com/bug-tracking/issue?issue=9577
Signature
- Magento ver. 1.3.2.4, 1.4.0.1

Solucionando problema. El precio en la caja de añadir al carrito cuando se selecciona el


atributo no cambia.

La respuesta me la da San Matt Dean, en un correo electrónico cuya primera parte dice:
So did you try changing price_clone.phtml so that it uses
$this->getPrice($_product, false)
instead of
$this->getPrice($_product, false, '_clone')
Cambiar posición del símbolo de la moneda

http://www.magentocommerce.com/boards/viewthread/57000/
En español
http://foros.mgnt.es/showthread.php?1492-Cambiar-posicion-simbolo-del-_
Ir a la carpeta lib/Zend/Locale/data y edtar el fichero es.xml
Buscar la cadena de texto:
<pattern>¤ #,##0.00</pattern>
y cambiar la posición de #,##0.00 delante de los símbolos.
Pero a mi me aparece: <pattern>#,##0.00 ¤Â</pattern>
y las À no se para que son. Avisar que en este caso el editor VI puede jugarte una mala pasada, y eso es lo
que me pasaba a mi. Yo al final tuve que editar el fichero en otro ordenador con Linux y subirlo al servidor (ojo
con los permisos al subirlo).
Pero antes de hacer nada, debéis vaciar una serie de directorios, puesto que aunque tengáis la caché de
Magento deshabilitada parece que en este caso como que no le afecta. Si no vaciáis esas carpeta os podréis
encontrar con la desagradable sorpresa de no poder entrar en el panel de administración porque os arroja un
error, justo el que se indica en el epígrafe siguiente. También debemos limpiar la caché del navegador.
Parece que el símbolo de moneda es muy delicado.
Los directorios a vaciar son:
• /var/cache
• /var/locks
• /var/report
• Yo por si acaso también borreo el directorio de sesiones /var/session
Ahora limpiamos la caché, temporales, etc... del navegador y ya debe funcionar.

Problema Panel de Administración “Currency USD not found”


Este problema me surge cuando intento cambiar la posición del símbolo Euro. Para hacer esto hay que tocar
el archivo /lib/Zend/locale/data/es.xml, y el símbolo € está representado por unos caracteres extraños. Pero
esta forma no funciona, así que vuelvo al archivo original, pero aún así me da el mismo error.
La forma de repararlo consiste en borrar el contenido de las siguientes carpetas:
/var/cache
/var/locks
/var/report
Luego limpiamos la caché del navegador y accedemos al panel de control.

Hacer que las imágenes cambien más rápido en SCP

Me lo dijo Matt Dean basta con poner a no la opción de configuración de la extensión SCP “Update gallery
images as well as main image?”.
De este modo las imágenes tardan mucho menos en cargar y es casi inmediato.
Implementando los Impuesto
Del enlace: http://lab.redmallorca.com/como-configurar-el-iva-en-magento/
Primero nos vamos a Ventas->Impuestos->Impuestos al producto. Aquí daremos de alta un nuevo tipo de
impuesto al producto. En nuestro caso debemos dar de alta ds tipos de impuestos:
1. Reducido (IVA al 8%) para los productos comercializados.
2. Normal (IVA al 18%) para el transporte.
Estos tipos de impuestos los tendremos disponibles en la ficha de los productos.
Ahora vamos a dar de alta los impuestos al cliente, que será el tipo de impuesto que le asignaremos a cada
uno de nuestros grupos de clientes. Accedemos a Ventas->Impuestos->Impuestos al cliente y damos de alta
un nuevo tipo, en este caso sólo tendremos Cliente final. En el apartado de clientes->Grupos de Clientes del
panel de administración podemos asignar a cada grupo de nuestros clientes una tasa de impuestos diferente.
De hecho es necesario hacer esto para que los impuestos sean aplicados.
Ahora vamos a especificar las zonas y tasas correspondientes para la gestión de los impuestos de nuestra
tienda. Para ello accedemos a Ventas->Impuestos->Gestionar zonas de impuesto y tasas. Aquí podemos
especificar las tasas de impuesto de cada país, provincia o código postal de los clientes de nuestra
tienda. A las provincias que estén exentas de impuestos, les asignaremos una tasa de 0.
Disponemos de la opción de exportar e importar la información de impuestos para poder automatizar estos
pasos a través de un editor de archivos csv. Puede ser muy útil para agilizar la operación y no tener que
repetir pasos si queremos, por ejemplo, poner una nueva tasa al 4% o al 7%.
Por último, vamos a enlazar toda la información que hemos creado, dando de alta una nueva regla de
impuesto. Para ello, accedemos a Ventas->Impuestos->Gestionar reglas de impuestos. Simplemente le
damos un nombre a la regla y vamos seleccionando las opciones que nos aparecen, entre ellas veremos los
impuestos al cliente e impuestos al producto que hemos creado, así como las tasas.
Ya hemos creado las reglas de impuestos necesarias, que recordemos combinan impuestos al cliente,
impuestos al producto, y tasas de impuestos que están creadas en virtud de las zonas (país, provincia e
incluso códigos postales). De esta forma es casi imposible que no podamos establecer los impuestos por
raros y tergiversados que estos sean.
Pero nos queda un aspecto importante para poner en marcha nuestros impuestos. Lo primero es que
debemos tener correctamente ajustados o configurados los siguientes parámetros en Configuración (Sistema
->Configuración).
1. Cofiguración General -> General. Aquí debemos establecer el país por defecto de la tienda y los
demás parámetros que nos solicitan sobre opciones locales y paises en los que se habilita la venta.
2. Configuración General ->Ventas -> Impuestos. Aquí estableceremos todas las opciones generales
sobre la aplicación de impuestos, incluyendo si incluiremos los precios con IVA, si se mostrarán con
IVA o sin IVA, etc. Esto último es interesante saberlo puesto que nos permitirá meter los precios de
los artículos incluso antes de establecer las relgas de impuestos, ya que los podremos meter con IVA
o si él y en la opción de configuración le diremos a Magento si lo hemos incluido con o sin IVA.

Cómo ordenar el orden de aparición de las Categorías


Las categorías aparecen en Magento según el orden en que se encuentren en el panel de administración. Así
si queremos que una categoría parezca antes que otra, solo debemos, desde el panel de administración,
picar y arrastrar la categoría y situarla por encima de la categoría que queramos aparezca después.
Cómo ordenar el orden de aparación de los productos
Del enlace: http://www.elblogdemagento.com/ordenar-por-mejor-valor/
Magento ofrece de forma predeterminada 3 formas de ordenación: Mejor valor, Precio y Orden alfabético.
Entonces, ¿de qué forma Magento determina el orden para “Mejor valor”? Pues de forma manual. Desde el
backend, el administrador puede darle un valor a la posición de aparición de cada producto y así “ordenar
manualmente” los productos que más le interese mostrar primero, segundo… hasta el último. ¿Y desde
dónde damos los valores a cada producto? Está un poco escondido, pero sigue estos pasos:
Paso 1. Accede a tu panel de administración de Magento.
Paso 2. Accede al menú Catálogo / Administrar Categorías
Paso 3. Selecciona una categoría que te interese ordenar. Puedes dar un orden distinto según en la categoría
que te encuentres.
Paso 4. En las pestañas de la categoría, selecciona “Productos de la categoría”.
Paso 5. En la tabla que lista los productos, observa la columna de la derecha, “Posición”. Aquí es donde
puedes determinar los valores por los cuales ordenar los productos.

Cómo ordenar el orden de aparición de los atributos en los productos


configurables
Sencillo, el mismo orden que pongamos para Gestión de Etiquetas / opciones será la que aparezca en el
front-end.

Establecer el número de niveles de categorías que se muestran en el


menú de navegación
Del enlace: http://foros.mgnt.es/showthread.php?2032-Mostrar-solo-el-primer-nivel-de-las-categorias-en-el-
top-menu
Sistema - Catálogo - Catálogo - Categoria Padre y en Máxima profundidad le pones hasta el nivel que querés
que aparezca ( el cero es el infinito).

Mostrar las categorías listadas en una página


Exiten dos posibles soluciones.
Solución 1: Magento 1.4 . Creación de Bloques Estáticos donde se incorporan Widget de Enlaces a
categorías. Posteriormente en las categorías Madre hay que habilitar dichos bloques en Display Settings y
seleccionar Solo Bloque estático. En el bloque estático seleccionamos el que hallamos creado.
El inconveniente de este método es que hay que crear las páginas (Bloques Estáticos) de forma manual por
cada categoría madre. No obstante, si las categorías no son muchas esta solución nos da mucha flexibilidad
en el diseño.
Solución 2: Modificar el core
La ventaja de esta solución es que se hace de forma automatizada el listado para todas las categorías.
Del enlace: http://foros.mgnt.es/showthread.php?1840-Soluci%F3n-ver-categor
%EDas&highlight=solucion+categorias
Bueno esto está hecho para monos amaestrados como yo…no pregunten si se puede hacer esto o lo otro.
No entiendo absolutamente nada de los códigos. Pero funciona de maravillas.
Bajar los dos archivos adjuntos y hacer lo siguiente. Ir a magento
app/code/Mage/Catalog/Model/Resource/Eav/Mysql4/Category.php y reemplazarlo por el adjunto
Category.php (antes hacer backup del que ya se encuentra en tu web).
Tambien copiar el archivo adjunto sub_category_listing.phtml en app/design/frontend/
default/tutemplate/template/catalog/navigaton/sub_navigation.html

Despues ir a CMS > Static Blocks. Click en Add New Block y llenar así
Block Title: Sub Category Listing
Identifier: sub_category_listing
Status: Enabled
Content: {{block type="catalog/navigation" template="catalog/navigation/sub_category_listing.phtml"}}
Click Save
Ahora hay que habilitar el static blok en las categorías madres
Ir a: Catalog > Manage Categories.
Ir a “General Information” y elegir una imagen para la categoría en examinar
Entonces clikear en la categoría madre que tiene subcategorias, ir a la solapa “Display Settings”.
Llenar los campos de la siguiente manera:
Display Mode: Static Block Only
CMS Block: Sub Category Listing
Is Anchor: Yes
Contenido de los ficheros:
Contenido del archivo Category.php (ocupa 20 pàginas)
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
* @package Mage_Catalog
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien
(http://www.varien.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software
License (OSL 3.0)
*/

/**
* Catalog category model
*
* @category Mage
* @package Mage_Catalog
* @author Magento Core Team <core@magentocommerce.com>
*/
class Mage_Catalog_Model_Resource_Eav_Mysql4_Category extends
Mage_Catalog_Model_Resource_Eav_Mysql4_Abstract
{
/**
* Category tree object
*
* @var Varien_Data_Tree_Db
*/
protected $_tree;

/**
* Catalog products table name
*
* @var string
*/
protected $_categoryProductTable;

/**
* Id of 'is_active' category attribute
*
* @var int
*/
protected $_isActiveAttributeId = null;

/**
* Store id
*
* @var int
*/
protected $_storeId = null;
/**
* Class constructor
*/
public function __construct()
{
$resource = Mage::getSingleton('core/resource');
$this->setType('catalog_category')
->setConnection(
$resource->getConnection('catalog_read'),
$resource->getConnection('catalog_write')
);
$this->_categoryProductTable = $this-
>getTable('catalog/category_product');
}

/**
* Set store Id
*
* @param integer $storeId
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
public function setStoreId($storeId)
{
$this->_storeId = $storeId;
return $this;
}

/**
* Return store id
*
* @return integer
*/
public function getStoreId()
{
if (is_null($this->_storeId)) {
return Mage::app()->getStore()->getId();
}
return $this->_storeId;
}

/**
* Retrieve category tree object
*
* @return Varien_Data_Tree_Db
*/
protected function _getTree()
{
if (!$this->_tree) {
$this->_tree = Mage::getResourceModel('catalog/category_tree')
->load();
}
return $this->_tree;
}

/**
* Process category data before delete
* update children count for parent category
* delete child categories
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _beforeDelete(Varien_Object $object)
{
parent::_beforeDelete($object);

/**
* Update children count for all parent categories
*/
$parentIds = $object->getParentIds();
$childDecrease = $object->getChildrenCount() + 1; // +1 is itself
$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('children_count'=>new Zend_Db_Expr('`children_count`-'.
$childDecrease)),
$this->_getWriteAdapter()->quoteInto('entity_id IN(?)',
$parentIds)
);

/**
* Recursion use a lot of memmory, that why we run one request for
delete children
*/
/*if ($child = $this->_getTree()->getNodeById($object->getId())) {
$children = $child->getChildren();
foreach ($children as $child) {
$childObject = Mage::getModel('catalog/category')-
>load($child->getId())->delete();
}
}*/

$select = $this->_getWriteAdapter()->select()
->from($this->getEntityTable(), array('entity_id'))
->where($this->_getWriteAdapter()->quoteInto('`path` LIKE ?',
$object->getPath().'/%'));

$childrenIds = $this->_getWriteAdapter()->fetchCol($select);

if (!empty($childrenIds)) {
$this->_getWriteAdapter()->delete(
$this->getEntityTable(),
$this->_getWriteAdapter()->quoteInto('entity_id IN (?)',
$childrenIds)
);
}

/**
* Add deleted children ids to object
* This data can be used in after delete event
*/
$object->setDeletedChildrenIds($childrenIds);
return $this;
}

/**
* Process category data before saving
* prepare path and increment children count for parent categories
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _beforeSave(Varien_Object $object)
{
parent::_beforeSave($object);

if (!$object->getId()) {
$object->setPosition($this->_getMaxPosition($object->getPath()) +
1);
$path = explode('/', $object->getPath());
$level = count($path);
$object->setLevel($level);
if ($level) {
$object->setParentId($path[$level - 1]);
}
$object->setPath($object->getPath() . '/');

$toUpdateChild = explode('/',$object->getPath());

$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('children_count'=>new
Zend_Db_Expr('`children_count`+1')),
$this->_getWriteAdapter()->quoteInto('entity_id IN(?)',
$toUpdateChild)
);

}
return $this;
}

/**
* Process category data after save category object
* save related products ids and update path value
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _afterSave(Varien_Object $object)
{
/**
* Add identifier for new category
*/
if (substr($object->getPath(), -1) == '/') {
$object->setPath($object->getPath() . $object->getId());
$this->_savePath($object);
}

$this->_saveCategoryProducts($object);
return parent::_afterSave($object);
}

/**
* Update path field
*
* @param Mage_Catalog_Model_Category $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _savePath($object)
{
if ($object->getId()) {
$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('path'=>$object->getPath()),
$this->_getWriteAdapter()->quoteInto('entity_id=?', $object-
>getId())
);
}
return $this;
}

protected function _getMaxPosition($path)


{
$select = $this->getReadConnection()->select();
$select->from($this->getTable('catalog/category'), 'MAX(position)');
$select->where('path ?', new Zend_Db_Expr("regexp '{$path}/[0-9]+\
$'"));

$result = 0;
try {
$result = (int) $this->getReadConnection()->fetchOne($select);
} catch (Exception $e) {

}
return $result;
}

/**
* Save category products
*
* @param Mage_Catalog_Model_Category $category
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _saveCategoryProducts($category)
{
$category->setIsChangedProductList(false);

/**
* new category-product relationships
*/
$products = $category->getPostedProducts();
/**
* Example re-save category
*/
if (is_null($products)) {
return $this;
}

/**
* old category-product relationships
*/
$oldProducts = $category->getProductsPosition();

$insert = array_diff_key($products, $oldProducts);


$delete = array_diff_key($oldProducts, $products);
/**
* Find product ids which are presented in both arrays
*/
$update = array_intersect_key($products, $oldProducts);
/**
* Use for update just products with changed position
*/
$update = array_diff_assoc($update, $oldProducts);

$productTable = $this->getTable('catalog/product');
$productUpdateSql = sprintf('UPDATE `%s` AS `e` SET
`category_ids`=(SELECT
GROUP_CONCAT(`category_id`) FROM `%s` AS `cp` WHERE
`cp`.`product_id`=`e`.`entity_id`)
WHERE `e`.`entity_id` IN(?)', $productTable, $this-
>_categoryProductTable);

/**
* Delete products from category
*
*/
if (!empty($delete)) {
$deleteIds = array_keys($delete);
$this->_getWriteAdapter()->delete($this->_categoryProductTable,
$this->_getWriteAdapter()->quoteInto('product_id in(?)',
$deleteIds) .
$this->_getWriteAdapter()->quoteInto(' AND category_id=?',
$category->getId())
);

$sql = $this->_getWriteAdapter()->quoteInto($productUpdateSql,
$deleteIds);
$this->_getWriteAdapter()->query($sql);
}

/**
* Add products to category
*
*/
if (!empty($insert)) {
$insertSql = array();
foreach ($insert as $k => $v) {
$insertSql[] = '('.(int)$category->getId().','.(int)$k.','.
(int)$v.')';
}
$sql = sprintf(
'INSERT INTO `%s` (`category_id`,`product_id`,`position`)
VALUES%s',
$this->_categoryProductTable,
join(',', $insertSql)
);
$this->_getWriteAdapter()->query($sql);

$insertIds = array_keys($insert);
$sql = $this->_getWriteAdapter()->quoteInto($productUpdateSql,
$insertIds);
$this->_getWriteAdapter()->query($sql);
}

/**
* Update product positions in category
*
*/
if (!empty($update)) {
foreach ($update as $k => $v) {
$cond = array(
$this->_getWriteAdapter()->quoteInto('category_id=?',
(int)$category->getId()),
$this->_getWriteAdapter()->quoteInto('product_id=?',
(int)$k)
);
$where = join(' AND ', $cond);
$bind = array(
'position' => (int)$v
);
$this->_getWriteAdapter()->update($this-
>_categoryProductTable, $bind, $where);
}
}

if (!empty($insert) || !empty($delete)) {
$productIds = array_unique(array_merge(array_keys($insert),
array_keys($delete)));
Mage::dispatchEvent('catalog_category_change_products', array(
'category' => $category,
'product_ids' => $productIds
));
}

if (!empty($insert) || !empty($update) || !empty($delete)) {


$category->setIsChangedProductList(true);
$categoryIds = explode('/', $category->getPath());
$this->refreshProductIndex($categoryIds);
}

return $this;
}

/**
* Get store identifiers where category is presented
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getStoreIds($category)
{
if (!$category->getId()) {
return array();
}

$nodePath = $this->_getTree()
->getNodeById($category->getId())
->getPath();

$nodes = array();
foreach ($nodePath as $node) {
$nodes[] = $node->getId();
}

$stores = array();
$storeCollection = Mage::getModel('core/store')->getCollection()-
>loadByCategoryIds($nodes);
foreach ($storeCollection as $store) {
$stores[$store->getId()] = $store->getId();
}

$entityStoreId = $category->getStoreId();
if (!in_array($entityStoreId, $stores)) {
array_unshift($stores, $entityStoreId);
}
if (!in_array(0, $stores)) {
array_unshift($stores, 0);
}
return $stores;
}

/**
* Get positions of associated to category products
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getProductsPosition($category)
{
$select = $this->_getWriteAdapter()->select()
->from($this->_categoryProductTable, array('product_id',
'position'))
->where('category_id=?', $category->getId());
$positions = $this->_getWriteAdapter()->fetchPairs($select);
return $positions;
}

/**
* Get chlden categories count
*
* @param int $categoryId
* @return int
*/
public function getChildrenCount($categoryId)
{
$select = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), 'children_count')
->where('entity_id=?', $categoryId);

$child = $this->_getReadAdapter()->fetchOne($select);

return $child;
}

/**
* Move category to another parent
*
* @param int $categoryId
* @param int $newParentId
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
public function move($categoryId, $newParentId)
{
$category = Mage::getModel('catalog/category')->load($categoryId);
$oldParent = $category->getParentCategory();
$newParent = Mage::getModel('catalog/category')->load($newParentId);

$childrenCount = $this->getChildrenCount($category->getId()) + 1;

// update children count of new parents


$parentIds = explode('/', $newParent->getPath());
$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('children_count' => new Zend_Db_Expr("`children_count` +
{$childrenCount}")),
$this->_getWriteAdapter()->quoteInto('entity_id IN (?)',
$parentIds)
);

// update children count of old parents


$parentIds = explode('/', $oldParent->getPath());
$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('children_count' => new Zend_Db_Expr("`children_count` -
{$childrenCount}")),
$this->_getWriteAdapter()->quoteInto('entity_id IN (?)',
$parentIds)
);

// update parent id
$this->_getWriteAdapter()->query("UPDATE
{$this->getEntityTable()} SET parent_id = {$newParent->getId()}
WHERE entity_id = {$categoryId}");

return $this;
}

/**
* Check if category id exist
*
* @param int $id
* @return bool
*/
public function checkId($id)
{
$select = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), 'entity_id')
->where('entity_id=?', $id);
return $this->_getReadAdapter()->fetchOne($select);
}

/**
* Check array of category identifiers
*
* @param array $ids
* @return array
*/
public function verifyIds(array $ids)
{
$validIds = array();
$select = $this->_getWriteAdapter()->select()
->from($this->getEntityTable(), 'entity_id')
->where('entity_id IN(?)', $ids);
$query = $this->_getWriteAdapter()->query($select);
while ($row = $query->fetch()) {
$validIds[] = $row['entity_id'];
}
return $validIds;
}

/**
* Get count of active/not active children categories
*
* @param Mage_Catalog_Model_Category $category
* @param bool $isActiveFlag
* @return int
*/
public function getChildrenAmount($category, $isActiveFlag = true)
{
$storeId = Mage::app()->getStore()->getId();
$attributeId = $this->_getIsActiveAttributeId();
$table = Mage::getSingleton('core/resource')-
>getTableName('catalog/category') . '_int';

$select = $this->_getReadAdapter()->select()
->from(array('m'=>$this->getEntityTable()),
array('COUNT(m.entity_id)'))
->joinLeft(
array('d'=>$table),
"d.attribute_id = '{$attributeId}' AND d.store_id = 0 AND
d.entity_id = m.entity_id",
array()
)
->joinLeft(
array('c'=>$table),
"c.attribute_id = '{$attributeId}' AND c.store_id =
'{$storeId}' AND c.entity_id = m.entity_id",
array()
)
->where('m.path like ?', $category->getPath() . '/%')
->where('(IFNULL(c.value, d.value) = ?)', $isActiveFlag);

return $this->_getReadAdapter()->fetchOne($select);
}

/**
* Get "is_active" attribute identifier
*
* @return int
*/
protected function _getIsActiveAttributeId()
{
if (is_null($this->_isActiveAttributeId)) {
$select = $this->_getReadAdapter()->select()
->from(array('a'=>$this->getTable('eav/attribute')),
array('attribute_id'))
->join(array('t'=>$this->getTable('eav/entity_type')),
'a.entity_type_id = t.entity_type_id')
->where('entity_type_code = ?', 'catalog_category')
->where('attribute_code = ?', 'is_active');

$this->_isActiveAttributeId = $this->_getReadAdapter()-
>fetchOne($select);
}
return $this->_isActiveAttributeId;
}

/**
* Rebuild associated products index
*
* @param array $categoryIds
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
public function refreshProductIndex($categoryIds = array(), $productIds =
array(), $storeIds = array())
{
/**
* Prepare visibility and status attributes information
*/
$statusAttribute = Mage::getSingleton('eav/config')-
>getAttribute('catalog_product', 'status');
$visibilityAttribute = Mage::getSingleton('eav/config')-
>getAttribute('catalog_product', 'visibility');
$statusAttributeId = $statusAttribute->getId();
$visibilityAttributeId = $visibilityAttribute->getId();
$statusTable = $statusAttribute->getBackend()->getTable();
$visibilityTable = $visibilityAttribute->getBackend()-
>getTable();

/**
* Select categories data
*/
$select = $this->_getReadAdapter()->select()
->from($this->getTable('catalog/category'))
->order('level')
->order('path');
if (is_array($categoryIds) && !empty($categoryIds)) {
$select->where('entity_id IN (?)', $categoryIds);
} elseif (is_numeric($categoryIds)) {
$select->where('entity_id=?', $categoryIds);
}

$categories = $this->_getWriteAdapter()->fetchAll($select);

$storesCondition = '';
if (!empty($storeIds)) {
$storesCondition = $this->_getWriteAdapter()->quoteInto(
' AND s.store_id IN (?)', $storeIds
);
}

/**
* Get information about stores root categories
*/
$stores = $this->_getWriteAdapter()->fetchAll("
SELECT
s.store_id, s.website_id, c.path AS root_path
FROM
{$this->getTable('core/store')} AS s,
{$this->getTable('core/store_group')} AS sg,
{$this->getTable('catalog/category')} AS c
WHERE
sg.group_id=s.group_id
AND c.entity_id=sg.root_category_id
{$storesCondition}
");

$indexTable = $this->getTable('catalog/category_product_index');

foreach ($stores as $storeData) {


$storeId = $storeData['store_id'];
$websiteId = $storeData['website_id'];
$rootPath = $storeData['root_path'];

$productCondition = '';
if (!empty($productIds)) {
$productCondition = $this->_getWriteAdapter()->quoteInto(
' AND product_id IN (?)', $productIds
);
}
$insProductCondition = str_replace('product_id', 'cp.product_id',
$productCondition);
foreach ($categories as $category) {
$categoryId = $category['entity_id'];
$path = $category['path'];

$this->_getWriteAdapter()->delete(
$indexTable,
'category_id='.$categoryId. ' AND store_id='.$storeId.
$productCondition
);

if (strpos($path.'/', $rootPath.'/') === false) {


continue;
}

$query = "INSERT INTO {$indexTable}


(`category_id`, `product_id`, `position`, `is_parent`,
`store_id`, `visibility`)
SELECT
{$categoryId},
cp.product_id,
cp.position,
{$categoryId}=cp.category_id as is_parent,
{$storeId},
IFNULL(t_v.value, t_v_default.value)
FROM
{$this->getTable('catalog/category_product')} AS cp
INNER JOIN {$this->getTable('catalog/product_website')} AS pw
ON pw.product_id=cp.product_id AND
pw.website_id={$websiteId}
INNER JOIN {$visibilityTable} AS `t_v_default`
ON (t_v_default.entity_id = cp.product_id)
AND
(t_v_default.attribute_id='{$visibilityAttributeId}')
AND t_v_default.store_id=0
LEFT JOIN {$visibilityTable} AS `t_v`
ON (t_v.entity_id = cp.product_id)
AND (t_v.attribute_id='{$visibilityAttributeId}')
AND (t_v.store_id='{$storeId}')
INNER JOIN {$statusTable} AS `t_s_default`
ON (t_s_default.entity_id = cp.product_id)
AND (t_s_default.attribute_id='{$statusAttributeId}')
AND t_s_default.store_id=0
LEFT JOIN {$statusTable} AS `t_s`
ON (t_s.entity_id = cp.product_id)
AND (t_s.attribute_id='{$statusAttributeId}')
AND (t_s.store_id='{$storeId}')
WHERE category_id IN(
SELECT entity_id FROM {$this-
>getTable('catalog/category')}
WHERE entity_id = {$category['entity_id']} OR path LIKE
'{$path}/%')
AND (IFNULL(t_s.value,
t_s_default.value)=".Mage_Catalog_Model_Product_Status::STATUS_ENABLED.")
{$insProductCondition}
GROUP BY product_id
ORDER BY is_parent desc";

$this->_getWriteAdapter()->query($query);
}
}
return $this;
}

public function findWhereAttributeIs($entityIdsFilter, $attribute,


$expectedValue)
{
$select = $this->_getReadAdapter()->select()
->from($attribute->getBackend()->getTable(), array('entity_id'))
->where('attribute_id = ?', $attribute->getId())
->where('value = ?', $expectedValue)
->where('entity_id in (?)', $entityIdsFilter);

return $this->_getReadAdapter()->fetchCol($select);
}

/**
* Get products count in category
*
* @param unknown_type $category
* @return unknown
*/
public function getProductCount($category)
{
$productTable =Mage::getSingleton('core/resource')-
>getTableName('catalog/category_product');

$select = $this->getReadConnection()->select();
$select->from(
array('main_table'=>$productTable),
array(new Zend_Db_Expr('COUNT(main_table.product_id)'))
)
->where('main_table.category_id = ?', $category->getId())
->group('main_table.category_id');
$counts =$this->getReadConnection()->fetchOne($select);

return intval($counts);
}

/**
* Deprecated since 1.1.7
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _saveCountChidren($object)
{
$chidren = $object->getChildren();
if (strlen($chidren)>0) {
$chidrenCount = count(explode(',', $chidren));
} else {
$chidrenCount = 0;
}
$this->_getWriteAdapter()->update($this->getEntityTable(),
array('children_count'=>$chidrenCount),
$this->_getWriteAdapter()->quoteInto('entity_id=?', $object-
>getId())
);

return $this;
}

/**
* Deprecated
*
* @param Varien_Object $object
* @return unknown
*/
protected function _saveInStores(Varien_Object $object)
{
if (!$object->getMultistoreSaveFlag()) {
$stores = $object->getStoreIds();
foreach ($stores as $storeId) {
if ($object->getStoreId() != $storeId) {
$newObject = clone $object;
$newObject->setStoreId($storeId)
->setMultistoreSaveFlag(true)
->save();
}
}
}
return $this;
}

/**
* Deprecated
*/
protected function _updateCategoryPath($category, $path)
{
return $this;
if ($category->getNotUpdateDepends()) {
return $this;
}
foreach ($path as $pathItem) {
if ($pathItem->getId()>1 && $category->getId() != $pathItem-
>getId()) {
$category = Mage::getModel('catalog/category')
->load($pathItem->getId())
->save();
}
}
return $this;
}

/**
* Retrieve categories
*
* @param integer $parent
* @param integer $recursionLevel
* @param boolean|string $sorted
* @param boolean $asCollection
* @param boolean $toLoad
* @return Varien_Data_Tree_Node_Collection|
Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection
*/
public function getCategories($parent, $recursionLevel = 0,
$sorted=false, $asCollection=false, $toLoad=true)
{
$tree = Mage::getResourceModel('catalog/category_tree');
/** @var $tree Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Tree
*/
$nodes = $tree->loadNode($parent)
->loadChildren($recursionLevel)
->getChildren();

$tree->addCollectionData(null, $sorted, $parent, $toLoad, true);

if ($asCollection) {
return $tree->getCollection();
}
return $nodes;
}

/**
* Return parent categories of category
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getParentCategories($category)
{
$pathIds = array_reverse(explode(',', $category->getPathInStore()));
$categories = Mage::getResourceModel('catalog/category_collection')
->setStore(Mage::app()->getStore())
->addAttributeToSelect('name')
->addAttributeToSelect('url_key')
->addAttributeToSelect('image')
->addFieldToFilter('entity_id', array('in'=>$pathIds))
->addFieldToFilter('is_active', 1)
->load()
->getItems();
return $categories;
}

/**
* Enter description here...
*
* @param Mage_Catalog_Model_Category $category
* @return unknown
*/
public function getChildrenCategories($category)
{
$collection = $category->getCollection();
/* @var $collection
Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection */
$collection->addAttributeToSelect('url_key')
->addAttributeToSelect('name')
->addAttributeToSelect('image')
->addAttributeToSelect('all_children')
->addAttributeToSelect('is_anchor')
->addAttributeToFilter('is_active', 1)
->addIdFilter($category->getChildren())
->setOrder('position', 'ASC')
->joinUrlRewrite()
->load();
return $collection;
}

/**
* Return children ids of category
*
* @param Mage_Catalog_Model_Category $category
* @param boolean $recursive
* @return array
*/
public function getChildren($category, $recursive = true)
{
$attributeId = $this->_getIsActiveAttributeId();
$select = $this->_getReadAdapter()->select()
->from(array('m' => $this->getEntityTable()), 'entity_id')
->joinLeft(
array('d' => $this->getEntityTable() . '_int'),
"d.attribute_id = '{$attributeId}' AND d.store_id = 0 AND
d.entity_id = m.entity_id",
array()
)
->joinLeft(
array('c' => $this->getEntityTable() . '_int'),
"c.attribute_id = '{$attributeId}' AND c.store_id =
'{$category->getStoreId()}' AND c.entity_id = m.entity_id",
array()
)
->where('(IFNULL(c.value, d.value) = ?)', '1')
->where('path LIKE ?', "{$category->getPath()}/%");
if (!$recursive) {
$select->where('level <= ?', $category->getLevel() + 1);
}
$_categories = $this->_getReadAdapter()->fetchAll($select);
$categoriesIds = array();
foreach ($_categories as $_category) {
$categoriesIds[] = $_category['entity_id'];
}

return $categoriesIds;

// $this->_getTree()->load();
// return $this->_getTree()->getChildren($category->getId(), false);
}

/**
* Return all children ids of category (with category id)
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getAllChildren($category)
{
$children = $this->getChildren($category);
$myId = array($category->getId());
$children = array_merge($myId, $children);

return $children;

// $this->_getTree()->load();
// $children = $this->_getTree()->getChildren($category->getId());
//
// $myId = array($category->getId());
// if (is_array($children)) {
// $children = array_merge($myId, $children);
// } else {
// $children = $myId;
// }
//
// return $children;
}

/**
* Check is category in list of store categories
*
* @param Mage_Catalog_Model_Category $category
* @return boolean
*/
public function isInRootCategoryList($category)
{
$innerSelect = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), new Zend_Db_Expr("CONCAT(path, '/
%')"))
->where('entity_id = ?', Mage::app()->getStore()-
>getRootCategoryId());
$select = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), 'entity_id')
->where('entity_id = ?', $category->getId())
->where(new Zend_Db_Expr("path LIKE ({$innerSelect-
>__toString()})"));
return (bool) $this->_getReadAdapter()->fetchOne($select);

// $tree = $this->_getTree();
// $tree->load();
// $children = $tree->getChildren(Mage::app()->getStore()-
>getRootCategoryId(), true);
// if (!in_array($category->getId(), $children)) {
// return false;
// }
// return true;
}
}

Contenido del archivo sub_category_listing.phtml


<?php
$category = $this->getCurrentCategory();
$id = $category->getId();
?>
<?php $_categories=$this->getCurrentChildCategories(); ?>
<?php foreach ($_categories as $_category): ?>
<div class="categorylisting">
<?php if($_category->getIsActive()): ?>
<div class="product-image">
<a href="<?php echo $_category->getURL() ?>"
title="<?php echo $this->htmlEscape($_category->getName()) ?>">
<img src="<?php echo $_category->getImageUrl() ?>" width="140" alt="<?php
echo $this->htmlEscape($_category->getName()) ?>" />
</a>
<?php /* echo "Find this item->" */ ?>
</div>
<h2><a href="<?php echo $_category->getURL() ?>"
title="<?php echo $this->htmlEscape($_category->getName()) ?>"><?php echo
$this->htmlEscape($_category->getName()) ?></a></h2>
<?php echo $_category->getDescription() ?>
<?php endif; ?>
</div>
<?php endforeach; ?>

Modificación en el listado de subcategorías. Mostrando a dos columnas

Esta modificación viene en el mismo enlace mencionado al comienzo, y consiste en cambiar el fichero
sub_category_listing.phtml ara que muestre las subcategorías en dos solumans. También ah y que incluir
nuevos estilos en la hoja de estilos:
El contenido del fichero sub_category_listing.phtml es el siguiente:
<?php
$category = $this->getCurrentCategory();
$id = $category->getId();
?>
<?php $_categories=$this->getCurrentChildCategories(); ?>
<div class="list-type-grid category-listing">
<?php $i=0; foreach ($_categories as $_category): ?>
<?php if($i==0): ?>
<ol class="grid-row">
<?php endif; ?>
<li class="item">
<?php if($_category->getIsActive()): ?>
<div class="product-image">
<a href="<?php echo $_category->getURL() ?>" title="<?php
echo $this->htmlEscape($_category->getName()) ?>">
<img src="<?php echo
$_category->getImageUrl() ?>" width="140" alt="<?php echo $this-
>htmlEscape($_category->getName()) ?>" />
</a>
</div>
<h5><a href="<?php echo $_category->getURL() ?>" title="<?php echo
$this->htmlEscape($_category->getName()) ?>"><?php echo $this->htmlEscape($_category-
>getName()) ?></a></h5>
<?php echo $_category->getDescription() ?>
<?php endif; ?>
</li>
<?php ($i = $i+1); ?>
<?php if($i==2):?>
</ol>
<?php ($i = 0); ?>
<?php endif; ?>
<?php endforeach ?>
<script type="text/javascript">decorateGeneric($$('.grid-row'), ['last',
'odd', 'even']);</script>
</div>

Y los estilos nuevos son:


.list-type-grid { }
.category-listing { line-height:1.35em; }
.list-type-grid .grid-row { }
.list-type-grid li.item { float:left; line-height:1.6em; overflow:hidden; padding:10px
5px; width:227px; }

Eliminar el filtro de Categorías en Comprar Por (Shop By)


El problema que se presenta es que los atributos que hemos creado podemos hacer que sean usados para
establecer este filtro o no (activando Layered Navigation en la ficha del atributo), pero esto en el caso de las
categorías no ocurre, puesto que no son un atributo, o bien son un atributo en si usado por defecto en
Magento.
Opción 1. No funciona.
En el siguiente enlace aparecen varias posiblidades, yo he escogido la de “mjeebu”, porque las otras parece
ser que no funcionan con la nueva versión de Magento, o bien consisten en toca el Core, cosa que no me
apetece mucho y es poco aconsejable. La dirección del enlace es la siguiente:
http://www.magentocommerce.com/boards/viewthread/28220/P15/
Y dice lo siguiente:
Otro camino para hacer esto es vía CSS, necesitará añadir el siguiente trozo de código al archivo siguiente:
\app\design\frontend\default\theme\template\catalog\layer\view.phtml
<?php
$tmpTitle = $this->htmlEscape($this->__($_filter->getName()));
$tmpTitle = strtolower($tmpTitle);
$tmpTitle = preg_replace("/[\s]+/", "-", $tmpTitle);
?>
<dt class="<?=$tmpTitle?>"><?php echo $this->__($_filter->getName()) ?></dt>
<dd class="<?=$tmpTitle?>">
<?php echo $_filter->getHtml() ?>
</dd>

Lo que la primera parte hace es tomar el "título" de los atributos (Fijado en la sección de Gestión de atributos
en back end) y cambia el "título" a minúsculas y los espacios por "-" (en el caso de que el nombre del atributo
tenga más de una palabra).
Entonces la segunda parte inyecta la variable $ tmpTitle como una etiqueta de "clase" para su uso por CSS
con un poco de magia!.
Ahora todo los que se necestia hacer es ir al archivo CSS y por ejemplo, si queremos ocultar un atributo
como la Categoría, hacer una entrada CSS como la siguiente:
.layered-nav .category { display: none; }

O si queremos ocultar el precio:


.layered-nav .price { display: none; }

He encontrado que esta técnica me da más control general. Por ejemplo, en algunas categorías, puede ser
que se desee mostrar Precio mientras que en otras no.
Opción 2. No funciona
Del enlace: http://www.imagedia.com/2010/04/remove-categories-from-shop-by-options-in-magento/
Consiste en sustituir el contenido del archivo:
app/design/frontend/default/your_template/template/catalog/layer/view.phtml
Por el siguiente código:
<?php
/**
* Category layered navigation
*
* @see Mage_Catalog_Block_Layer_View
*/
?>
<?php if($this->canShowBlock()): ?>
<div class=”box layered-nav”>
<div class=”head”>
<h3><?php echo $this->__(’Shop by’) ?></h3>
</div>
<div class=”border-creator”>
<?php echo $this->getStateHtml() ?>
<?php if($this->canShowOptions()): ?>
<div class=”narrow-by”>
<h4><?php echo $this->__(’Browsing Options’) ?></h4>
<dl id=”narrow-by-list”>
<?php $_filters = $this->getFilters() ?>
<?php foreach ($_filters as $_filter): ?>
<?php if($_filter->getItemsCount()): ?>
<?php if($_filter->getName() != “Category”){ ?>
<dt><?php echo $this->__($_filter->getName()) ?></dt>
<dd>
<?php echo $_filter->getHtml() ?>
</dd>
<?php } endif; ?>
<?php endforeach; ?>
</dl>
<script type=”text/javascript”>decorateDataList(’narrow-by-list’)</script>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<!– [ends] .browse-by // –>

Opción 3: Funciona pero hay que tocar el Core


Del enlace: http://www.magentocommerce.com/boards/viewthread/33199/
Editamos el archivo go to app/code/core/Mage/Catalog/Block/Layer/View.php
Y comentamos la siguiente línea:
$filters[] = $categoryFilter;

Opción 4: Usando una extensión. No la he probado, aunque dice que vale para todas las versiones de
Magento.
La llave de la extensión es: magento-community/Adtrak_DisableCategoryFilter-0.1.0
El enlace donde se encuentra: http://www.magentocommerce.com/extension/packages/module/1678/disable-
layered-nav-category-filter#releases

Eliminar la opción de Ordenar por en la vista de listado de productos


No he encontrado nada respecto a eliminar esta opción de forma funcional, así que opté por hacerlo a través
de los estilos.
Simplemente añadimos display:none en la siguiente línea en la hoja de estilos:
.sorter{ display:none; font-size:11px; background:#fff url(../images/bkg_toolbar.gif) 0
100% repeat-x; padding:3px 8px; border-top:1px solid #e2e2e2; }

Eliminar el Bloque Comparar Productos


Editamos el fichero //app/design/frontend/default/mi tema/layout/catalog.xml, y comentamos la línea siguiente
que se encuentra casi al principio del fichero:
<!--<block type="catalog/product_compare_sidebar" after="cart_sidebar"
name="catalog.compare.sidebar" template="catalog/product/compare/sidebar.phtml"/>-->

Cómo modificar las plantillas de correo

Las plantillas de correo se encuentran en la ruta: //app/locale/es_ES/template/email, o la que corresponda al


idioma de la tienda.

Quitar suscripción a las Newsletter


Las quitamos como Bloque, pero no quitamos la posiblidad de que un usuario registrado se suscriba.
Simplemente tenemos que comentar las siguientes líneas en el archivo:
//app/design/frontend/default/mi_tema/layout/newsletter.xml:
<!--
<default>
<!-- Mage_Newsletter -->
<reference name="right">
<block type="newsletter/subscribe" after="_"
name="right.newsletter" template="newsletter/subscribe.phtml"/>
</reference>
</default>
-->

Las líneas evidentemente ya aparecen comentadas.


De este modo ya nos aparece a la izquierda menos en la vista

Cambiar de Posición el Bloque Productos Vistos


Recientemente
Como tengo hecha una modificación para que me muestre las subcategorías de segundo nivel en una página
(visto anteriormente en este documento), he tenido que hacer dos cambios, no obstante, creo que aún no
teniendo dicha modificación hecha es necesario igualmente hacer los dos cambios.
Como no sabía cuál era el fichero de la plantilla que hace referencia a este bloque activé la visibilidad de las
rutas desde el back end en Sistema – Configuracion – Desarrollador. El fichero de la plantilla que
corresponde a este bloque es product_viewed.phtml. Ahora solo tenemos que buscar la referencia (en la que
aparecerá el nombre del fichero) dentro de los ficheros que correspondan.
Los cambios se hacen en los ficheros del layout en la ruta: /app/design/frontend/default/mitema/layout
En concreto tocamos los siguientes ficheros: catalog.xml y reports.xml
Cambios en el fichero catalog.xml:
Buscamos las siguiente líneas:
<catalog_category_layered_nochildren translate="label">
<label>Catalog Category (Without Subcategories)</label>
<remove name="right.reports.product.viewed" />
<reference name="left">
<block type="reports/product_viewed"
before="right.permanent.callout" name="left.reports.product.viewed"
template="reports/product_viewed.phtml" />
</reference>
</catalog_category_layered_nochildren>

estas líneas se encuentran en la sección del fichero Category layered navigation layout
Lo que he hecho es comentar la línea que referencia a product_viewed.phtml para mantener el original, y
después la he copiado y modificado según aparece en el resultado final a continuación, también he cambiado
la posición de right a left en la etiqueta <reference name>:
<remove name="right.reports.product.viewed" />
<reference name="left">
<!-- <block type="reports/product_viewed"
before="right.permanent.callout" name="left.reports.product.viewed"
template="reports/product_viewed.phtml" />-->
<block type="reports/product_viewed"
name="left.reports.product.viewed" template="reports/product_viewed.phtml" />
</reference>
</catalog_category_layered_nochildren>

Bien mediante este cambio conseguimos que en la vista de catálogo los productos vistos recientemente
aparezcan a la izquierda, pero como las páginas de vistas de subcategorías realmente son listados o lo que
es lo mismo reportes, entonces me dirijo al archivo reports.xml. El contenido de este archivo se limita a:
<layout version="0.1.0">
<default>
<!-- Mage_Reports -->
<reference name="right">
<block type="reports/product_viewed"
before="right.permanent.callout" name="right.reports.product.viewed"
template="reports/product_viewed.phtml" />
<block type="reports/product_compared"
before="right.permanent.callout" name="right.reports.product.compared"
template="reports/product_compared.phtml" />
</reference>
</default>
</layout>

Bien pues tendremos que cambiarlo para que cambie de posición el bloque de productos vistos
recientemente que está referenciado en el primer block type. Dejando el contenido del archivo del siguiente
modo:
<layout version="0.1.0">
<default>
<!-- Mage_Reports -->
<reference name="left">
<block type="reports/product_viewed"
before="right.permanent.callout" name="right.reports.product.viewed"
template="reports/product_viewed.phtml" />
</reference>

<reference name="right">
<!--<block type="reports/product_viewed" before="right.permanent.callout"
name="right.reports.product.viewed" template="reports/product_viewed.phtml" />-->
<block type="reports/product_compared"
before="right.permanent.callout" name="right.reports.product.compared"
template="reports/product_compared.phtml" />
</reference>
</default>
</layout>
(PENDIENTE) Colocando Banners en Magento

Creando Enlaces a Archivos PDF en páginas html


Aunque parezca mentira el editor Tiny MCE en Magento no permite la inclusión de enlaces a archivos que no
sean de imágenes. Me encontré con esto al intentar crear enlaces a documentos PDF (que ya sabemos que
el navegador los maneja abriendo el lector de dichos documentos de forma automática) en una página html.
Pues bien, opté por la calle de en medio. Subí los ficheros a través de FTP a una carpeta creada en expreso
para ello en la raíz, es decir, en la carpeta html, a esta carpeta le di permisos 755, porque comprobando
combinaciones más restricitivas los PDF no se abrían (ojo al dar los permisos que si lo hacemos después de
subir los archivos debemos hacer que dichos permisos se apliquen de forma recursiva).
Bien, una vez subidos los archivos y dados los permisos, me fui al administrador de páginas en Magento, abrí
la página correspondiente y le di al botón de ver código HTML, para editar a pelo los enlaces. Ojo también
con esto que si no lo hacemos bien nos podemos encontrar que el editor intente corregir los fallos (como
hace cuando pegamos texto desde un procesador de texto que le añade a las líneas inservibles en html los
caracteres de comentario: <!-- y -->), y nos descuageringue la página.
Bien para hacer el enlace recurrimos al HTML puro y duro, buscamos en la ventana la parte o texto que
queremos enlazar y añadimos lo siguiente:
<a href="/carpeta_contenedora/nombre_del_archivo.pdf" target="_blank">Texto que hace de link</a>
En Target podemos emplear cualquiera de los valores propios de la etiqueta, yo he usado Blank para abrir en
vantana nueva, podemos usar Self para abrir en la misma, etc....(si existe el etc...en este caso).
Y eso es todo, sólo queda probar que funcione.

Incrementando la seguridad de la carpeta que contiene los PDF

Una vez hecho lo anterior me di cuenta que si te situabas encima del enlace al fichero te daba la ruta, si la
copias y la pegas en el navegador te muestra el directory Index, vamos que ve lo que hay ahí, y tal y como
están las cosas es poco recomendable. Así que intenté mejorar la seguridad, ¿cómo?, buscando en Google y
con los famosos ficheros .htaccess
Bien, para evitar que te listen el índice de la carpeta, en la misma creamos un .htaccess en el que incluimos
la siguiente línea:
Options -Indexes

Así nos mostrará la típica página de Apache con el Forbidden...perooo....en esta página se nos muestra tanto
el sistema operativo como el apache y su versión, tampoco me gusta. Así que busqué un poco más, y de
nuevo el ficherito .htaccess nos va a ser útil.
Incluí la siguiente línea en el mismo, y listo, ahora la página que me muestra es la que tiene por defecto
Magento para las páginas no encontradas:
ErrorDocument 403 /html/errors/404.php

Con estas dos líneas y el ficherito hemos contribuido en algo a la seguridad de nuestra tienda.

Traducir el valor del atributo Gender


Lo primero es traducir Gender (Género). Lo haremos desde el archivo /app/locale/es_ES/Mage_Customer.csv
Incluimos la Línea Gender y su traducción Sexo, tal y como pòdemos observar en las líneas del Archivo.
Otra cosa es traducir el valor que trae por defecto este Campo (Male y Female), he encontrado un post sobre
este tema (en Portugués menos mál que a nuestros hermanos es fácil entenderlos), hay que modifcar el valor
de en la tabla: eav_attribute_option_value
Esta solución sin duda alguna funcionará, pero tengo el problema de qué pasa cuando la tienda está en
varios idiomas.
Por cierto la ruta del post es: http://www.magentocommerce.com/boards/viewthread/180194/

Traducir la etiqueta Availability: en la página de


producto
Incluyo esta modificación porque aunque una vez que hemos traducido algo (a excepción de los valores de
algún campo) el procedimiento es prácticamente el mismo para cualquier cosa que queramos traducir, pero
ojo, porque podemos encontrarnos con casos como este.
Quería traducir esta etiqueta para que apareciera en español, revisé el fichero
/app/locale/es_ES/Mage_Catalog.csv y encontré la palabra Availability traducida. Pero esta traducción no se
reflejaba en la página de vista del producto.
Opté por incluirla en el archivo locale de mi tema, de la forma habitual: "Availability","Disponibilidad",
sin resultado.
Cuando estaba a punto de tirar por la calle de en medio, es decir, irme al fichero de la template
(app/design/frontend/default/default/template/catalog/product/view/type/ ) y cambiar la etiqueta a pelo, con lo
que cuando pusiera la tienda en otros idiomas seguiría teniendo un problema, caí en la cuenta de que en el
fichero de la template Availability estaba precedida por los dos puntos. Me dije: “ a ver si va a ser esto”. Así
que edité el fichero Es_es de la carpeta locale de mi tema /app/design/frontend/default/mitema/locale/es_ES,
e incluí la línea con los dos puntos, tal que así: "Availability:","Disponibilidad:", y funcionó a la
perfección. Esto es un aviso a navegantes para que se tenga claro que lo que se traduce debe ser el texto
idéntico a lo que aparece e la plantilla.
Después para curarme en salud y para eliminar este pequeño bug de Magento hice lo propio en el fichero
Mage_Catalog.csv

Habilitando el pago por transferencia y cambiando los


textos
Del enlace: http://onestic.com/cambiar-textos-en-modulo-de-pago-en-magento-transferencia-bancaria/
El pago por transferencia viene de serie con Magento 1.4, pero se llama Check/Money Order.
Para habilitarlo rellenamos los campos de este Método de pago del siguiente modo:
Habilitado: Si
Título: Pondremos el título que queremos que aparezca en el Front End por ejemplo: Pago por
Transferencia.
New Order Status: Lo suyo es dejarlo en pendiente.
Payment from Applicable Countries: Podemos indicar Todos los paises permitidos o especificar en la lista
que vendrá justo a continuación los páises en los que permitiremos esta forma de pago.
Payment from Specific Countries: Aquí seleccionaremos los países en los que queremos tener esta forma
de pago. Se activa si en el campo anterior hemos seleccionado Especificar países.
Make Check Payable to: Este lo dejamos en blanco.
Enviar cheque a: Aquí pondremos los datos del banco y del IBAN si hacemos comercio exterior.
Mínimo pedido: El pedido mínimos que aceptamos para esta forma de pago.
Máximo pedido: Justo lo contrario que lo anterior.
Ordenar Pedido: No estoy seguro, pero me da que es el orden en que queremos que aparezca esta forma
de pago respecto al resto que tengamos configuradas.
Bueno pues ya está disponible esta forma de pago, solo que en el front end nos aparece el siguiente texto
“Enviar Cheque a”
Bien vamos a cambiar este texto y además vamos a incluir otro para avisar el cliente que el pedido no es
procesado hasta tanto no se verifique la transferencia, por lo que los envíos pueden retrasarse 48 horas.
Bueno, para cambiar el texto “Enviar Cheque a:”, vamos a hacerlo desde el fichero de traducción
/app/locale/es_ES/Mage_Payment.csv . Buscamos el texto y cambiamos la traducción.
La inclusión del texto es otra historia. En la versión 1.4.1.1 he encontrado algunos post en los que se dice que
presenta problemas con la traducción inline. Intenté incluir un texto que luego fuera traducible en el fichero
/app/design/frontend/default/mitema/template/payment/form/checkmo.phtml mediante la siguiente línea que
coloqué al final del fichero:
<?php echo $this->__('This payment method means that shipments are not processed until the transfer
is not confirmed, so delivery time may be delayed 48 hours.') ?>
Y no me funcionó, en el progreso de compra no pasaba del método de envío. Pero como no se PHP no se si
esto era lo adecuado.
Así que me he conformado con incluir un texto en castellano, agregando antes del <?php endif; ?>
<spam class="success-msg">Esta método de pago retrasa la entrega en al menos 48 horas
por requerir confirmación de transferencia</spam>

Si alguien que lea este documento sabe como hacerlo, pues que aporte.

Resolviendo Problema en el Progreso de Compra: “Card


Verification Please verify the card with the issuer bank”
Resulta que en el progreso de compra en el paso 5 que dice “Revisión del Pedido” me aparecía un mensaje
tal que así:
Card Verification
Please verify the card with the issuer bank.
Y no aparecía nada más, sólo un cuadro en blanco, pero de revisión de pedido nada.
Bien parece que es un Bug de la versión, pero se soluciona de una forma poco adecuada, pero se soluciona,
consiste en desactivar el modo centinela. Para ello iremos a Sistema – Configuración – Avanzado – Avanzado
y deshabilitaremos el módulo Mage_Centinel.
Se puede encontrar información sobre esto en el post:
http://www.magentocommerce.com/boards/viewthread/196550/

Eliminando del Panel de Control de Mi Cuenta los enlaces


Billing Agreements y Recurring Profiles
Del Enlace: http://www.magentocommerce.com/boards/viewthread/197799/#t248148
Estos dos enlaces están incluidos en la versión 1.4.1.1. Pero no existe documentación respecto a su
funcionalidad, además en el panel de administración sólo he visto una referencia a Billing Agreements en la
forma de Pago PayPal. En consecuencia, tanto si no vamos a usar PayPal como si no queremos
complicarnos la vida hasta que no haya una documentación en condiciones lo mejor es quitar estos enlaces.
El caso es que quitarlos no es tan sencillo porque por lo visto van embebidos en el código y no hay archivo n
del template ni del layuot que tocar.
Pero en el enlace apuntado al principio de este epígrafe nos dan una solución sencilla. Dentro del layout
creamos una carpeta “sales” y ahí incluimos dos archivos con el contenido que se indica. De este modo
procederemos así:
1. Dentro de /app/design/frontend/default/mi tema/layout creamos la carpeta “sales”.
2. Dentro de /app/design/frontend/default/mi tema/layout/sales creamos dos archivos:
billing_agreement.xml y recurring_profile.xml
3. El contenido de ambos archivos es exactamente el mismo que se indica:
<?xml version="1.0"?>
<layout version="0.1.0">
</layout>

En ese mismo post viene otra forma de hacerlo pero es algo más complicada. A mi esta me funcionó.

(PENDIENTE) Extensión Auguria Sponsorchip

Cambiando la fisonomía del Panel de Control del Cliente


Lo primero el Panel de Control del Cliente (en la interfaz Mi Panel de Control), carga el diseño a dos
columnas con una a la izquierda. En la columna de la izquiera nos aparece el menú de navegación Mi
Cuenta, Los productos vistos recientemente, Una llamada (la del perrito) y el carrito de compras.
Para cambiar el diseño a dos columnas pero una de ellas a la derecha vamos a editar el fichero;
/app/design/frontend/default/mi tema/layout/customer.xml
Buscamos la siguiente sección dentro del archivo:
<!--
Customer account home dashboard layout
-->

Y ahí la línea que dice lo siguiente:


<action method="setTemplate"><template>page/2columns-left.phtml</template></action>

Y la sustituimos por:
<action method="setTemplate"><template>page/2columns-right.phtml</template></action>

Ok...si ahora refrescamos la pàgina (teniendo la caché de Magento deshabilitada), veremos que la columna
aparece a la derecha pero que los bloques han cambiado, no nos aparece el Menú de Mi Cuenta, ni el carrito,
ni el perrito, etc....¿Por qué?. Veamos la sección justo anterior a la que hemos visto de este archivo, donde
pone:
<!--
Customer account pages, rendered for all tabs in dashboard
-->

Nos fijamos en la línea siguiente:


<reference name="root">
<action method="setTemplate"><template>page/2columns-
left.phtml</template></action>
</reference>
Y también en la línea:
<reference name="left">

Bien pues en ambas líneas vamos a cambiar la palabra left por right. Ahora si nos aparece el menú de Mi
Cuenta y el Carrito, es más éste nos aparece duplicado. Pero no nos aparece los productos vistos
recientemente y el perrito. Ese me da igual porque no lo quiero en esta página, pero quiero que aparezcan
los productos vistos recientemente y obviamente quitar un carrito de la compra, así como otro menú que
tengo yo de opciones de usuario creado con los toplinks.
Para eso sólo tenemos que repasar el código de ambas secciones y veremos las referencias a lo que
queremos o no queremos.
Bien para quitar el menú opciones de usuario que yo tengo (que son los toplinks convertidos en bloque, ya
hemos visto como hacerlo en este documento), y que según revisamos en el fichero customer.xml se cargan
en todas aquellas páginas en lo que no se diga lo contrario, tendremos que hacer precisamente eso: Decirle
lo contrario. Y para eso nos sirve la etiqueta <remove>
En la sección:
<!--
Customer account pages, rendered for all tabs in dashboard
-->

Que lo que nos dice es que son las páginas de la cuenta del cliente, que se reproducen para todas las
etiquetas (enlaces) en el panel de control, añadimos los siguiente antes del final de la sección, quedando tal
que así:
</reference>
<remove name="top.links"></remove>
</customer_account>

Así evitamos que el bloque que creé con los toplinks aparezca.
Ahora vamos a quitar uno de los carritos....queremos que nos compren pero mejor no ser pesados.
En la misma sección que en el caso anterior vamos a comentar las líneas que referencian el bloque del
Carrito, por lo que la sección quedaría así:
<reference name="right">
<block type="customer/account_navigation"
name="customer_account_navigation" before="-"
template="customer/account/navigation.phtml">
<action method="addLink" translate="label"
module="customer"><name>account</name><path>customer/account/</path><label>Ac
count Dashboard</label></action>
<action method="addLink" translate="label"
module="customer"><name>account_edit</name><path>customer/account/edit/</path
><label>Account Information</label></action>
<action method="addLink" translate="label"
module="customer"><name>address_book</name><path>customer/address/</path><lab
el>Address Book</label></action>
</block>
<!--<block type="checkout/cart_sidebar" name="cart_sidebar"
template="checkout/cart/sidebar.phtml">
<action
method="addItemRender"><type>simple</type><block>checkout/cart_item_renderer<
/block><template>checkout/cart/sidebar/default.phtml</template></action>
<action
method="addItemRender"><type>grouped</type><block>checkout/cart_item_renderer
_grouped</block><template>checkout/cart/sidebar/default.phtml</template></act
ion>
<action
method="addItemRender"><type>configurable</type><block>checkout/cart_item_ren
derer_configurable</block><template>checkout/cart/sidebar/default.phtml</temp
late></action>
</block>
-->

Como se ve hemos comentado el bloque al completo, y así eliminamos uno de los carritos de compra.
Más cosas, ahora queremos que debajo del carrito nos aparezca el bloque de productos vistos
recientemente,
Para eso en la misma sección debemos añadir el bloque de productos vistos recientemente y decirle que
debe ir después del carrito de compra. Pues nada incluimos la siguiente línea:
<block type="reports/product_viewed" before="right.permanent.callout"
name="left.reports.product.viewed" template="reports/product_viewed.phtml" />

¿Dónde?. Pues yo la he puesto tal que así:


<!--<block type="checkout/cart_sidebar" name="cart_sidebar"
template="checkout/cart/sidebar.phtml">
<action
method="addItemRender"><type>simple</type><block>checkout/cart_item_renderer<
/block><template>checkout/cart/sidebar/default.phtml</template></action>
<action
method="addItemRender"><type>grouped</type><block>checkout/cart_item_renderer
_grouped</block><template>checkout/cart/sidebar/default.phtml</template></act
ion>
<action
method="addItemRender"><type>configurable</type><block>checkout/cart_item_ren
derer_configurable</block><template>checkout/cart/sidebar/default.phtml</temp
late></action>
</block>
-->
<!--<block type="catalog/product_compare_sidebar"
name="catalog.compare.sidebar"
template="catalog/product/compare/sidebar.phtml"/>-->
<block type="sales/reorder_sidebar" name="sale.reorder.sidebar"
as="reorder" template="sales/reorder/sidebar.phtml"/>

A que molan los layout...parecen complejos pero cuando le coges el rollo facilitan mucho las cosas.

Traduciendo “There are X items in your cart” de carrito de


compra de la columna
Esto tiene mucha guasa. Lo primero referenciar el enlace, que me orientó en algo pero que no me lo resolvió
puesto que me da que el que escribió la posible solución se expresó mal.
http://www.magentocommerce.com/boards/viewthread/177338/#t231660
Bien, lo que hice fue comparar mi archivo Mage_Checkout.csv (en la ruta: /app/locale/es_ES), con el de otra
traducción y vi el problema.
En el archivo referenciado encuentras las siguientes líneas:
"There are <a href=""%s""><strong>%s items</strong></a> in your cart.","Hay <a
href=""%s""><strong>%s artÃculos</strong></a> en su carrito."
"There is <a href=""%s""><strong>1 item</strong></a> in your cart.","Hay <a
href=""%s""><strong>1 artÃculo</strong></a> en su carrito."

Bien pues el problema reside en las etiquetas “strong”, si las quitamos el texto se traduce perfectamente, y
además el enlace aparece en negrita igualmente. Las líneas quedarían así:
"There are <a href=""%s"">%s items</a> in your cart.","Hay <a href=""%s"">%s artÃ-
culos</a> en su cesta."
"There is <a href=""%s"">1 item</a> in your cart.","Hay <a href=""%s"">1 artÃculo</a>
en su cesta."

Y listo.

Implementando el módulo de pago Servired


El módulo de pago de Servired es el más extendido, quizás porque es gratuito, es fiable y además se integra
con los TPV de muchos bancos.
El módulo se puede instalar a través de Magento Connect, y lo podéis encontrar en este enlace:
http://www.magentocommerce.com/magento-connect/defcon2/extension/464/metodo-de-pago-servired
Además del sitio oficial de Magento, existen otro foro en castellano que parece que se mueve más que el
oficial (cosa que no es difícil). El otro foro esta en el siguiente enlace:
http://foros.mgnt.es/showthread.php?332-Metodo-de-pago-Servired-para-Magento
El caso es que te dice que el módulo no es compatible con la versión 1.4, pero bicheando en los foros al final
se encuentra que si. Para ello hay que hacer una pequeña modificación en el fichero
/app/code/local/Mage/Servired/Model/Standard.php, consistente en moficar la siguiente línea:
$currency = $this->convertToServiredCurrency($order->getOrderCurrency());

Por:
$currency = $this->convertToServiredCurrency($order->getOrderCurrencyCode());

La información anterior la encontráis en el siguiente enlace:


http://www.magentocommerce.com/boards/viewthread/77950/
Una vez hecha esta modificación es el momento de entrar en el Panel de Administración – Métodos de Pago
– Servired, y cumplimentar los datos con los que nos proporciona la entidad con la que hayamos contratado.
Este paso es sencillo, pero tres apuntes. El primero es que en Nuevo estado del pedido debemos poner
Procesando. El segundo es que en Método para la firma hay que poner (a no ser que el banco nos diga lo
contrario) Completo ampliado. Y el tercero es que es conveniente que en Estado de la Ventana
seleccionemos Full Screen – Same Windows (2), por aquello del bloqueo de los pop up´s.
Bien hecho esto ya estamos en condiciones de probar el módulo. Cuando yo lo probé me encontré que me
lanzaba el siguiente error:
Invalid entity supplied: Mage_Sales_Model_Mysql4_Order_Address Object ...y un
chorizaco de código.

Después de algunas horas de desesperación encontré algo en un foro:


http://www.magentocommerce.com/boards/viewthread/200324/P0/
Que venía a decir que el problema era el paquete de actualización de la versión 1.4 a la 1.4.1, y sobre la
página 3 de este post empiezas a encontrar gente que dice algo así como “a mi me funcionó”...y los
encuentras a mogollón, luego habrá que probar.
El problema en sí es que los señores de Varien (yo creo que a posta) mandan el paquete de actualización de
forma incorrecta, de tal modo que en el paquete van archivos antiguos. La solución, descargarse el paquete
completo de instalación de la versión 1.4.1, extraerlo y machacar (no sin antes hacer copia de seguridad) la
carpeta core/Mage/Sales/Model/Mysql4/Order/ to local/Mage/Sales/Model/Mysql4/Order/ .
Y listo.
Tenemos un segundo problema. De esta forma el módulo no actualiza los pedidos ni para el cliente ni para el
Panel de Administración, de tal forma que el cliente no ve un historial de los pedidos, y el administrador no
puede cambiar el estado de los mismos.
Encontré dos posible soluciones. Una parte de realizar dos modificaciones, y la otra de sustituiir un fichero
entero. Con ambas me ha funcionado, aunque la primera ha sido finalmente más fiable.
Solución 1: Del Enlace: http://onestic.com/pasarela-de-pago-servired-para-magento-bug/
Esta es la solución que yo he implementado. En este caso lo que hacemos es sustituir varias líneas en el
fichero StandardController.php del módulo de Servired que está en la ruta:
/app/code/local/Mage/Servired/controllers.
He de decir que yo he hecho una interpretación de lo que el enlace mencionado comenta, porque como
veréis no indica exactamente cuáles son la líneas a sustituir. Y lo he hecho mediante pruebas de ensayo y
error, hasta que me ha funcionado. Así que lo que veréis a continuación es mi interpretación de las
modificaciones.
Buscamos la función "public function successAction() " , mediante una búsqueda de este texto. Al principio de
la función comentaremos las tres primeras líneas, ahora copiamos la dos primeras y las pegamos pero
intercambiamos su orden. Con lo que nos queda tal que así:
public function successAction() {
$orderState = Mage_Sales_Model_Order::STATE_PROCESSING;
$orderStatus = Mage::getModel('servired/standard')->getConfigData('order_status');
//$orderStatus = Mage::getModel('servired/standard')-
>getConfigData('order_status');
//$orderStatus = Mage_Sales_Model_Order::STATE_PROCESSING;
//$comment=null;

Un detalle de mucho interés. Resulta que la línea comment=null la comenté en modo pruebas y funcionó el
módulo. Cuando pasé al modo REAL el módulo no funcionaba y siempre me daba error de Número de
Pedido Repetido, la descomenté y el módulo salió andando.
Ahora no vamos al final de la función mencionada, justo antes de $order->save(); y buscamos la línea (que
está justo antes de order->save), y delante de ella pegamos el código que se muestra a continuación,
quedando el final de la función como se ve:
if (!$orderStatus) {
$orderStatus = $order->getConfig()->getStateDefaultStatus($orderState);
}
$order->setState($orderState, $orderStatus,$comment,true);
$order->save();

Solución 2: Del enlace: http://foros.mgnt.es/showthread.php?332-Metodo-de-pago-Servired-para-


Magento/page30&highlight=magento+1.4+servired
Consiste en sustituir el fichero StandardController.php del módulo por el que deja el usuario mac75a. El
fichero se encuentra en: /app/code/local/Mage/Servired/controllers.
Si bien esta solución tiene el visto bueno del creador del módulo (defcon2), también es cierto que el que la
crea pide que la gente la pruebe...luego...no está muy probada que digamos.
En esta solución si es necesario que en el TPV de LA Caixa (la interfaz web que nos facillita) se
cumplimenten los datos de URLOK y URLKO, porque de lo contrario cuando la operación se realiza, bien o
mal, te manda a la página de página no encontrada.
La URL de OK es:
http://www.midominio.com/checkout/onepage/success/
Aunque en un post he visto que esta dirección se escribe con una sola “c” en success.
La URL de KO es:
http://www.mi_temadetarifa.es/checkout/cart/
A mi no me funciona del todo correctamente.

Quitar el Callout del “perrito”


Vamos al fichero /app/design/frontend/default/mitema/layout/catalog.xml, y comentamos la siguientes líneas,
que se encuentran dentro de la sección “Default layout, loads most of the pages”
<!--
<block type="core/template" name="left.permanent.callout"
template="callouts/left_col.phtml">
<action
method="setImgSrc"><src>images/media/col_left_callout.jpg</src></action>
<action method="setImgAlt" translate="alt"
module="catalog"><alt>Servicio Tecnico</alt></action>
<action method="setLinkUrl"><url>customer-
service</url></action>
</block>
-->

Incluir un texto en el formulario de Búsqueda Avanzada


El formulario de búsqueda avanzada de Magento es una magnífica herramienta para que el cliente pueda
localizar el producto o productos deseados, puesto que combina los atributos habituales (nombre, precio,
etc.) con aquellos que al crearlos hayamos decidido que se usen para las búsquedas.
Además Magento de forma automática te muestra los posibles valores existentes cuando el atributo puede
mostrar varios, ya sea mediante listas desplegables o cuadros de selección múltiple. Pero de lo que no avisa
Magento es de que esos cuadros de selección múltiples pueden usarse realizando varias selecciones de
valores.
Mi intención es guiar el posible cliente para que pueda ver un listado de resultados cuando le interesa
localizar un determinado producto por ejemplo en distintos formatos, siempre y cuando el atributo formato se
muestre en la búsqueda con un cuadro de selección múltiple. ¿Cómo hacer esto?, pues incluyendo un aviso,
un texto, que indique que puede usar la tecla Control. Así el texto que he incluido en la búsqueda avanzada
es “Utilice la tecla Ctrl para selecciones múltiples”.
De momento no se como hacer que el texto sea traducible, y como ya he comentado anteriormente, en la
versión 1.4. parece que no es tan sencillo como en versiones anteriores.
Lo primero que vamos a hacer es incluir el texto en el formulario de búsqueda, para ello debemos ir a la
plantilla del mismo que está en app/design/frontend/default/mitema/template/catalogsearch/advanced y
editamos el archivo form.phtml
Podemos incluir el texto al principio del formulario o bien justo cuando comienzan los campos de selección
múltiple. Yo he optado por esto segunda, así que en el fichero se incluye la siguiente línea con etiquetas
spam y resaltada en negrita, que se muestra posicionada en el lugar que corresponde:
<div class="input-range">
<input name="<?php echo $_code ?>[from]" value="<?php
echo $this->htmlEscape($this->getAttributeValue($_attribute, 'from')) ?>"
id="<?php echo $_code ?>" title="<?php echo $this->htmlEscape($this-
>getAttributeLabel($_attribute)) ?>" class="input-text validate-number"
type="text" />
<span class="separator">-</span>
<input name="<?php echo $_code ?>[to]" value="<?php
echo $this->htmlEscape($this->getAttributeValue($_attribute, 'to')) ?>"
id="<?php echo $_code ?>_to" title="<?php echo $this->htmlEscape($this-
>getAttributeLabel($_attribute)) ?>" class="input-text validate-number"
type="text" />
<small>(<?php echo $this->getCurrency($_attribute); ?
>)</small>
</div>
<div><spam class="notice-msg-propio">Utilice la tecla Ctrl para selecciones
multiples.</spam></div>
<?php break;
case 'select': ?>

El estilo que he aplicado al texto es una copia del estilo notice-msg, y lo he llamado notice-msg-propio, al
objeto de ajustarlo a esta plantilla y no modificar el original con lo que me podría encontrar con sorpresas
desagradables.
Ahora en la hoja de estilos crearemos este estilo, y hay que hacerlo en dos líneas, porque existen dos líneas
que lo referencian. Lo que hacemos es copiar esas dos líneas y duplicarlas, cambiarles el nombre y luego
ajustar los valores a nuestra conveniencia. A continuación se muestran esta líneas en negrita y en la posición
en que yo las he puesto:
.notice-msg { border-style:solid !important; border-width:1px !important;
background-position:10px 9px !important; background-repeat:no-repeat !
important; min-height:24px !important; padding:8px 8px 8px 32px !important;
font-size:11px !important; font-weight:bold !important; }
.notice-msg-propio { border-style:solid !important; border-width:1px !important;
background-position:5px 5px !important; background-repeat:no-repeat !important; min-
height:17px !important; padding:8px 8px 3px 24px !important; font-size:11px !
important; font-weight:bold !important; margin:10px 0px 0px 150px !important;
float:left !important; }
.error-msg { border-color:#f16048; background-color:#faebe7; background-
image:url(../images/i_msg-error.gif); color:#df280a; }
.success-msg { border-color:#446423; background-color:#eff5ea; background-
image:url(../images/i_msg-success.gif); color:#3d6611; }
.note-msg,
.notice-msg { border-color:#fcd344; background-color:#fafaec; background-
image:url(../images/i_msg-note.gif); color:#3d6611; }
.notice-msg-propio { border-color:#fcd344; background-color:#fafaec;
background-image:url(../images/i_msg-note.gif); color:#3d6611; }

Borrando y Reiniciando Pedidos, Facturas, etc


Toda vez que hemos realizado las pruebas de la pasarela de pago y nos han pasado a modo real, toca
resetear los contadores y borrar los pedidos de purebas.
La información la obtengo el enlace: http://www.magentocommerce.com/boards/viewthread/1680/P375/
Este post tiene un montón de páginas pero este enlace os lleva a la página dónde encontré la solución. El
script lo aporta el nick: Viktor F y hace referencia a otro enlace, que me da que es el original:
http://inchoo.net/ecommerce/magento/delete-test-orders-in-magento/comment-page-2/#comment-8363
Simplemente creamos un archivo, o script SQL, al que yo he llamado borra_ordenes.sql con el siguiente
contenido:
– Resetea el Test de datos de Magento
SET FOREIGN_KEY_CHECKS=0;
– Resetea las consultas de búsqueda del Panel de Administración
TRUNCATE `catalogsearch_query`;
ALTER TABLE `catalogsearch_query` AUTO_INCREMENT=1;
– Reseta la información de Pedidos de Ventas
TRUNCATE `sales_flat_creditmemo`;
TRUNCATE `sales_flat_creditmemo_comment`;
TRUNCATE `sales_flat_creditmemo_grid`;
TRUNCATE `sales_flat_creditmemo_item`;
TRUNCATE `sales_flat_invoice`;
TRUNCATE `sales_flat_invoice_comment`;
TRUNCATE `sales_flat_invoice_grid`;
TRUNCATE `sales_flat_invoice_item`;
TRUNCATE `sales_flat_order`;
TRUNCATE `sales_flat_order_address`;
TRUNCATE `sales_flat_order_grid`;
TRUNCATE `sales_flat_order_item`;
TRUNCATE `sales_flat_order_payment`;
TRUNCATE `sales_flat_order_status_history`;
TRUNCATE `sales_flat_quote`;
TRUNCATE `sales_flat_quote_address`;
TRUNCATE `sales_flat_quote_address_item`;
TRUNCATE `sales_flat_quote_item`;
TRUNCATE `sales_flat_quote_item_option`;
TRUNCATE `sales_flat_quote_payment`;
TRUNCATE `sales_flat_quote_shipping_rate`;
TRUNCATE `sales_flat_shipment`;
TRUNCATE `sales_flat_shipment_comment`;
TRUNCATE `sales_flat_shipment_grid`;
TRUNCATE `sales_flat_shipment_item`;
TRUNCATE `sales_flat_shipment_track`;
TRUNCATE `sales_invoiced_aggregated`;
TRUNCATE `sales_invoiced_aggregated_order`;
TRUNCATE `sales_order_aggregated_created`;
TRUNCATE `sendfriend_log`;
TRUNCATE `tag`;
TRUNCATE `tag_relation`;
TRUNCATE `tag_summary`;
TRUNCATE `wishlist`;
TRUNCATE `log_quote`;
TRUNCATE `report_event`;
ALTER TABLE `sales_flat_creditmemo` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_creditmemo_comment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_creditmemo_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_creditmemo_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice_comment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_address` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_payment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_status_history` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_address` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_address_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_item_option` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_payment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_shipping_rate` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_comment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_track` AUTO_INCREMENT=1;
ALTER TABLE `sales_invoiced_aggregated` AUTO_INCREMENT=1;
ALTER TABLE `sales_invoiced_aggregated_order` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_aggregated_created` AUTO_INCREMENT=1;
ALTER TABLE `sendfriend_log` AUTO_INCREMENT=1;
ALTER TABLE `tag` AUTO_INCREMENT=1;
ALTER TABLE `tag_relation` AUTO_INCREMENT=1;
ALTER TABLE `tag_summary` AUTO_INCREMENT=1;
ALTER TABLE `wishlist` AUTO_INCREMENT=1;
ALTER TABLE `log_quote` AUTO_INCREMENT=1;
ALTER TABLE `report_event` AUTO_INCREMENT=1;
SET FOREIGN_KEY_CHECKS=1;

Nota: Las líneas en castellano debemos borrarlas si no, nos dará error de sintáxis. Las líneas están
simplemente para indicar que hace cada bloque de código.
Guardamos este fichero y desde la consola ejecutamos lo siguiente:
mysql -u nombre_usuario -p nombre_base_de_datos < borra_ordenes.sql

Cuando vuelvas a entrar en tu cuenta de cliente o como administrador verás que no hay pedidos, y en el
panel de administración los importes están a cero.

Hacer convivir el Envío Gratis con la Tarifa Plana de envío


Si dispones de envío gratuitos para un importe determinado y una tarifa plana para envío por debajo de ese
importe, encontramos que Magento nos presenta los dos métodos de envío cuando ambos son aplicables. Es
decir, cuando el importe supera el que hemos marcado para envíos gratuitos.
La verdad es que esto es un poco absurdo y puede llevar a confusión. Por lo que es necesario que cuando el
importe supere el marcado para los envíos gratuitos, no nos aparezca la opción de la tarifa plana.
En este post nos dan la solución: http://www.magentocommerce.com/boards/viewthread/53031/
A continuación la explico.
En el Panel de Administración en Configuración – Ventas – Métodos de Envío, tenemos que hacer lo
siguiente:
1. El orden que pongamos para Envíos Gratuitos debe ser siempre inferior (es decir que aparezca
primero) que para Tarifa Plana.
2. El título de los Envíos gratis los ponemos como Transporte Gratis. Cuando veas el código verás el
porqué, y también verás como puedes cambiar esto.
3. El título de la Tarifa Plana la ponemos como Tarifa Plana. Del mismo modo que en el caso anterior
podrás ver el porqué en el código, y si quieres podrás cambiarlo.
A continuación de guardar estos cambios editamos el archivo:
/app/design/frontend/default/mi_tema/template/checkout/onepage/shipping_method/available.phtml
Buscamos la siguiente línea de código:
<dl class="sp-methods">

Y justo debajo añadimos una línea, quedando tal que así:


<dl class="sp-methods">
<?php /* Agregamos 1 linea aqui */ ?>
<?php $freeshipping_available_flag=0; ?>

Ahora buscamos foreach ($_shippingRateGroups as $code => $_rates): ?> que estará justo debajo
de lo que acabamos de añadir y que si estamos en la versión 1.4 de Magento la línea aparece tal que así:
<?php $_sole = count($_shippingRateGroups) == 1; foreach
($_shippingRateGroups as $code => $_rates): ?>

Bien, pues justo debajo de esto añadimos dos líneas más quedando tal que así:
<?php $_sole = count($_shippingRateGroups) == 1; foreach
($_shippingRateGroups as $code => $_rates): ?>
<?php /* Added 2 lines here */ ?>
<?php if($this->getCarrierName($code)=='Transporte Gratis')
$freeshipping_available_flag=1;?>
<?php if(($this->getCarrierName($code)=='Tarifa Plana') and
($freeshipping_available_flag)) continue; ?>
<dt><?php echo $this->getCarrierName($code) ?></dt>

Ahora cuando el pedido supere el importe marcado para el envío gratuito sólo nos aparece este método y no
ambos.
En este mismo post dice que cambiando determinada línea el botón de chequeo del método de envío nos
aparecerá marcado, pero a mi no me ha funcionado. Este método consiste en sustituir la línea:
<input name="shipping_method" type="radio" value="<?php echo $_rate-
>getCode() ?>" id="s_method_<?php echo $_rate->getCode() ?>"<?php if($_rate-
>getCode()===$this->getAddressShippingMethod()) echo ' checked="checked"' ?>
class="radio" />

Por:
<input name="shipping_method" type="radio" value="<?php echo $_rate-
>getCode() ?>" id="s_method_<?php echo $_rate->getCode() ?>"<?php if(($_rate-
>getCode()===$this->getAddressShippingMethod()) or ($_rate->getMethodTitle()
== 'Transporte Gratis')) echo ' checked="checked"'?> class="radio" />

Si alguien sabe dónde está el error o como hacerlo para que así sea, pues que contribuya.

Vous aimerez peut-être aussi