Promociones

En este tutorial vamos a agregar las promociones en tu diseño, ofreciendo la posibilidad de mostrar y aplicar promociones del tipo: 2x1, 3x1, % de descuento sobre un producto o a partir de una determinada cantidad de unidades.

Las promociones se muestran en:

  • El ítem en el listado de productos
  • El detalle de un producto
  • El carrito, antes del total.


HTML

1. En el theme Base usamos un solo snipplet para todos los labels o carteles en los productos (envío gratis, sin stock y porcentaje de descuento). Por lo que en este paso vamos a crear ese tpl con el nombre labels.tpl dentro de la carpeta snipplets.

El código del snipplet completo es el siguiente:

{% if product.compare_at_price > product.price %}
{% set price_discount_percentage = ((product.compare_at_price) - (product.price)) * 100 / (product.compare_at_price) %}
{% endif %}

{% if not product.has_stock or product.free_shipping or product.compare_at_price or product.promotional_offer %}
  <div class="labels">
    {% if not product.has_stock %}
      <div class="{% if product_detail %}js-stock-label {% endif %}label label-default">{{ "Sin stock" | translate }}</div>
    {% else %}
      {% if product.compare_at_price or product.promotional_offer %}
        <div class="{% if not product.promotional_offer and product %}js-offer-label{% endif %} label label-primary" {% if (not product.compare_at_price and not product.promotional_offer) or not product.display_price %}style="display:none;"{% endif %}>
          {% if product.promotional_offer.script.is_percentage_off %}
            {{ product.promotional_offer.parameters.percent * 100 }}% OFF
          {% elseif product.promotional_offer.script.is_discount_for_quantity %}
            <div>{{ product.promotional_offer.selected_threshold.discount_decimal_percentage * 100 }}% OFF</div>
            <div class="label-small p-right-quarter p-left-quarter">{{ "Comprando {1} o más" | translate(product.promotional_offer.selected_threshold.quantity) }}</div>
          {% elseif product.promotional_offer %}
            {% if store.country == 'BR' %}
              {{ "Leve {1} Pague {2}" | translate(product.promotional_offer.script.quantity_to_take, product.promotional_offer.script.quantity_to_pay) }}
            {% else %}
              {{ "Promo" | translate }} {{ product.promotional_offer.script.type }} 
            {% endif %}
          {% else %}
            <span {% if product_detail %}class="js-offer-percentage"{% endif %}>{{ price_discount_percentage |round }}</span>% OFF
          {% endif %}
        </div>
      {% endif %}
      {% if product.free_shipping %}
        <div class="label label-secondary">{{ "Envío gratis" | translate }}</div>
      {% endif %}
    {% endif %}
  </div>
{% endif %}

Pero si solo querés usar la parte de promociones, con el siguiente código ya vas poder mostrar las promociones en el listado y el detalle de los productos:

{% if product.compare_at_price or product.promotional_offer %}
  <div class="label label-primary" {% if (not product.compare_at_price and not product.promotional_offer) or not product.display_price %}style="display:none;"{% endif %}>
    {% if product.promotional_offer.script.is_percentage_off %}
      {{ product.promotional_offer.parameters.percent * 100 }}% OFF
    {% elseif product.promotional_offer.script.is_discount_for_quantity %}
      <div>{{ product.promotional_offer.selected_threshold.discount_decimal_percentage * 100 }}% OFF</div>
      <div class="label-small p-right-quarter p-left-quarter">{{ "Comprando {1} o más" | translate(product.promotional_offer.selected_threshold.quantity) }}</div>
    {% elseif product.promotional_offer %}
      {% if store.country == 'BR' %}
        {{ "Leve {1} Pague {2}" | translate(product.promotional_offer.script.quantity_to_take, product.promotional_offer.script.quantity_to_pay) }}
      {% else %}
        {{ "Promo" | translate }} {{ product.promotional_offer.script.type }} 
      {% endif %}
    {% endif %}
  </div>
{% endif %}

2. Luego tenemos que incluir el snipplet label.tpl tanto en el detalle del producto como en el item del listado. 

Para el item del listado lo hacemos en el snipplet item.tpl dentro de la carpeta snipplets/grid. Si en tu diseño no tenés estos archivos, entonces es posible que tengas que agregarlo en el snipplet single_product.tpl

{% include 'snipplets/labels.tpl' %}

Para el detalle del producto hacemos algo similar, solo que en el snipplet product-image.tpl dentro de la carpeta snipplets/product. De nuevo, en tu caso puede que tengas que aplicarlo directamente sobre el template product.tpl

{% include 'snipplets/labels.tpl' with {'product_detail': true} %}

3. Ahora necesitamos agregar el mensaje con el detalle de la promoción en la página de cada producto. En el caso del theme Base, lo ubicamos en el snipplet product-form.tpl dentro de la carpeta snipplets/product o directamente en el template product.tpl, dependiendo cuan actualizado esté el código de tu diseño. Lo importante es que esté cerca del precio para asociar el descuento con el precio.

El código para este mensaje es:

{# Promotional text #}


{% if product.promotional_offer and not product.promotional_offer.script.is_percentage_off and product.display_price %}
    <div class="js-product-promo-container text-center text-sm-left">
        {% if product.promotional_offer.script.is_discount_for_quantity %}
            {% for threshold in product.promotional_offer.parameters %}
                <h4 class="mb-2"><strong>{{ "¡{1}% OFF comprando {2} o más!" | translate(threshold.discount_decimal_percentage * 100, threshold.quantity) }}</strong></h4>
            {% endfor %}
        {% else %}
            <h4 class="mb-2"><strong>{{ "¡Llevá {1} y pagá {2}!" | translate(product.promotional_offer.script.quantity_to_take, product.promotional_offer.script.quantity_to_pay) }}</strong></h4> 
        {% endif %}
        {% if product.promotional_offer.scope_type == 'categories' %}
            <p>{{ "Válido para" | translate }} {{ "este producto y todos los de la categoría" | translate }}:  
            {% for scope_value in product.promotional_offer.scope_value_info %}
               {{ scope_value.name }}{% if not loop.last %}, {% else %}.{% endif %}
            {% endfor %}</br>{{ "Podés combinar esta promoción con otros productos de la misma categoría." | translate }}</p>
        {% elseif product.promotional_offer.scope_type == 'all'  %}
            <p>{{ "Vas a poder aprovechar esta promoción en cualquier producto de la tienda." | translate }}</p>
        {% endif %}  
    </div> 
{% endif %}

4. Por último solo queda agregar el mensaje dentro del carrito. En el theme Base tenemos un tpl llamado cart-totals.tpl, donde mostramos el subtotal, el calculador de envíos y el total. Vamos a agregar el código en este snipplet pero si en tu diseño no lo tenés, entonces agregalo en el snipplet cart-panel-ajax.tpl y el template cart.tpl. Lo importante es que esté debajo del subtotal.

{# Cart panel promos #}
<div class="js-total-promotions">
  <span class="js-promo-title" style="display:none;">{{ "Promo" | translate }}</span>
  <span class="js-promo-in" style="display:none;">{{ "en" | translate }}</span>
  <span class="js-promo-all" style="display:none;">{{ "todos los productos" | translate }}</span>
  <span class="js-promo-buying" style="display:none;"> {{ "comprando" | translate }}</span>
  <span class="js-promo-units-or-more" style="display:none;"> {{ "o más" | translate }}</span>
  {% for promotion in cart.promotional_discount.promotions_applied %}
    {% if(promotion.scope_value_id) %}
      {% set id = promotion.scope_value_id %}
    {% else %}
      {% set id = 'all' %}
    {% endif %}
      <span class="js-total-promotions-detail-row row" id="{{ id }}">
        <span class="col">
          {% if promotion.discount_script_type == "NAtX%off" %}
            {{ promotion.selected_threshold.discount_decimal_percentage * 100 }}% OFF
          {% else %}
            {{ "Promo" | translate }} {{ promotion.discount_script_type }} 
          {% endif %}


          {{ "en" | translate }} {% if id == 'all' %}{{ "todos los productos" | translate }}{% else %}{{ promotion.scope_value_name }}{% endif %}


          {% if promotion.discount_script_type == "NAtX%off" %}
            <span>{{ "Comprando {1} o más" | translate(promotion.selected_threshold.quantity) }}</span>
          {% endif %}
          :
        </span>
        <span class="col text-right">-{{ promotion.total_discount_amount_short }}</span>
      </span>
  {% endfor %}
</div>

CSS

Requisito:

Tener agregados en tu diseño las clases helpers. Podés seguir este este pequeño tutorial para hacerlo (simplemente es copiar y pegar algunas clases, no toma más de 1 minuto).

1. Agregamos el siguiente SASS de colores en style-colors.scss.tpl (o la hoja de tu diseño que tenga los colores y tipografías de la tienda). Recordá que las variables de colores y tipografías pueden variar respecto a tu diseño:

{# /* // Labels */ #}

.label {
  background: darken($main-background, 1%);
  &.label-primary{
    background: $main-foreground;
    color: $main-background;
  }
}

2. Si en tu diseño usas una hoja de estilos para CSS crítico, vamos a necesitar agregar el siguiente código dentro de la misma en el archivo static/style-critical.tpl , pero si no es el caso podés unificar el CSS de los pasos 2 y 3 en un solo archivo.

{# /* // Labels */ #}

.labels {
  position: absolute;
  top: 0;
  z-index: 9;
}

.label {
  margin-bottom: 10px;
  padding: 5px 10px; 
  font-size: 12px;
  text-align: left;
}

3. Agregar los estilos dentro del archivo static/style-async.tpl 

.cart-promotion-detail{
  float: left;
  width: 65%;
  text-align: left;
} 
.cart-promotion-number{
  position: absolute;
  right: 0;
  bottom: 0;
  width: 35%;
  float: right;
  margin: 0;
  text-align: right;
  font-weight: bold;
} 
.total-promotions-row{
  float: right;
  width: 100%;
  margin-bottom: 5px;
  position: relative;
  .cart-promotion-number{
    margin-left: 5px;
  }
}

Traducciones

En este paso agregamos los textos para las traducciones en el archivo config/translations.txt

--- --- Labels


es "Sin stock"
pt "Esgotado"
en "Out of stock"
es_mx "Agotado"


es "Envío gratis"
pt "Frete grátis"
en "Free shipping"
es_mx "Envío gratis"


es "Gratis"
pt "Grátis"
en "Free"
es_mx "Gratis"


es "Oferta"
pt "Oferta"
en "Sale"
es_mx "Rebaja"


es "Nuevo"
pt "Novo"
en "New"
es_mx "Nuevo"


es "Promo"
pt "Promoção"
en "Promo"
es_mx "Promo"


es "¡Llevá {1} y pagá {2}!"
pt "Leve {1} e pague {2}!"
en "Buy {1} and only pay for {2}"
es_mx "¡Lleva {1} y paga {2}!"


pt "Leve {1} Pague {2}"
es_mx "Lleva {1} y paga {2}"


es "Válido para"
pt "Válido para"
en "Available for"
es_mx "Válido para"


es "este producto y todos los de la categoría"
pt "este produto e todos da categoria"
en "this product and all of the products of category: "
es_mx "este producto y todos los de la categoría"


es "todos los productos"
pt "todos os produtos"
en "all products"
es_mx "todos los productos"


es "en"
pt "em"
en "on"
es_mx "en"


es "Vas a poder aprovechar esta promoción en cualquier producto de la tienda."
pt "Você pode aproveitar esta promoção em qualquer produto da loja."
en "You will be able to use this promotion on any product of the shop"
es_mx "Aprovecha esta promoción en cualquier producto del sitio."


es "Podés combinar esta promoción con otros productos de la misma categoría."
pt "Nesta promoção você pode combinar este produto com outros da mesma categoria."
en "You can combine this offer with other products of the same category"
es_mx "Combina esta promoción con otros productos de la misma categoría."


es "Comprando {1} o más"
pt "Comprando {1} ou mais"
en "Buying {1} or more"
es_mx "Comprando {1} o más"


es "¡{1}% OFF comprando {2} o más!"
pt "{1}% OFF comprando {2} ou mais!"
en "{1}% OFF buying {2} or more!"
es_mx "¡{1}% OFF comprando {2} o más!"


es "comprando"
pt "comprando"
en "buying"
es_mx "comprando"


es "o más"
pt "ou mais"
en "or more"
es_mx "o más"

Activación

Para usar esta funcionalidad, ahora solo tenés que activarla desde el Administrador nube desde la sección Descuentos > Promociones.