Magento 1.9: Extensión Wishlist admin email, traducir a español y arreglar precios

Puede que nos interese conocer qué productos han añadido nuestros clientes a su wishlist. Para ello, existe una extensión (gratuita) que funciona con Magento 1.9, llamada Wishlist Admin Email.

Esta extensión funciona muy bien, pero tiene dos pegas:
1) Cuando envía el email de la wishlist, el precio que muestra en los productos es el precio SIN IMPUESTOS. Para corregirlo y que muestre el precio con impuestos, debemos editar el fichero app/design/frontend/base/default/template/me/wlae/email/items.phtml y modificar el cálculo del precio.

Reemplazar:

<?php echo $coreHelper->formatPrice($_product->getFinalPrice()); ?>

Por

<!-- modifico para que salga el precio con impuestos -->
<!--<?php echo $coreHelper->formatPrice($_product->getFinalPrice()); ?>-->
<?php 
$_priceIncludingTax = Mage::helper('tax')->getPrice($_product, $_product->getFinalPrice());
echo $_priceIncludingTax;
?>

2) El email se envía en inglés. Aunque no es muy trascendente, puesto que solo el administrador recibe estos emails (y NO los reciben clientes) es interesante saber cómo traducir la plantilla.

Para añadir el fichero de traducciones, vamos a app/locale/es_ES y subimos el fichero con las traducciones (Me_Wlae.csv) con el siguiente contenido:

"Wishlist Admin Email","Wishlist Admin Email"
"Basic","Basico"
"Enable Extension","Habilitar extension"
"Enable Extension.","Deshabilitar extension."
"Yes","Si"
"No","No"
"Email Options","Opciones de email"
"Email Wishlist Items","Enviar items de wishlist"
"Send Only Newly Added","Enviar solo los nuevos"
"Send Entire Wishlist","Enviar wishlist completa"
"Please select to send only the recently added item, or the whole wishlist. In the second option the newly added item will be marked.","Por favor seleccione si enviar solo los items nuevos o la wishlist completa. En la segunda opcion se marcaran los productos nuevos."
"Send Emails To","Enviar emails a"
"Please enter the email address where notification will be sent.","Introduzca la direccion de email a la que llegaran las notificaciones."
"Send BCC Emails To","Enviar BCC a"
"Please enter the bcc copy email address where notification will be also sent.","Por favor introduce la direccion de email a la que se enviara copia de la notificacion."
"Email Sender","Email Sender"
"Please select the email sender from store email addresses.","Por favor, seleccione un sender de la lista de emails."
"Email Template","Plantilla Email"
"Please select the custom email template or use the default.","Por favor seleccione la plantilla custom de email o utilice la defecto."
"Email Items Setting","Ajustes basicos de email"
"Email Basic Setting","Ajuste basico email"

Asi nos quedaría, ya traducido, el panel de Admin del módulo (System > Config > Admin Wishlist Email)

magevolve-wishlist admin email traducido

Además hay que modificar el fichero app/locale/es_ES/template/email/me_wlae_notification.html y ponerle éste contenido:

<!--@subject {{var store.getFrontendName()}}: Wishlist Admin Notification @-->
<!--@vars
{"store url=\"\"":"Store Url",
"var logo_url":"Email Logo Image Url",
"var logo_alt":"Email Logo Image Alt",
"var customer_name":"Customer Name",
"var customer_email":"Customer Email",
"var items":"Items",
"var store.getFrontendName()":"Store Name"}
@-->
<!--@styles
body,td { color:#2f2f2f; font:11px/1.35em Verdana, Arial, Helvetica, sans-serif; }
@-->
 
<body style="background:#F6F6F6; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12px; margin:0; padding:0;">
<div style="background:#F6F6F6; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12px; margin:0; padding:0;">
    <table cellspacing="0" cellpadding="0" border="0" height="100%" width="100%">
        <tr>
            <td align="center" valign="top" style="padding:20px 0 20px 0">
                <!-- [ header starts here] -->
                <table bgcolor="#FFFFFF" cellspacing="0" cellpadding="10" border="0" width="650" style="border:1px solid #E0E0E0;">
                    <tr>
                        <td valign="top"><a href="{{store url=""}}"><img src="{{var logo_url}}" alt="{{var logo_alt}}" style="margin-bottom:10px;" border="0"/></a></td>
                    </tr>
                    <!-- [ middle starts here] -->
                    <tr>
                        <td valign="top">
                            <h1 style="font-size:22px; font-weight:normal; line-height:22px; margin:0 0 11px 0;">Notificación de wishlist</h1>
                            <p style="font-size:12px; line-height:16px; margin:0 0 16px 0;">Nuevo producto en wishlist...</p>
                            <p style="font-size:12px; line-height:16px; margin:0 0 16px 0;">
                                <strong>Detalles:</strong><br /><br />
                                Nombre cliente: {{var customer_name}}<br />
                                Email cliente: {{var customer_email}}
                            </p>
                            {{var items}}
                        </td>
                    </tr>
                    <tr>
                        <td bgcolor="#EAEAEA" align="center" style="background:#EAEAEA; text-align:center;"><center><p style="font-size:12px; margin:0;"><strong>{{var store.getFrontendName()}}</strong></p></center></td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</div>
</body>

Después vaciamos la cache y ¡listo!

Asi quedaría el email que recibe el admin…
magevolve admin wishlist email including taxes

[SOLVED] Magento 1.9 BUG FIX Cron email alerts sent in wrong language

I found a Magento bug which makes cron (price, stock) alerts emails being in the wrong language.

Issue

I have configured price alerts for a client (which originally registered into my shop with spanish language).

The user receives the email, but it is in english.

For instance, the text: “You are receiving this notification because you subscribed to receive alerts when the prices for the following products changed:” (in ./app/design/frontend/base/default/template/email/productalert/price.phtml) is not being translated to spanish.

I have checked and the translation is present in ./app/locale/es_ES/Mage_ProductAlert.csv: “You are receiving this notification because you subscribed to receive alerts when the prices for the following products changed:”,”Usted está recibiendo esta notificación porque está suscrito para recibir alertas cuando los precios de los siguientes productos cambien:”

I am using a custom theme.

I have also tried to add that translation to my theme: app/design/frontend/mytheme/default/locale/es_ES/translate.csv

I have flushed translations cache and deleted Magento cache. Still not being translated.

Fix

What I did to fix the issue:

Edit app/code/core/Mage/ProductAlert/Model/Email.php

Replace this (line 255):

       $appEmulation = Mage::getSingleton('core/app_emulation');
       $initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($storeId);

With this:

        $appEmulation = Mage::getSingleton('core/app_emulation');
        $initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($storeId);
        //Dealing with uninitialized translator!
        Mage::app()->getTranslator()->init('frontend', true);

Flushed the cache and voila! Now magento is sending the email alerts in the right language 🙂

Magento 1.9: Alertas de reposición de stock y alertas de precio

Una de las funcionalidades que ofrece Magento es que el usuario pueda suscribirse a alertas en productos. Bien sean alertas de modificación de precio (“productalert/price”) o de reposición de stocks (“productalert/stock”).

Para activar dicha funcionalidad, hay que ir a Sistema > Configuración > Catálogo > Catálogo:

alertas magento precio y stock

Y los productos (de los productos configurables hablaremos más adelante) pasan a mostrar dicha alerta:
alertas_magento_stock_price-23

Para ello, el theme debe llamar a:

<?php echo $this->getChildHtml('alert_urls') ?>

Y la plantilla por defecto que se ejecuta es productalert/product/view.phtml:

<?php /* @var $this Mage_ProductAlert_Block_Product_View */?>
<h1>Hello</h1>
<p class="<?php echo $this->getHtmlClass() ?>">
    <a href="<?php echo $this->escapeHtml($this->getSignupUrl()) ?>" title="<?php echo $this->escapeHtml($this->__($this->getSignupLabel())); ?>"><?php echo $this->escapeHtml($this->__($this->getSignupLabel())); ?></a>
</p>

En layout/productalert.xml encontramos la función a la que se llama (preparePriceAlertData o prepareStockAlertData):

<layout version="0.1.0">
    <catalog_product_view>
        <reference name="content">
            <reference name="product.info">
                <reference name="alert.urls">
                    <block type="productalert/product_view" name="productalert.price" as="productalert_price" template="productalert/product/view.phtml">
                        <action method="preparePriceAlertData"/>
                        <action method="setHtmlClass"><value>alert-price link-price-alert</value></action>
                        <action method="setSignupLabel" translate="value"><value>Sign up for price alert</value></action>
                    </block>
                    <block type="productalert/product_view" name="productalert.stock" as="productalert_stock" template="productalert/product/view.phtml">
                        <action method="prepareStockAlertData"/>
                        <action method="setHtmlClass"><value>alert-stock link-stock-alert</value></action>
                        <action method="setSignupLabel" translate="value"><value>Sign up to get notified when this product is back in stock</value></action>
                    </block>
                </reference>
            </reference>
        </reference>
    </catalog_product_view>
</layout>

Además, desde cada producto (Catálogo > Administrar producto), se puede ver quién se ha suscrito a cada alerta, en la pestaña “Alertas de producto”:

magento alerts

Estas alertas se almacenan internamente en la tabla product_alert_* (una para precio, otra para stock).

Si queremos obtener un informe con sumario, podemos hacer una query a las tablas anteriores o, si queremos verlo de forma gráfica, podemos instalar la extensión Amasty – Product Alert Reports (gratuita) https://amasty.com/product-alerts-reports.html y en Informes > Alerts dispondremos de la información de alertas a modo de sumario.

Para que los correos de alerta salgan, es necesario tener configurado CRON (+info aqui y aqui).

Hasta aqui, todo bien. Ahora, algunas dudas habituales:

¿Qué sucede si el cliente no está registrado y por tanto no se dispone de su email?
Si el cliente no está registrado, por defecto Magento le pide que se identifique para poder usar las alertas. No muestra un input donde el cliente no registrado pueda introducir su email para suscribirse a la alerta…

¿Qué sucede con los productos configurables?
Imaginemos que vendemos camisetas en tallas S,M,L. El producto “camiseta roja” será un prod configurable y los productos simples tendrán la variante de la talla. Sin embargo, Magento por defecto NO muestra el aviso de “Sign up to get notified when product is back in stock” en los productos configurables, aunque alguno de los productos simples asociados no esté en stock.

¿Puede el cliente registrado acceder desde su panel a la lista de suscripciones de stock y precio?
No, por defecto no puede. El código para mostrar las alertas de cada cliente sería algo asi:

/* LIST STOCK ALERTS */
$customer_id = Mage::getSingleton('customer/session')->getCustomer()->getId();
$customer_stock_alerts = Mage::getModel('productalert/stock')
         ->getCollection()
         ->addFieldToFilter('customer_id', $customer_id);
<p>foreach ( $customer_stock_alerts as $alert )
{
 echo $alert->getProductId();
}
 
/* LIST PRICE ALERTS */
$customer_id = Mage::getSingleton('customer/session')->getCustomer()->getId();
$customer_stock_alerts = Mage::getModel('productalert/price')
         ->getCollection()
         ->addFieldToFilter('customer_id', $customer_id);
<p>foreach ( $customer_stock_alerts as $alert )
{
 echo $alert->getProductId();
}

¿Cómo solucionar estas cuestiones, si no queremos ponernos a programar? Podemos comprar e instalar el módulo Amasty – Out of stock notification, que da solución a estas cuestiones: https://amasty.com/out-of-stock-notification.html

+info:
https://stackoverflow.com/questions/11648920/magento-show-sign-up-to-get-notified-when-this-product-is-back-in-stock-link-f
http://magento.stackexchange.com/questions/10989/cant-see-alert-urls-block-template
http://stackoverflow.com/questions/10810960/show-out-of-stock-for-configurable-products-in-magento
http://magento.stackexchange.com/questions/470/configurable-product-inventory-stock-availability-status-doesnt-change-when
http://stackoverflow.com/questions/5290868/how-would-test-cron-with-magento
http://merch.docs.magento.com/ee/user_guide/content/catalog/inventory-product-alert-run-settings.html
http://www.megamagento.com/2013/11/magento-product-stock-back-alerts-out.html

Magento 1.9 – mostrar productos sin existencias

Imaginemos un producto configurable (“Camiseta”) con varios productos simples asociados, de diversas tallas (“Camiseta-M”, “Camiseta-XL”). Imaginemos que tenemos 5 unidades de Camiseta-M pero ninguna de Camiseta-L.

Por defecto, si tenemos marcada en Magento la opción de configuración de no mostrar productos sin stock, Magento solo mostrará en el desplegable de tallas las tallas para las que haya stock.

¿Cómo mostrar las tallas para las que no hay stock?

Hay dos posibles soluciones:

1) Por código

: crear un nuevo módulo y en el config.xml del módulo añadir 2 eventos dentro del tag :

    <events>
        <controller_action_layout_render_before_catalog_product_view>
            <observers>
                <[namespace]_[module]>
                    <class>[module]/observer</class>
                    <method>showOutOfStock</method>
                </[namespace]_[module]>
            </observers>
        </controller_action_layout_render_before_catalog_product_view>
        <controller_action_layout_render_before_checkout_cart_configure>
            <observers>
                <[namespace]_[module]>
                    <class>[module]/observer</class>
                    <method>showOutOfStock</method>
                </[namespace]_[module]>
            </observers>
        </controller_action_layout_render_before_checkout_cart_configure>
    </events>

A continuación crear un observer en app/code/local/[Namespace]/[Module]/Model/Observer.php

class [Namespace]_[Module]_Model_Observer {
    public function showOutOfStock($observer){
        Mage::helper('catalog/product')->setSkipSaleableCheck(true);
    }
}

2) Solución por extensión (la que he aplicado yo)

– Descargar e instalar la extensión EasyLifeSwitcher para Magento: https://github.com/tzyganu/Switcher (mirror)
– Configurarla (más info aqui) para que permita mostrar y seleccionar prods simples sin stock

easylife_switcher

– Editar js/easylife_switcher/product.js y reemplazar:

/**
     * rewrite fillSelect to transform elements to labels
     * @param $super
     * @param element
     */
    fillSelect: function($super, element){
        $super(element);
        //if (this.config.transform_dropdowns){
        var transformed = this.transformDropdown(element);
        if (!transformed && !this.getConfigValue(this.config, 'allow_no_stock_select', false)) {
            var attributeId = element.id.replace(/[a-z]*/, '');
            var options = this.getAttributeOptions(attributeId);
            for (var i in options) {
                if (options.hasOwnProperty(i)){
                    var optVal = options[i].id;
                    var inStock = this.isInStock(attributeId, optVal);
                    $(element).select('option').each (function(elem){
                        if ($(elem).value == optVal && !inStock) {
                            $(elem).disabled="disabled";
                        }
                    });
                }
            }
        }
    },

Por:

/**
     * rewrite fillSelect to transform elements to labels
     * @param $super
     * @param element
     */
    fillSelect: function($super, element){
        $super(element);
        //if (this.config.transform_dropdowns){
        var transformed = this.transformDropdown(element);
        if (!transformed && !this.getConfigValue(this.config, 'allow_no_stock_select', false)) {
            var attributeId = element.id.replace(/[a-z]*/, '');
            var options = this.getAttributeOptions(attributeId);
            for (var i in options) {
                if (options.hasOwnProperty(i)){
                    var optVal = options[i].id;
                    var inStock = this.isInStock(attributeId, optVal);
                    $(element).select('option').each (function(elem){
                        if ($(elem).value == optVal && !inStock) {
                            $(elem).disabled="disabled";
                            // este evento solo se dispara si allow_no_stock_select=0 (NO Permitir seleccionar productos sin existencias)
                            //alert("debug product.js");
                        }
                    });
                }
            }
        }
        // para añadir etiqueta "sin stock" - esto se ejecuta solo si allow_no_stock_select=1 (Permitir seleccionar productos sin existencias)
        if (!transformed && this.getConfigValue(this.config, 'allow_no_stock_select', false)) {
            var attributeId = element.id.replace(/[a-z]*/, '');
            var options = this.getAttributeOptions(attributeId);
            for (var i in options) {
                if (options.hasOwnProperty(i)){
                    var optVal = options[i].id;
                    var inStock = this.isInStock(attributeId, optVal);
                    $(element).select('option').each (function(elem){
                        if ($(elem).value == optVal && !inStock) {
                            //$(elem).label = "Sin stock";
                            $(elem).classList.add("sin-stock-actual");
                        }
                    });
                }
            }
        } // HASTA AQUI ACERTIUS NUEVO
    },

– Editar nuestro archivo de estilos y añadir las reglas:

 /* para mostrar en rojo los productos sin stock */
 .sin-stock-actual{ color: red; }
 .sin-stock-actual::after{content: " - ¡Existencias agotadas!"; }

De esta forma nuestros desplegables de tallas mostrarán todas las tallas:

easylife_switcher_custom_css