This website uses cookies to ensure you get the best experience. Learn More.
How to create a Discount Rule extension to Liferay Commerce - DEV24 - (part 2)
...Done the part 1, we can continue our journey through the module extension...
In order to have a reusable module, we can make the “Age value” configurable and eliminate the hardcoded age from the module, following these steps you will learn how to create it:
1. In “resources” folder (i.e.: liferay-workspace-7-3/modules/commerce-discount-rule-by-age/src/main/resources), create two new folders: the first one called “META-INF” and the second one into the first, called “resources”.
2. Inside “META-INF/resources” create a new JSP file called “init.jsp” and another JSP file called “view.jsp”
3. In the “init.jsp”, copy and paste the following line, to import the aui taglib (which will be used in the view.jsp):
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
4. In the “view.jsp”, copy and paste the following line (which there is the input for age):
<%@ include file="/init.jsp" %> <div class="col-12"> <div class="card d-flex flex-column"> <h4 class="align-items-center card-header d-flex justify-content-between py-3"> <liferay-ui:message key="add-minimum-age-to-discount" /> </h4> <div class="card-body flex-fill"> <aui:input label="minimum-age-to-discount" name="typeSettings" type="text"> <aui:validator name="digits" /> <aui:validator name="min">30</aui:validator> </aui:input> </div> </div> </div>
5. Include the language keys “add-minimum-age-to-discount” and “minimum-age-to-discount” in the JSP above. Include the translation in the 3 properties files (below the key with each translation).
add-minimum-age-to-discount=Add the minimum age to discount minimum-age-to-discount=Minimum age to apply the discount
add-minimum-age-to-discount=Añada la edad mínima para el descuento minimum-age-to-discount=Edad mínima a aplicar el descuento
add-minimum-age-to-discount=Adicione a idade mínima para o desconto minimum-age-to-discount=Idade mínima para dar o desconto
6. Create a new package on your project “com.liferay.commerce.discount.rule.by.age.render”.
7. Create a java class “CommerceDiscountRuleTypeJSPContributorRuleByAge” which implements the “CommerceDiscountRuleTypeJSPContributor” interface.
8. Implement the “render” method.
9. Inside the class create a Key:
public static final String KEY = "key-rule-gold-person";
10. Mark this class as a @Component and inside, include 3 properties. It should look like the below:
@Component( immediate = true, property = { "commerce.discount.rule.type.jsp.contributor.key=" + CommerceDiscountRuleTypeJSPContributorRuleByAge.KEY, },service = CommerceDiscountRuleTypeJSPContributor.class )
11. Add new dependencies to your project. Open the “build.gradle” file, and copy and paste the following line (this dependency is needed to use the JSPRenderer):
compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib", version: "5.4.3"
12. In the “CommerceDiscountRuleTypeJSPContributorRuleByAge.java”, at the bottom of class, inject the service “JSPRenderer” with the @Reference annotation,
@Reference private JSPRenderer _jspRenderer;
13. After, inject the service “ServletContext” with the @Reference annotation, and use the “target” parameter to reference the “Bundle-SymbolicName” (located in the bnd.bnd file) from your module to locate the JSP.
@Reference(target="(osgi.web.symbolicname=com.liferay.commerce.discount.rule.by.age)") private ServletContext _servletContext;
14. Open the “bnd.bnd” file (located on “liferay-workspace-7-3/modules/commerce-discount-rule-by-age”) and declare a “Web-ContextPath” (the value should be unique). This way, your ServletContext will be generated correctly.
Web-ContextPath: /discount-rule-by-age
15. Now, in the component class “CommerceDiscountRuleTypeJSPContributorRuleByAge”, in the “render” method implement the logic for your custom input value (for the age) with the “_jspRenderer” service to “view.jsp”, like in the code snippet below:
@Override public void render(long commerceDiscountId, long commerceDiscountRuleId, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { _jspRenderer.renderJSP( _servletContext, httpServletRequest, httpServletResponse, "/view.jsp"); }
16. To finish this step, go back to the component class “CommerceDiscountRuleByAge”, in the “evaluate” method we will retrieve the value setting to change the age value “70” hardcoded to your settings variable.
String settingsProperty = commerceDiscountRule.getSettingsProperty( commerceDiscountRule.getType()); int ageSetting = Integer.valueOf(settingsProperty); if(period.getYears() >= ageSetting){ return true; }
17. Save and deploy it by executing the following command into your Liferay Workspace.
liferay-workspace-7-3 % ./gradlew deploy
The code used in the previous step is available on a tag called “step-4” on github.
In Liferay Portal/DXP, go to: Open Menu > Commerce > Discounts > Click on discount created before, at the bottom, there will be a box for “Rules”, click on “Edit”
Fill with the value “70” and save it.
Go to your commerce site and test it, adding some products to your cart and check that everything keeps working as expected.
Go back to “edit” your rule again and you will see the input empty.
In the next step we will see how to retrieve the stored value.
1. Add two new dependencies to your project. Open the “build.gradle” file, and copy and paste the following lines (these dependencies are necessary to use the StringPool and the BeanParamUtil classes):
compileOnly group: "com.liferay", name: "com.liferay.petra.string" compileOnly group: "javax.portlet", name: "portlet-api", version: "3.0.0"
2. Create a new package in your project “com.liferay.commerce.discount.rule.by.age.display.context”.
3. Create a class “CommerceTrainingDiscountRuleDisplayContext.java”.
4. At the bottom on your class, declare the 3 variables:
private CommerceDiscountRule _commerceDiscountRule; private final HttpServletRequest _httpServletRequest; private final CommerceDiscountRuleService _commerceDiscountRuleService;
5. Create a constructor for your class, which will receive as parameters the “CommerceDiscountRuleService” and “HttpServletRequest”.
public CommerceTrainingDiscountRuleDisplayContext(CommerceDiscountRuleService commerceDiscountRuleService, HttpServletRequest httpServletRequest){ _commerceDiscountRuleService = commerceDiscountRuleService; _httpServletRequest = httpServletRequest; }
6. Create a method to get the “CommerceDiscountRule”, like in the code snippet below.
public CommerceDiscountRule getCommerceDiscountRule() throws PortalException { if (_commerceDiscountRule != null) { return _commerceDiscountRule; } long commerceDiscountRuleId = ParamUtil.getLong( _httpServletRequest, "commerceDiscountRuleId"); if (commerceDiscountRuleId > 0) { _commerceDiscountRule = _commerceDiscountRuleService.getCommerceDiscountRule( commerceDiscountRuleId); } return _commerceDiscountRule; }
7. Finally in this class, create a method to get the “getTypeSettings”, which will retrieve the value stored in your custom configuration.
public String getTypeSettings() throws PortalException { CommerceDiscountRule commerceDiscountRule = getCommerceDiscountRule(); if (commerceDiscountRule == null) { return StringPool.BLANK; } String type = BeanParamUtil.getString( commerceDiscountRule, _httpServletRequest, "type"); return commerceDiscountRule.getSettingsProperty(type); }
8. Open the “CommerceDiscountRuleTypeJSPContributorRuleByAge.java”, and at the bottom of class, inject the service “CommerceDiscountRuleService” with the @Reference annotation.
@Reference private CommerceDiscountRuleService _commerceDiscountRuleService;
9. Even in this class, go to the “render” method, create an instance of “CommerceDiscountRuleByAgeDisplayContext” and set it to “httpServletRequest”.
CommerceDiscountRuleByAgeDisplayContext CommerceDiscountRuleByAgeDisplayContext = new CommerceDiscountRuleByAgeDisplayContext(_commerceDiscountRuleService,httpServletRequest); httpServletRequest.setAttribute("view.jsp-commerceDiscountRuleByAgeDisplayContext",CommerceDiscountRuleByAgeDisplayContext);
10. In the “init.jsp”, import the “CommerceDiscountRuleByAgeDisplayContext” (which you will use in the view.jsp)
<%@ page import="com.liferay.commerce.discount.rule.by.age.display.context.CommerceDiscountRuleByAgeDisplayContext" %>
11. In the “view.jsp”, below at the include, retrieve the “CommerceDiscountRuleByAgeDisplayContext” from the request, and through the method “getTypeSetting” retrieve the stored value.
<%@ include file="/init.jsp" %> <% CommerceDiscountRuleByAgeDisplayContext commerceDiscountRuleByAgeDisplayContext = (CommerceDiscountRuleByAgeDisplayContext)request.getAttribute("view.jsp-commerceDiscountRuleByAgeDisplayContext"); String value = commerceDiscountRuleByAgeDisplayContext.getTypeSettings(); %>
12. Finally, add the value parameter to the input with the variable.
<aui:input label="minimum-age-to-discount" name="typeSettings" type="text" value="<%= value %>">
13. Save and deploy it by executing the following command in your Liferay Workspace.
14. Now, if you go back to “edit” your rule, you will see the input with the value stored.
The code used in the previous step is available on a tag called “last-step” on github.
...And this is the end...
I hope you have enjoyed it. In this tutorial, I tried to explain everything step by step, so that all developers are able to understand it (to the newbies , welcome! XD ).