/ hybris

hybris Europe1PriceFactory

Hoy daremos un vistaso al componente que realiza la obtención de los precios en hybris, algunos de los errores más comunes y cómo sobreescribir algunas partes sin morir en el intento

introducción

El component Europe1PriceFactory es la clase que se encarga de consultar, filtrar e instanciar los precios y precios de descuento (DiscountRow) en hybris. Trabaja sobre la capa deprecada de Jalo (aunque en la realidad, esta capa lleva ya varios releases como depreciada, pero simplemente no se va) y la mayor parte de las veces es totalmente necesario modificarla

métodos más comunes

getBasePrice

Obtiene el precio base de un producto para un entry del carrito. Esto quieree decir que se llama justo después de haber agregado el producto al carrito ó en cualquier recálculo

Dicho componente realiza llamados a distintos mecanismos internos, los cuales resumiremos en los siguientes:

  • queryPriceRows4Price - Y sí, amigos, hybris es tan guarro que escribió 4 en lugar de la palabra For, en fin. Este método busca TODOS los precios relacionados al producto. Filtrando el grupo del usuario que está ejecutando el query, el canal de venta y el usuario (por si se hace asignaciones no por grupo de usuario, si no al usuario directamente)
  • filterPriceRows4Price - Como su nombre lo indica, filtra los precios obtenidos, estos filtros son sobre los objetos Jalo que arrojó el primer query. Lógica aplicada es sobre: busca precios válidos para la fecha indicada (en función de la fecha de creación de la orden), moneda (currency)

problemas comunes

Cuando las fechas de los precios cambian demasiado, y no se encuentra alguno que tenga un rango de validez dentro de la fecha de la orden (carrito), este podría indicar que no encontró un precio válido para dicha orden, aunque sí existan precios válidos para el sitio, esto es, por ejemplo:

Fecha de la orden: 4 de Abril, 2019
Fecha de los precios (inicialmente): 1 de Abril 2019 - 10 Abril, 2019

Después, el usuario deja su carrito vivo, y regresa después del día 10 de Abril, 2019. Imaginemos que también se actualizaron los rangos de las fechas a 5 de Abril, 2019 - Fecha irrelevante

El método de filterPriceRows4Price lanzará una excepción, ya que los rangos de fecha del precio (5 de Abril, 2019 - Fecha irrelevante) no contempla la fecha de la orden (4 de Abril, 2019)

En mi experiencia, el cliente contempla este caso como incorrecto (depende realmente del ecommerce y sus reglas), para solucionarlo, sin "alterar" la metadata de tus órdenes, podrías:

Sobreescribir la clase FindPricingWithCurrentPriceFactoryStrategy#findBasePrice, donde estableceremos order.setDate(getTimeService.getCurrentTime()) para la orden, esto será previo a la consulta de findBasePrice, dicho cambio tendrá que estar dentro de una cláusula try / catch / finally para asegurarnos de que en el finally siempre reestablezcamos la fecha previa, por ejemplo:

public class DefaultNopalFindPricingWithCurrenPriceStrategy extends FindPricingWithCurrentPriceFactoryStrategy
{
    @Override
    public PriceValue findBasePrice(final AbstractOrderEntryModel oe) throws CalculationExcepetion
    {
        PriceValue price = null;
        final AbstractOrderModel order = oe.getOrdeer();
        final Date previousDate = order.getDate();
        
        try
        {
            // establecer una fecha actual para la validez de los precios
            order.setDate(getTimeService().currentTime());
            
            price = super.findBasePrice(eo);
        }
        finally
        {
            order.setDate(previousDate);
            getModelService().save(order);
        }
        
        return price;
    }
}

getDiscountValues

Obtiene los DiscountRows disponibles para un AbstractOrderEntry, una vez más, esto quiere decir que se ejecuta durante el recálculo, y después de haber realizado la alteración del addToCart

La lógica general es muy similar a la obtención de precios:

  • queryDiscounts4Price - Obtiene todos los descuentos eexistentes para un usuario ó grupo de eusuario
  • filterDiscountRows4Price - Realiza el filtro de la fecha

Aquí no encontramos errores genereados en caso de que no se encuentre algún elemento para el producto, ya que en realidad, lo mínimo necesario para la venta es el precio (y el inventario, pero en este ejemplo nos delimitamos a precios)

sobreescribir Europe1PriceFactory

Es posible sobreescribir todos los componentes, sin embargo, en este caso necesitamos ser más cuidadosos con la definición de nuestro elemento:

El componente original no cuenta con una definición de alias, por lo que no podemos apuntar un parent a un defaultPriceeFactory ó basePriceFactory:

    <bean id="europe1.manager" class="de.hybris.platform.catalog.jalo.CatalogAwareEurope1PriceFactory"
          init-method="init" destroy-method="destroy">
        <property name="retrieveChannelStrategy" ref="retrieveChannelStrategy"/>
    </bean>

Habiendo dicho eso, será necesario volver a definir el componente desde cero, esto es, inyectar manualmente las dependencias y ajustar un alias al id del componente original:

    <alias name="nopalEuropePriceFactory" alias="europe1.manager"/>
    <bean id="nopalEuropePriceFactory" class="mx.nopal.core.prices.impl.DefaultNopalEurope1PriceFactory"
          init-method="init" destroy-method="destroy">
        <property name="retrieveChannelStrategy" ref="retrieveChannelStrategy"/>
    </bean>

Como se puede observar, hay que indicarle manualmente los métodos init y destroy del componente para que el factory inicialice correctamente

Nota: He aquí la importacia de tener un id como base para la inyección y posteriormente un alias agnóstico a la implementación, para poder reutilizar las inyecciones del elemento parent. También, no es la única implementación de este tipo que encontrarás en hybris... Así que sólo da un fuerte suspiro

conclusión

El componente Europe1PriceFactory realiza los accesos a más bajo nivel de los elementos relacionados a precios: tax, price, discount. Este ejecuta algunos filtros y hace uso de excepciones a manera de control de flujo de ejecución para casos inválidos (lo cual, depende de tus gustos, es algo bueno o malo). Sin embargo, al tener que vivir dentro de la capa de Jalo, es un tanto complicado sobreescribir el comportamiento, sin mencionar lo complejo que se vuelve hacer un debug de este componente, es decir, sólo miren a estas joyas de la capa de Jalo:

Captura-de-Pantalla-2019-05-03-a-la-s--12.14.26

Captura-de-Pantalla-2019-05-03-a-la-s--12.15.55

Captura-de-Pantalla-2019-05-03-a-la-s--12.16.27

Todo esto, sin mencionar que la clase cuenta con casi 2500 líneas

Al final del día, no importa qué componente sea, si está en Jalo, seguramente terminarás tu tarea así:

finger_animated