I have implemented BXGY custom promotion. To simplify my case let's say after you have X products in your cart you'll get Y free products.
If I have 2*X qualifying products in cart expected behavior is to get 2*Y free products.
My problem is multi-firing of that promotion. If I set maximum count of multifiring to 4, than action (get free products) is activated 4 times although I have 2*X products in cart.
So my conclusion is that I need to consume qualifying products (entries with that product) like free products that user gets are consumed so they cannot participate in qualification for another promotion.
Conclusion of my research is that I need to consume entries in (YFreeGift)RAOAction, but then I need to retrieve all conditional products and I don't feel that it's a right way (condition in action).
Do anybody knows how to consume qualifying entries?
Condition translator for BXGY (I have mandatory qualifying products too but that isn't important for this problem)
public class RuleHeinekenBXGYFQualifyingProductsConditionTranslator implements RuleConditionTranslator
{
@Override
public RuleIrCondition translate(RuleCompilerContext context, RuleConditionData ruleCondition, RuleConditionDefinitionData conditionDefinition) throws RuleCompilerException
{
List<String> mandatoryProducts = (List) getConditionParameterValue(ruleCondition, "mandatoryQualifyingProducts");
List<String> alternativeProducts = (List) getConditionParameterValue(ruleCondition, "alternativeQualifyingProducts");
Integer qualifyingCount = (Integer) getConditionParameterValue(ruleCondition, "qualifyingCount");
if(isEmpty(mandatoryProducts) && isEmpty(alternativeProducts) || qualifyingCount == null || qualifyingCount <= 0)
throw new PromotionConditionParametersValidationException();
String cartRAO = context.generateVariable(CartRAO.class);
List<RuleIrCondition> mandatoryProductsConditions = getMandatoryProductsConditions(context, mandatoryProducts, cartRAO);
List<RuleIrCondition> qualifyingCountCondition = getQualifyingCountCondition(context, qualifyingCount, cartRAO);
RuleIrGroupCondition qualifyingConditions = new RuleIrGroupCondition();
qualifyingConditions.setOperator(RuleIrGroupOperator.AND);
qualifyingConditions.setChildren(listUnion(mandatoryProductsConditions, qualifyingCountCondition));
return qualifyingConditions;
}
private List<RuleIrCondition> getQualifyingCountCondition(RuleCompilerContext context, Integer qualifyingCount, String cartRAO)
{
String qualifyingCountRAO = context.generateVariable(QualifyingCountRAO.class);
String promotionCode = context.getRule().getCode();
return getListOfRuleConditions(
aRuleCondition()
.withModelRAO(qualifyingCountRAO)
.withAttribute("promotionCode")
.withOperator(EQUAL)
.withValue(promotionCode)
.buildAttributeCondition(),
aRuleCondition()
.withModelRAO(qualifyingCountRAO)
.withAttribute("qualifyingCount")
.withOperator(GREATER_THAN_OR_EQUAL)
.withValue(qualifyingCount)
.buildAttributeCondition(),
aRuleCondition()
.withModelRAO(cartRAO)
.withAttribute("qualifyingCounts")
.withOperator(CONTAINS)
.withTargetVariable(qualifyingCountRAO)
.buildAttributeRelationCondition());
}
private List<RuleIrCondition> getMandatoryProductsConditions(RuleCompilerContext context, List<String> mandatoryProducts, String cartRAO)
{
if(isEmpty(mandatoryProducts))
return emptyList();
return getMapOfQualifyingProductsWithQuantities(mandatoryProducts)
.entrySet().stream()
.map(entry -> getMandatoryProductCondition(context, cartRAO, entry.getKey(), entry.getValue()))
.collect(toList());
}
private RuleIrExistsCondition getMandatoryProductCondition(RuleCompilerContext context, String cartRAO, String product, int qualifyingCount)
{
RuleIrLocalVariablesContainer variablesContainer = context.createLocalContainer();
String containsProductRAO = context.generateLocalVariable(variablesContainer, ProductRAO.class);
String containsOrderEntryRAO = context.generateLocalVariable(variablesContainer, OrderEntryRAO.class);
List<RuleIrCondition> listOfConditions = getListOfRuleConditions(
aRuleCondition()
.withModelRAO(containsProductRAO)
.withAttribute("code")
.withOperator(EQUAL)
.withValue(product)
.buildAttributeCondition(),
aRuleCondition()
.withModelRAO(containsOrderEntryRAO)
.withAttribute("product")
.withOperator(EQUAL)
.withTargetVariable(containsProductRAO)
.buildAttributeRelationCondition(),
aRuleCondition()
.withModelRAO(containsOrderEntryRAO)
.withAttribute("quantity")
.withOperator(GREATER_THAN_OR_EQUAL)
.withValue(qualifyingCount)
.buildAttributeCondition(),
aRuleCondition()
.withModelRAO(cartRAO)
.withAttribute("entries")
.withOperator(CONTAINS)
.withTargetVariable(containsOrderEntryRAO)
.buildAttributeRelationCondition());
RuleIrExistsCondition mandatoryProductsExistCondition = new RuleIrExistsCondition();
mandatoryProductsExistCondition.setVariablesContainer(variablesContainer);
mandatoryProductsExistCondition.setChildren(listOfConditions);
return mandatoryProductsExistCondition;
}
}