Define New Promotion Type_
Story
Define a new promotion type
Generate a (JALO) class for the promotion logic
Rebuild and Verify
Implement the promotion's logic
Navigation
Previous Step | Home | Next Step
Please review all available product promotions that promotions extension comes out-of-the-box.
Story
Imagine that you need a new type of promotion: Buy X items of product A, get product B for free!.
The difference between our new type and the standard BOGOF (Buy 1 Get 1 Free) promotion is that ours allows the free product to be different from the
qualifying products. For instance, Buy 5 A5 notepads, get a hybris pen for free. Let's then define a promotion that would apply to the following cart:
Define a new promotion type
A promotion type is an entity we need to define in our project's [Link].
Let's add a new promotion type that:
extends from ProductPromotion
defines qualifyingCount integer attribute
defines giftProduct attribute of type Product
defines the following localized String messages attributes : messageFired and messageCouldHaveFired
merchandisecommerceservices/resources/[Link]
...
<itemtype code="ProductQuantityThresholdFreeGiftPromotion"
extends="ProductPromotion"
jaloclass="[Link]"
autocreate="true"
generate="true">
<attributes>
<attribute
qualifier="giftProduct"
autocreate="true"
type="Product">
<description>The partner product.</description>
<modifiers read="true" write="true" search="true" optional="true"/>
<persistence type="property"/>
</attribute>
<attribute
qualifier="qualifyingCount"
autocreate="true"
type="[Link]">
<defaultvalue>[Link](3)</defaultvalue>
<description>The number of base products required to qualify for the
free gift.</description>
<modifiers read="true" write="true" search="true" optional="true"/>
<persistence type="property"/>
</attribute>
<attribute qualifier="messageFired" type="localized:[Link]">
<description>The message to show when the promotion has fired.<
/description>
<modifiers read="true" write="true" optional="true" />
<persistence type="property">
<columntype database="oracle">
<value>varchar2(4000)</value>
</columntype>
<columntype database="mysql">
<value>text</value>
</columntype>
<columntype database="sqlserver">
<value>nvarchar(max)</value>
</columntype>
<columntype database="hsqldb">
<value>LONGVARCHAR</value>
</columntype>
<columntype>
<value>varchar</value>
</columntype>
</persistence>
</attribute>
<attribute qualifier="messageCouldHaveFired" type="localized:[Link]">
<description>The message to show when the promotion could have
potentially fire.</description>
<modifiers read="true" write="true" optional="true" />
<persistence type="property">
<columntype database="oracle">
<value>varchar2(4000)</value>
</columntype>
<columntype database="mysql">
<value>text</value>
</columntype>
<columntype database="sqlserver">
<value>nvarchar(max)</value>
</columntype>
<columntype database="hsqldb">
<value>LONGVARCHAR</value>
</columntype>
<columntype>
<value>varchar</value>
</columntype>
</persistence>
</attribute>
</attributes>
</itemtype>
...
We will need this type and its attributes to be localized (the hMC will use these value for its prompts):
merchandisecommerceservices/resources/localization/merchandisecommerceservices-locales_en.properties
[Link]=Buy x Items of Product A, get Product B as a Gift
[Link]=Free Gift
[Link]=Qualifying Count of Base Product
[Link]=Message for fired promotion
[Link]=Message if promotion could have fired
Generate a (JALO) class for the promotion logic
Not only does hybris generate servicelayer model classes to represent hybris types, but the ant compilation process also generates utility classes that
serve as the underpinning of these model classes. These utility classes are referred to as jalo layer classes. The jalo layer (the name comes from Jakarta
Logic) is normally invisible, and hybris developers are in fact discouraged from using it, at it is expected to be deprecated in an upcoming hybris release.
In spite of this, the promotion extension mechanism requires you to place new code in the jalo layer. We will do so, keeping in mind that this is an
exception to our recommendation to avoid placing code in the jalo layer.
Run ant all which generates the jalo class ProductQuantityThresholdFreeGiftPromotion. Notice that abstract methods in the parent class are
not generated automatically (that is, after all, the point of abstract methods: the extending class must provide an implementation for them).
build logs
[yjavac] Compiling 10 source files to C:
\commerceTrails\hybris\bin\custom\merchandise\merchandisecommerceservices\classes
[yjavac] ----------
[yjavac] 1. ERROR in C:
\commerceTrails\hybris\bin\custom\merchandise\merchandisecommerceservices\src\de\hybris\merchandise\jalo\Product
QuantityThre
[Link] (at line 22)
[yjavac] public class ProductQuantityThresholdFreeGiftPromotion extends
GeneratedProductQuantityThresholdFreeGiftPromotion
[yjavac] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[yjavac] The type ProductQuantityThresholdFreeGiftPromotion must implement the inherited abstract method
[Link](Ses
sionContext, PromotionResult, Locale)
[yjavac] ----------
[yjavac] 2. ERROR in C:
\commerceTrails\hybris\bin\custom\merchandise\merchandisecommerceservices\src\de\hybris\merchandise\jalo\Product
QuantityThre
[Link] (at line 22)
[yjavac] public class ProductQuantityThresholdFreeGiftPromotion extends
GeneratedProductQuantityThresholdFreeGiftPromotion
[yjavac] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[yjavac] The type ProductQuantityThresholdFreeGiftPromotion must implement the inherited abstract method
[Link](SessionContext,
PromotionEvaluationContext)
[yjavac] ----------
[yjavac] 2 problems (2 errors)
BUILD FAILED
Abstract methods inherited from parent classes need to be created manually. Refresh the merchandisecommerceservices extension and open the
generated ProductQuantityThresholdFreeGiftPromotion class.
The only method generated automatically is createItem; since it merely calls super(), please feel free to remove it. Replace it with the following code,
which provides an empty (for now) implementation for the two abstract methods of the GeneratedProductQuantityThresholdFreeGiftPromotion class, e
valuate() and getResultDescription():
merchandisecommerceservices/src/de/hybris/merchandise/jalo/[Link]
...
import [Link];
import [Link];
public class ProductQuantityThresholdFreeGiftPromotion extends
GeneratedProductQuantityThresholdFreeGiftPromotion
{
@SuppressWarnings("unused")
private final static Logger LOG = [Link]([Link].
getName());
@Override
public List<PromotionResult> evaluate(final SessionContext ctx, final PromotionEvaluationContext
promoContext)
{
// YTODO Auto-generated method stub
return null;
}
@Override
public String getResultDescription(final SessionContext ctx, final PromotionResult promotionResult,
final Locale locale)
{
// YTODO Auto-generated method stub
return null;
}
Rebuild and Verify
Rebuild the code base by calling ant all. Then restart hybris server.
We need to perform a system update to:
create deployment for our new promotion type
localize our new type
load our hmc configuration changes
Go to the hac's system update page to perform system update.
After updating the system, you can go to the hmc and verify if you can create a new instance of our promotion type.
Notice that we created a required attribute Qualifying Count of Base Product on the Administration tab:
Implement the promotion's logic
We have previously supplied empty methods for our promotion class:
evaluate - which evaluates the current cart, its products and current promotion evaluation context to respond with a collection of PromotionResult
s
getResultDescription - which composes promotion marketing messages on the frontend.
Promotion evaluation
In the evaluate method we have to:
get the base product for the current promotion instance (A5 notepad)
get the qualifying quantity of base product for the current promotion instance (5)
check the quantity of the base product in the session cart
add a PromotionAction to the promotion result if the real quantity is greater or equal to the qualifying quantity
if the base product appears in the cart but the quantity does not qualify - add PromotionResult without PromotionAction (less than 1 , more that 0
- which will display the "couldHaveFired" marketing message to the customer. )
PromotionAction - is an executable entity that represents an action which is performed if user's cart qualifies for promotion.
The promotion extension comes with a set of promotion actions out-of-the-box. You may define your own PromotionAction type by creating a new type that
extends AbstractPromotionAction.
However, in this trail, we will use an existing action: PromotionOrderAddFreeGiftAction
Promotion messages creation
In getResultDescription, we must resolve the parameter values for the parametrized promotion fired and promotion could have fired messages.
We will allow messages with 1 parameter, the qualifying quantity of the base product, in order that users know how many items need to added to the cart
to get the promotion fired.
Please note that the parameters we add to the messages and their order need to be described in localized text entries (in the hMC):
[Link]
[Link]
Provide the complete implementation for the ProductQuantityThresholdFreeGiftPromotion class:
merchandisecommerceservices/src/de/hybris/merchandise/jalo/[Link]
/*
*
* [y] hybris Platform
*
* Copyright (c) 2000-2014 hybris AG
* All rights reserved.
*
* This software is the confidential and proprietary information of hybris
* ("Confidential Information"). You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the
* license agreement you entered into with hybris.
*
*/
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
/**
* Custom promotion for a trail scenario. Buy a defined number of base product to get a partner gift.
*
*
*/
public class ProductQuantityThresholdFreeGiftPromotion extends
GeneratedProductQuantityThresholdFreeGiftPromotion
{
private final static Logger LOG = [Link]([Link].
getName());
@Override
public List<PromotionResult> evaluate(final SessionContext ctx, final PromotionEvaluationContext
promoContext)
{
if (getProducts() != null && !getProducts().isEmpty())
{
// the base product is the first of related products
final Product baseProduct = getProducts().iterator().next();
final List<PromotionResult> results = new ArrayList<PromotionResult>();
// Find the eligible products, and apply any restrictions
final [Link] restrictResult =
findEligibleProductsInBasket(ctx, promoContext);
// If the restrictions did not reject this promotion, and there are still products
allowed after the restrictions
if ([Link]() && ![Link]().
isEmpty())
{
final int qualifyingCount = [Link](ctx).intValue();
// Create a view of the order containing only the allowed products
final PromotionOrderView orderView = [Link](ctx, this,
[Link]());
// Get the real quantity of the base product in the cart
final long realQuantity = [Link](ctx, baseProduct);
if (realQuantity >= qualifyingCount)
{
if ([Link]())
{
[Link]("(" + getPK() + ") evaluate: product quantity " +
realQuantity + ">" + qualifyingCount
+ ". Creating a free gift action.");
}
final PromotionResult result = [Link]().
createPromotionResult(ctx, this,
[Link](), 1.0F);
//Apply free gift promotion action
final Product product = [Link](ctx);
[Link](ctx, [Link]().
createPromotionOrderAddFreeGiftAction(ctx, product, result));
[Link](result);
}
else
{
if ([Link]())
{
[Link]("(" + getPK() + ") evaluate: product quantity " +
realQuantity + ">" + qualifyingCount
+ ". Creating a free gift action.");
}
final float certainty = (realQuantity / qualifyingCount);
final PromotionResult result = [Link]().
createPromotionResult(ctx, this,
[Link](), certainty);
[Link](result);
}
return results;
}
}
return null;
}
@Override
public String getResultDescription(final SessionContext ctx, final PromotionResult promotionResult,
final Locale locale)
{
final Object[] args =
{ [Link]() };
if ([Link](ctx))
{
return formatMessage([Link](ctx), args, locale);
}
else if ([Link](ctx))
{
return formatMessage([Link](ctx), args, locale);
}
return "";
}
Rebuild and Verify
Rebuild the code base and restart the server.
Create an instance of our promotion type in the hmc:
Identifier: GetPensForFree
Promotion Group: hybrisPromoGrp
Enabled: yes
Priority: 1000
Products: Hybris A5 Notepad (from the Online Product Catalog)
And in the Administration tab:
Free Gift: hybris Pen (from the Online Product Catalog)
Message if promotion could have fired: Buy {0} A5 Notepads to get a free gift
Message for fired promotion: With your {0} A5 Notepads, you have qualified for a free pen.
Go to the store front end and compose a
"promotion could have fired" cart (with a quantity of less than 5 hybris A5 Notepads)
"promotion fired" cart (with at least 5 hybris A5 Notepads)