This website uses cookies to ensure you get the best experience. Learn More.
Cómo crear una regla de descuento para Liferay Commerce - DEV24 - (Parte 1)
Hola a todos, tal como prometí en Dev24, aquí tenéis el blog con el paso a paso de principio a fin. Aquí puedes aprender cómo crear una extensión de “Regla de Descuento” para Liferay Commerce, haciéndola además configurable.
Aquí tienes el enlace en caso de que no pudieras asistir en vivo al evento de Dev24 donde dimos una introducción: “Forget Amazon, help your users to buy with Alexa from Liferay Commerce (thanks to its headless APIs)
En este momento, las extensiones para Liferay Commerce extensions no están disponibles como plantillas de BLADE y por ello, explico toda la estructura de proyectos y andamiaje necesario.
Si entiendes toda la estructura que es necesaria, podrás aplicarlo para crear diferentes tipos de extensiones para Liferay Portal 7.X o Liferay Commerce.
Crearemos una regla de descuento basada en la edad del comprador. Vamos allá.
1. Con Blade CLI, podemos comenzar creando un Liferay Workspace, en caso de que no tengas uno ya para Liferay 7.3.
blade init -v 7.3 liferay-workspace-7-3
2. En tu “Liferay Workspace”, creamos un nuevo módulo de descuento:
blade create -t api -p com.liferay.commerce.discount.rule.by.age -c CommerceDiscountRuleByAge commerce-discount-rule-by-age
3. Ahora deberías tener una estructura de proyecto como la siguiente:
4. Abre el fichero gradle.properties con un editor de texto, descomenta y cambia el valor de la propiedad de “liferay.workspace.home.dir=bundle” a la ruta donde se encuentra Liferay Commerce instalado (por ej.: “liferay.workspace.home.dir=/Users/roselainedefaria/Liferay/Source/bundles”). Esta configuración nos permitirá desplegar el módulo automáticamente.
5. Ahora, renombra el paquete de “com.liferay.commerce.discount.rule.by.age.api” a “com.liferay.commerce.discount.rule.by.age” para eliminar la palabra “api” que “blade CLI” genera automáticamente (esto es porque usamos la plantilla “api” previamente).
6. En el fichero “bnd.bnd” elimina la línea “Export-Package: com.liferay.commerce.discount.rule.by.age.api”.
7. Abre la carpeta “resources” (i.e.:liferay-workspace-7-3/modules/commerce-discount-rule-by-age/src/main/resources) y borra todo en ella.
8. Abre el fichero “CommerceDiscountRuleByAge.java” y cambia el tipo de interface a class que implementa “CommerceDiscountRuleType” interfaz y guarda.
9. Ahora añadimos las dependencias a nuestro proyecto. Abre el fichero build.gradle file, elimina todo de este fichero y añade las siguientes dependencias:
dependencies { compileOnly group: "org.osgi", name: "org.osgi.core", version: "5.0.0" compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations" compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel" compileOnly group: "com.liferay.commerce", name: "com.liferay.commerce.api", version: "22.2.4" compileOnly group: "com.liferay.commerce", name: "com.liferay.commerce.discount.api", version: "7.0.0" compileOnly group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1" }
10. Vuelve a la clase “CommerceDiscountRuleByAge”, importa el paquete requerido por la interfaz implementa los tres métodos definidos por la interfaz.
11. Crea la siguiente variable (KEY):
public static final String KEY = "key-rule-gold-person";
12. Anota esta clase con @Component y establece 3 propiedades. Debería quedar así:
@Component( immediate = true, property = { "commerce.discount.rule.type.key=" + CommerceDiscountRuleByAge.KEY, "commerce.discount.rule.type.order=:Integer=61" },service = CommerceDiscountRuleType.class )
En el array de propiedades, establece los siguientes 2 valores necesarios para nuestro módulo de descuento:
"commerce.discount.rule.type.key=" + CommerceDiscountRuleOldPerson.KEY
"commerce.discount.rule.type.order:Integer=61"
Como servicio, declara la interfaz que estamos usando en nuestra clase:
service = CommerceDiscountRuleType.class .
13. Ahora en el método “getKey” incluya la sentencia “return KEY” para devolver la clave que declaramos antes, y en el método “getLabel” útil solo para poder probar el módulo, incluye la sentencia “return “New Custom Discount Type”. La clase @Component debería quedar así:
package com.liferay.commerce.discount.rule.by.age; import com.liferay.commerce.context.CommerceContext; import com.liferay.commerce.discount.model.CommerceDiscountRule; import com.liferay.commerce.discount.rule.type.CommerceDiscountRuleType; import com.liferay.portal.kernel.exception.PortalException; import org.osgi.service.component.annotations.Component; import java.util.Locale; /** * @author roselainedefaria */ @Component( immediate = true, property = { "commerce.discount.rule.type=" + CommerceDiscountRuleByAge.KEY, "commerce.discount.rule.order=:Integer=61" },service = CommerceDiscountRuleType.class ) public class CommerceDiscountRuleByAge implements CommerceDiscountRuleType { public static final String KEY = "key-rule-gold-person"; @Override public boolean evaluate(CommerceDiscountRule commerceDiscountRule, CommerceContext commerceContext) throws PortalException { return false; } @Override public String getKey() { return CommerceDiscountRuleByAge.KEY; } @Override public String getLabel(Locale locale) { return "New Custom Discount Type"; } }
14. Despliega tu módulo ejecutando el siguiente comando en la carpeta de tu “Liferay Workspace”:
liferay-workspace-7-3 % ./gradlew deploy
15. Si todo fue bien, el resultado será el siguiente (se enviará tu módulo a tu “Liferay Portal/DXP Bundle"):
> Task :modules:commerce-discount-rule-by-age:deploy Files of project ':modules:commerce-discount-rule-by-age' deployed to /Users/roselainedefaria/Liferay/Source/bundles/osgi/modules BUILD SUCCESSFUL in 4s
En Liferay Portal/DXP: Abre el Menu > Commerce > Descuentos > Añadir Nuevo Descuento. En el descuento creado, al final habrá una sección de “Reglas”, haz click en “+” para añadir una nueva. La nueva “Regla de Descuento” creada debería aparecer en la lista.
El código usado en este paso está disponible en una tag llamada “step-1” en mi repo de github.
Como sabrás, es una mala práctica utilizar un String con un valor codificado “a fuego” (o hard-code) como hicimos en el paso previo en el método “getLabel” (especialmente en un portal multi-idioma). Es importante que nuestro módulo sea multi-idioma, como muchas cosas en el mundo Liferay, así que tendremos que transformar el módulo para incluir capacidades multilenguaje.
1. Para ello... en el método “getLabel” usaremos un objeto “ResourceBundle”. Copia el siguiente fragmento de código y pégalo en el método “getLabel”. Después, importa todos los paquetes necesarios apoyándote en el IDE que utilices como Liferay Developer Studio.
ResourceBundle resourceBundle = ResourceBundleUtil.getBundle( "content.Language", locale, getClass()); return LanguageUtil.get(resourceBundle, "discount-rule-by-age");
2. Ahora, crearemos los ficheros de propiedades con las traducciones en el directorio “resources”:
Dentro de la carpeta ”content” crea un fichero con el idioma por defecto “Language.properties”, y en mi caso también los ficheros “Language_pt_BR.properties” y “Language_es_ES.properties”.
Copia la clave declarada antes: “rule-gold-person” en el método “getLabel”. Incluyela en los 3 ficheros de propiedades (a continuación, encontrarás las traducciones para cada idioma).
En Language.properties:
discount-rule-by-age=Discount Rule By Age
En Language_es_ES.properties
discount-rule-by-age=Regla de Descuento por edad
En Language_pt_BR.properties
discount-rule-by-age=Regra de Desconto por idade
3. Guarda los cambios y despliega el módulo ejecutando el siguiente comando dentro del directorio de tu Liferay Workspace:
En Liferay Portal/DXP, abre el Menu > Commerce > Descuentos > haz click en la regla de descuento creada antes. Hacia el final, habrá una sección con “Reglas”, haz click en “+” para añadir una nueva regla. Como resultado, aparecerá en la lista “Discount Rule By Age”.
4. Para probar con otros idiomas (portugués y español):
Ve a “localhost:8080” y al final de la URL añade “/es-ES/“ (http://localhost:8080/es-ES/)
Después, abre Menú > Commerce > Descuentos > haz click en el descuento creado antes. Hacia el final, habrá una sección para “Reglas”, haz click en “+” para añadir una nueva. Como resultado, en la lista debería aparecer el texto en español “Regla de Descuento por edad”.
Ve a “localhost:8080” y al final de la URL añade “/pt-BR/“ (http://localhost:8080/pt-BR/)
Después, abre Menú > Commerce > Descuentos > haz click en el descuento creado antes. Hacia el final, habrá una sección para “Reglas”, haz click en “+” para añadir una nueva. Como resultado, en la lista debería aparecer el texto en portugués “Regla de Descuento por edad”.
¡Felicidades! Ya has creado tu primera extensión de Commerce internacionalizada.
El código usado en este paso está disponible en una etiqueta con nombre “step-2” en mi repo de github.
1. Vuelve a tu clase Component “CommerceDiscountRuleByAge”, dentro del método “evaluate” recuperaremos el CommerceOrder del CommerceContext, y comprobaremos is commerceOrder es NULL (para parar el flujo).
CommerceOrder commerceOrder = commerceContext.getCommerceOrder(); if (commerceOrder == null){ return false; }
2. Al final de la clase, inyecta el servicio “UserLocalService” con la anotación @Reference.
@Reference protected UserLocalService userLocalService;
3. In the “evaluate” method, now you will recover the user, using the “userLocalService”.
User user = userLocalService.fetchUser(commerceOrder.getUserId());
4. Implementa un poco más de código para recuperar la edad del usuario actual, y así decidir si la regla se aplicará.
User user = userLocalService.fetchUser(commerceOrder.getUserId()); Calendar birthdayCal = CalendarFactoryUtil.getCalendar(); birthdayCal.setTime(user.getBirthday()); int birthdayMonth = birthdayCal.get(Calendar.MONTH) +1; int birthdayDay = birthdayCal.get(Calendar.DATE); int birthdayYear = birthdayCal.get(Calendar.YEAR); LocalDate birthdayLocalDate = LocalDate.of(birthdayYear, birthdayMonth, birthdayDay); LocalDate now = LocalDate.now(); Period period = Period.between(birthdayLocalDate, now); if(period.getYears() >= 70){ return true; }
5. Tras el paso previo, el método “evaluate” debería quedar como sigue:
@Override public boolean evaluate(CommerceDiscountRule commerceDiscountRule, CommerceContext commerceContext) throws PortalException { CommerceOrder commerceOrder = commerceContext.getCommerceOrder(); if (commerceOrder == null){ return false; } User user = userLocalService.fetchUser(commerceOrder.getUserId()); Calendar birthdayCal = CalendarFactoryUtil.getCalendar(); birthdayCal.setTime(user.getBirthday()); int birthdayMonth = birthdayCal.get(Calendar.MONTH) +1; int birthdayDay = birthdayCal.get(Calendar.DATE); int birthdayYear = birthdayCal.get(Calendar.YEAR); LocalDate birthdayLocalDate = LocalDate.of(birthdayYear, birthdayMonth, birthdayDay); LocalDate now = LocalDate.now(); Period period = Period.between(birthdayLocalDate, now); if(period.getYears() >= 70){ return true; } return false; }
6. Guarda los cambios y despliega el módulo ejecutando el comando siguiente en tu “Liferay Workspace”.
Adicionalmente, puedes añadir trazas en este clase. Para más información, consulta mi repo de GitHub.
El código usado en este paso está disponible en una etiqueta con nombre “step-3” en mi repo de github.
La configuración de descuentos debería ser más o menos así (resalto las importantes a configurar):
En la pestaña Aptitud (o “Eligibility” en inglés) puedes ver más configuración para asociar el descuento a “Grupos de cuentas específicas”,”Cuenta específica” o “Canal específico”.
Para probar necesitamos a un usuario del portal con más de 70 años. Para probar: Abre Menú > Control Panel > Usuarios y Organizaciones > haz click en el usuario actual, y cambian la fecha de nacimiento a una fecha de hace más de 70 años.
Ve a tu sitio de Commerce y comencemos las pruebas (si no tienes un sitio creado, consulta aquí como crear uno con los Aceleradores disponibles). ¡Añade algunos productos al carrito y comprueba! Debería aparecer el descuento (como en la imagen que se muestra a continuación).
Ahí lo tienes, módulo finalizado, pero podemos hacerlo mejor, en la próxima publicación del blog, aprenderá cómo hacer que la edad sea configurable y eliminar la "edad" como hard-code en su código.