[rules-users] rules for promotional offers

Sandeep Bandela gibsosmat at gmail.com
Fri Sep 9 04:55:11 EDT 2011


some more info for the modify() problem, the CartItem is an interface and
the implementation is CartItemImpl. if this info leads to some clues.

On Fri, Sep 9, 2011 at 1:28 PM, Sandeep Bandela <gibsosmat at gmail.com> wrote:

> Hi here is the same thing converted to mvl
>
> // this Bundler.java has integer member that keeps incrementing
> global Bundler bundler
>
>
> rule "Apply 10% discount if you purchase 2 items"
>     when
>         $s1 : CartItem( *productId == 219759*, processed == false)
>         $s2 : CartItem( this != $s1, productId == $s1.productId, processed
> == false)
>
>         $m : RuleMessage()
>  then
>         $m.addMessage("Found item1: " + $s1.getName() + " id:
> "+$s1.getId());
>         $m.addMessage("Found item2: " + $s2.getName() + " id:
> "+$s2.getId());
>         modify($s1){
>         setProcessed(true),
>         setPromoItemDiscount($s1.getPrice() * 0.1),
>         setPromoId("1"),
>         setBundleId(bundler.getId()),
>         setAggrigatorId(1)
>         };
>         modify($s2){
>         setProcessed(true),
>         setPromoItemDiscount($s2.getPrice() * 0.1),
>         setPromoId("1"),
>         setBundleId(bundler.getId()),
>         setAggrigatorId(1)
>         };
>         $m.addMessage("bundled ["+*bundler.getId()*+"]
> "+$s1.getId()+","+$s2.getId());
>         bundler.increment();
> end
>
> the above rule dosent fire, but if I change the highlighter to
> getProductId() == 219759, or use productId == "219759", may be this is some
> edge case but it took long time for me to figure it out productId is String.
> now consider the *bundler.getId()*, if I use *bundler.id* I get
> compilation error.
>
> Rule Compilation error : [Rule name='Apply 10% discount if you purchase 2
> items']
>
> com/example/promotions/promotionEngine/Rule_Apply_10__discount_if_you_purchase_2_items_0.java
> (23:1592) : The field Bundler.id is not visible
> 2011-09-09 13:18:39,863  INFO [STDOUT] - 2011-09-09 13:18:39,863  INFO
> [PromotionsManager] - ksession initialized
> 2011-09-09 13:18:39,863  INFO [STDOUT] - 2011-09-09 13:18:39,863  INFO
> [PromotionsManager] - Exploding items and inserting cart
> 2011-09-09 13:18:39,864  INFO [STDOUT] - 2011-09-09 13:18:39,863 ERROR
> [CheckOutBasedUtilities] - Failed to apply promo offers
> java.lang.RuntimeException: Unexpected global [bundler]
>     at
> org.drools.common.AbstractWorkingMemory.setGlobal(AbstractWorkingMemory.java:613)
>     at
> org.drools.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:332)
>     at
> com.example.promotions.promotionEngine.PromotionsManager.applyOffers(PromotionsManager.java:154)
>     at
> com.example.promotions.promotionEngine.PromotionsManager.shuffleForOffers(PromotionsManager.java:61)`
>
> lastly my actual problem that I am looking for a solution lets say we have
> "Buy X items of A and get Y Items of B". X=5 & Y=4 from the original problem
> I want to template the rule and load the values of X,A,Y,B from database or
> excel etc. if I use modify the error is as follows
>
> *my rule*
>
>
>
> rule "Buy X units of Product A and Get Y units of Product B Free"
>     when
>         $itemsX : ArrayList( size == 2 ) from collect( CartItem(
> getProductId() == 24257, !isProcessed()))
>         $itemsY : ArrayList( size == 1) from collect(CartItem(
> getProductId() == 24260, !isProcessed()))
>         $m : RuleMessage()
>  then
>          for(Object item : $itemsX){
>              CartItem ci = (CartItem) item;
>              $m.addMessage( ci.getId()+")Found item: "+ci.getItemId()+"
> name: "+ci.getName());
>              modify(ci){
>                 setProcessed(true),
>                 setPromoItemDiscount(0),
>
>                 setPromoId("2"),
>                 setBundleId(bundler.getId()),
>                 setAggrigatorId(1)
>             };
>          }
>          for(Object item : $itemsY){
>          CartItem ci = (CartItem) item;
>              $m.addMessage( ci.getId()+")Found item: "+ci.getItemId()+"
> name: "+ci.getName());
>              modify(ci){
>                 setProcessed(true),
>                 setPromoItemDiscount(ci.getPrice()),
>                 setPromoId("2"),
>                 setBundleId(bundler.getId()),
>                 setAggrigatorId(2)
>             };
>          }
>         bundler.increment();
> end
>
> Rule Compilation error : [Rule name='Buy X units of Product A and Get Y
> units of Product B Free']
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (11:1236) : The method setProcessed(boolean) is undefined for the type
> Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (12:1265) : The method setPromoItemDiscount(int) is undefined for the type
> Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (13:1299) : The method setPromoId(String) is undefined for the type Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (14:1325) : The method setBundleId(Integer) is undefined for the type Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (15:1364) : The method setAggrigatorId(int) is undefined for the type Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (22:1702) : The method setProcessed(boolean) is undefined for the type
> Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (23:1731) : The method setPromoItemDiscount(Double) is undefined for the
> type Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (24:1777) : The method setPromoId(String) is undefined for the type Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (25:1803) : The method setBundleId(Integer) is undefined for the type Object
>
> com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java
> (26:1842) : The method setAggrigatorId(int) is undefined for the type Object
>
> Rule Compilation error : [Rule name='Apply 10% discount if you purchase 2
> items']
>
> com/example/promotions/promotionEngine/Rule_Apply_10__discount_if_you_purchase_2_items_0.java
> (23:1592) : The field Bundler.id is not visible
>
>
>
> On Fri, Sep 9, 2011 at 12:40 PM, Sandeep Bandela <gibsosmat at gmail.com>wrote:
>
>> Hi Wolfgang,
>> This is what I did initially but for product > 2 I didnt find a generic
>> way to do this. following is my first rule. I didnt use field names because
>> it was giving error that member is not accessible. I will attach the errors
>> of each case in a few mins.
>>
>> rule "Apply 10% discount if you purchase 2 items"
>>     dialect "java"
>>     when
>>         $s1 : CartItem( getProductId() == 236061, !isProcessed())
>>         $s2 : CartItem( getProductId() == 236061, getId() != $s1.getId(),
>> !isProcessed())
>>         $m : RuleMessage()
>>  then
>>         $m.addMessage("Found item1: " + $s1.getName() + " id:
>> "+$s1.getId());
>>         $m.addMessage("Found item2: " + $s2.getName() + " id:
>> "+$s2.getId());
>>         modify($s1){
>>         setProcessed(true),
>>         setPromoItemDiscount($s1.getPrice() * 0.1),
>>         setPromoId("1"),
>>         setBundleId(bundler.getId()),
>>         setAggrigatorId(1)
>>         };
>>         modify($s2){
>>         setProcessed(true),
>>         setPromoItemDiscount($s2.getPrice() * 0.1),
>>         setPromoId("1"),
>>         setBundleId(bundler.getId()),
>>         setAggrigatorId(1)
>>         };
>>         bundler.increment();
>> end
>>
>>
>> 2011/9/9 Wolfgang Laun <wolfgang.laun at gmail.com>
>>
>>> Your rule exhibits procedural thinking. (For an aspiring rule programmer
>>> his is typical teething troubles.)
>>>
>>> There's no need to collect all A's and B's in order to determine their
>>> number being greater than one or two - this is achieved automatically by a
>>> simple triple match rule. Consider
>>>
>>> rule "2A - 1B"
>>> when
>>>    $a1: CartItem( productId == "A", processed == false )
>>>    $a2: CartItem( this != $a1, productId == "A", processed == false )
>>>    $b: CartItem( productId == "B", processed == false )
>>> then
>>>    modify( $a1 ){...}
>>>    modify( $a2 ){...}
>>>    modify( $b ){...}
>>> end
>>>
>>> Note:
>>>
>>>    - The modify is essential. (When you say "doesn't work", always
>>>    provide details.)
>>>    - Use the field name rather than the getter call - it improves
>>>    readability.
>>>    - I'm not sure whether 5.2.0 final handles boolean fields correctly -
>>>    IIRC, there were some issues. It's possible that CartItem(..., !processed)
>>>    works.
>>>
>>> -W
>>>
>>> 2011/9/8 Sandeep Bandela <gibsosmat at gmail.com>
>>>
>>>> Hi,
>>>> I am new to rules engine, after going through the examples shipped
>>>> (shopping.drl, petstore.drl)
>>>> I am trying to implement promotional discounting using drools 5.2.0
>>>> final, stateful session. assume cart has all the items that customer wants
>>>> to buy,
>>>> I am trying to bundle them together with the existing offers
>>>>
>>>> rule "Buy X units of Product A and Get Y units of Product B Free"
>>>>     dialect "java"
>>>> when
>>>>     $itemsA : ArrayList( size >= 2) from collect( CartItem(
>>>> getProductId() == "A", !isProcessed()))
>>>>     $itemsB : ArrayList( size >= 1) from collect( CartItem(
>>>> getProductId() == "B", !isProcessed()))
>>>> then
>>>>     // current scenario buy 2*A and get 1*B
>>>>     int x = 2;
>>>>     int y = 1;
>>>>     for(int i=0 ; i < x ; i++){
>>>>         CartItem $ci = (CartItem) $itemsA.get(i);
>>>>         // modify($ci){setProcessed(true) ... } dosent work
>>>>         $ci.setProcessed(true);
>>>>         $ci.setItemDiscount(0.0);
>>>>         $ci.setBundleId(bundler.getId());
>>>>     }
>>>>
>>>>     for(int i=0 ; i < y  ; i++){
>>>>         CartItem $ci = (CartItem) $itemsB.get(i);
>>>>         $ci.setProcessed(true);
>>>>         $ci.setItemDiscount($ci.getPrice());
>>>>         $ci.setBundleId(bundler.getId());
>>>>     }
>>>>     // global counter to identify bundled items
>>>>     bundler.increment();
>>>> end
>>>>
>>>> the above rule calculates only for 1 set of offer i.e first 2*A & 1*B
>>>> are considered, rest in the cart are not bundled.
>>>> if customer buys 4*A + 2*B it dosent consider it. am I missing anything?
>>>> is this the right way to do it?
>>>> any feedback is appreciated.
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Regards,
>>>> Sandeep Bandela.
>>>>
>>>>
>>>> _______________________________________________
>>>> rules-users mailing list
>>>> rules-users at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>>
>>>>
>>>
>>> _______________________________________________
>>> rules-users mailing list
>>> rules-users at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>
>>>
>>
>>
>> --
>> Regards,
>> Sandeep Bandela.
>>
>>
>
>
> --
> Regards,
> Sandeep Bandela.
>
>


-- 
Regards,
Sandeep Bandela.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20110909/6e04efe3/attachment.html 


More information about the rules-users mailing list