Hybris 6 "Could have fired" messages (PoC)
Situation
“Could Have Fired” message indicates that the criteria of the promotion has been partially fulfilled. For example, when you have two products in your cart and the promotion for the three products (like buy 3 get 1 free), the ‘could have fired’ message could look like “buy one more product and get one free”. SAP hybris 6.0 uses new rule-based promotion engine that is faster and more flexible. However, because of the completely new paradigm some capabilities that we had in the previous versions of hybris are not presented now in hybris 6. One of them is “Could have fired” messages. In the new version for this purpose you need to use fake promotions. It means that for the example above you need to create two promotions: one is for a set of three products and another is for a set of two products. Being fired, the second promotion should show the ‘could have fired’ message. For some cases this approach is quite flexible. For example, you can configure ‘could have fired’ messages for products which similar to the promotional product. It is a really strong point. However, it is a manual work. It is difficult to cover all the cases when ‘could have fired’ message could be shown. The ‘could have fired’ promotions are difficult to manage and support.Complexity
The new rule-based promotion engine is only integrated into the cart. Product pages, product list, search results will not use it at all. Drools, the core of the hybris 6 promotion engine, is designed for a broad range of tasks. SAP hybris pushes data into drools and receives a set of actions. There are no such thing as “partially fired rules” detection.Challenge
Create a proof-of-concept prototype with smart ‘could have fired’ messages. The idea is about showing tips on the product pages like- If you put this product in the cart, you will get 10% discount”
- If you put this product in the cart, you will get a free product”
- If you put this product in the cart, you will have a free delivery” etc.
Solution
Product page controller evaluates promotions against (the customer’s cart + current product). Then the results are compared with ones from the shopping cart. Added actions are displayed as ‘could have fired’ messages. The caveat is in promotion engine interfaces. For some reason, the classes don’t expose all the data available in the backoffice. Some methods and attributes that used by hybris are not available for developers.Video
In the video below the following process is shown: the second part is a bit more complicated:Technical details
final CartModel existingCart = cartService.getSessionCart();
final CartModel virtualCart = modelService.create(CartModel.class);
cloneCart(existingCart, virtualCart);
final ProductModel product = productService.getProductForCode(productCode);
addProductToCart(virtualCart, product)
...
RuleEvaluationResult ruleEvaluationResultWithoutNewProduct =
promotionEngineService.evaluate(virtualCart, getPromotionGroups());
RuleEvaluationResult ruleEvaluationResult =
promotionEngineService.evaluate(existingCart, getPromotionGroups());
...
Iterator < AbstractRuleActionRAO > next6 = ruleEvaluationResult.getResult().getActions().iterator();
while (next6.hasNext()) {
AbstractRuleActionRAO actionRAO = next6.next();
if (actionRAO instanceof DiscountRAO) {
BigDecimal discountValue = ((DiscountRAO) actionRAO).getValue();
if (ruleEvaluationResultWithoutNewProduct.getResult() != null) {
Iterator < AbstractRuleActionRAO > next7 = ruleEvaluationResultWithoutNewProduct.getResult().getActions().iterator();
...
}
}
...
}
final CartModel virtualCart = modelService.create(CartModel.class);
cloneCart(existingCart, virtualCart);
final ProductModel product = productService.getProductForCode(productCode);
addProductToCart(virtualCart, product)
...
RuleEvaluationResult ruleEvaluationResultWithoutNewProduct =
promotionEngineService.evaluate(virtualCart, getPromotionGroups());
RuleEvaluationResult ruleEvaluationResult =
promotionEngineService.evaluate(existingCart, getPromotionGroups());
...
Iterator < AbstractRuleActionRAO > next6 = ruleEvaluationResult.getResult().getActions().iterator();
while (next6.hasNext()) {
AbstractRuleActionRAO actionRAO = next6.next();
if (actionRAO instanceof DiscountRAO) {
BigDecimal discountValue = ((DiscountRAO) actionRAO).getValue();
if (ruleEvaluationResultWithoutNewProduct.getResult() != null) {
Iterator < AbstractRuleActionRAO > next7 = ruleEvaluationResultWithoutNewProduct.getResult().getActions().iterator();
...
}
}
...
}