Excluding Certain Products from Total Cart Value Calculation (PromoEngine)


Introduction

In one of our projects we have a requirement to exclude certain products from the total cart value calculation. So, for example, we would have a custom condition which would trigger a free gift action if the order total > 200 without including product A and product B on the order. In other words, the dollar values of the cart entries which contain product A and B need to be excluded in the cart total calculation. It appears that this dynamic condition cannot be supported with the promotion engine since when the СartRao is being populated the promotion condition parameters are not known. The problem is accessing the products at runtime, because in the default implementation all the condition constraints are compiled into static drools rules. It is not possible/very difficult to extract the condition values like a list of the products to be excluded from the calcultation. When the cartRao is being created we don’t even know which promotion could potentially trigger so that we could get the condition parameters from it.

Solution

My solution is using two promotions, one is for calculating “a new cart total” if all certain products are present in the cart.  The calculated value is stored in CartRAO and can be used in the next promotions in the same promo calculation session. The second promotion depends on the first one, so it will work only if the certain products are found and “a new cart total” is calculated. Then you can combine them together using stackability so only one promotion fires at a time. 2016-12-17_12h36_40.png

Demonstration

Technical details

public class CalcTotalPriceAction implements RuleExecutableAction {
private CalculatedTotalsRao calculatedTotalsRao;
private ProductService productService;
private PriceService priceService;
@Override
public void executeAction(RuleActionContext ruleActionContext, Map<String, Object> map) throws RuleEvaluationException {
String orderEntryRAOCode = "de.hybris.platform.ruleengineservices.rao.OrderEntryRAO";
String cartEntryRAOCode = "de.hybris.platform.ruleengineservices.rao.CartRAO";;
long totalPrice=calculateTotalPrice( (Set<OrderEntryRAO>) ((DefaultDroolsRuleActionContext) ruleActionContext).getVariables().get(orderEntryRAOCode));
Set <CartRAO> carts = (Set<CartRAO>) ((DefaultDroolsRuleActionContext) ruleActionContext).getVariables().get(cartEntryRAOCode);
CartRAO cart = carts.iterator().next();
// I use cart.setTotal in PoC, but I recommend to have a designated attribute for the recalculated cart totals
// However, you will need to extend the cart totals condition to use the recalculated value
// For the demonstration purposes I used an OOTB attribute, "Total"
cart.setTotal(BigDecimal.valueOf(cart.getTotal().longValue() - BigDecimal.valueOf(totalPrice).longValue()));
}

//for the demonstration purposes I use "long" for the price values
private long calculateTotalPrice(Set<OrderEntryRAO> entries) {
long totalPrice = 0;
for (OrderEntryRAO orderEntryRao : entries) {
ProductModel productModel = productService.getProductForCode(orderEntryRao.getProduct().getCode());
List<PriceInformation> prices = priceService.getPriceInformationsForProduct(productModel);
double productPrice = prices.get(0).getPriceValue().getValue();
//for the demonstration purposes I use "long" for the price values
totalPrice = totalPrice + Math.round(orderEntryRao.getQuantity() * productPrice) ;
}
return totalPrice;
}
}

© Rauf Aliev, January 2017

3 Responses

  1. Suhaim

    Suhaim

    Reply

    13 June 2017 at 11:15

    Hi Rauf , i too was trying to implement the similar feature. The subpromotion or the promotion that checks for the qualifying products do work along with the recalculate totals but the updated totals is not passed over to the main promotion.
    For the action i have used ( XXXXaction extends AbstractRuleExecutableSupport implements RAOAction )
    Can you please let me know what values did you set for stackabilty for the main and sub promotion.
    Did you enable or disable the flag when you invoke the sub promotion from the main promotion (Action rule execution allowed)?
    Thank you for sharing the approach

Leave a Reply