Search code examples
drools

Drools : stop a rule from firing after a number of executions


I'm trying to figured out how to stop a rule from firing after a number of executions. Let's say you grant a discount if you buy an item X (current price $10), but this discount can be granted only 2 times per customer.

so my rule is as follow:

 rule "Fixed Price Promotion Item X"

 when
     $o : Order( )
     $ol1 : OrderLine( item.code == "X" )
 then
    FixedPrice fixedPrice = new FixedPrice(8.80, $ol1.getItem().getPrice().doubleValue(), $ol1.getItem().getBarcode(), 1, "e78fbca5ed014f49806ad667aea80965" , "Happy Mother's day!! This is a fixed price promotion" );
    insertLogical (fixedPrice); //here I grant a promotion

Originally, I thought to have another rule to insert a fact when my condition was met so It would stop my promotion rule from firing.

I would have something like this:

declare LimitReachedOut
   promotionId : String
end

rule "stop Promotion"
when
     Number($numOfGrantedProm : intValue) from accumulate ( 
                                FixedPrice(promotionId == "123",
                                        $count: quantity),
                                sum($count)
            )
then
    if( $numOfGrantedProm == 2  ){ //this cause an issue, even > 1 or >=2 will keep inserting new LimitReachedOut("123") recursively.
        insertLogical (new LimitReachedOut("123"));
     }
end  


rule "Fixed Price Promotion Item X"
 when
     not( LimitReachedOut( promotionId == "123" ) )
     $o : Order( )
     $ol1 : OrderLine( item.code == "X" ) 
 then
    FixedPrice fixedPrice = new FixedPrice(8.80, $ol1.getItem().getPrice().doubleValue(), $ol1.getItem().getBarcode(), 1, "123" , "Happy Mother's day!! This is a fixed price promotion" );
    insertLogical (fixedPrice);

 end

Is there another way to do it?

I will really appreciate your comments.


Solution

  • I've found a way to accomplish what I wanted, and I'm posting it in here just if someone wants to use this as well. I'm basically not executing the RHS of the rule putting a conditional clause there.

    Firstly, I'm calculating the number of Facts that were inserted into the working memory ( FixedPrice with an id called ruleId to link the facts to this particular rule ) using the accumulate function. Secondly, the condition in the RHS if( $numOfGrantedProm < 2 ) means that I will execute the block inside of the conditional if (create & insert fixedPrice fact) up to two times. The rule will be fired anyway but the if condition will avoid executing the block of code.

    rule "Fixed Price Promotion Item X"
    
    when
       $o : Order( )
       $ol1 : OrderLine( item.code == "X" )
       Number($numOfGrantedProm : intValue) from accumulate ( 
                                               FixedPrice(ruleId == 
                               "e78fbca5ed014f49806ad667aea80965",$count:quantity),
                               sum($count)
                          )
    then
       if( $numOfGrantedProm < 2  ){ 
           FixedPrice fixedPrice = new FixedPrice(8.80,
                                       $ol1.getItem().getPrice().doubleValue(),
                                       $ol1.getItem().getBarcode(), 
                                       1, 
                                       "e78fbca5ed014f49806ad667aea80965" , 
                                       "Happy Mother's day!! This is a fixed price 
                                        promotion" );
           insertLogical (fixedPrice); //here I grant a promotion enter code here
        }
    end