Popular Posts

Promotion Engine

Parts of a promotion engine

There are 5 different parts of a promotion engine.

  •     The agenda builder
  •     The sequence builder
  •     Promotion events and listeners
  •     The promotion code manager
  •     The coupon manager

List of tables
   
PX_PROMOARGS: Contains historical information about all the promotions applied for an order
ORDPROMOCD: Records promotion codes entered for an order
PX_GROUP: Lists every promotion group available for a store
PX_POLICY: Lists all the available policies available for a store
PX_GRPPOLICY: Maps all the policies for a group
PX_PROMOTION: Contains all the informations related to a particular promotion
CLCDPROMO: Conatins the mapping b/w the CALCODE_ID and PROMOTION_ID
CATENCALCD: Promotion for a for catalog entry, relate CALCODE and CATENTRY.
CATGPCALCD: Promotion for a for catalog entry, relate CALCODE and CATGROUP.
CALCODEMGP: Promotion for a for catalog entry, relate CALCODE and MBRGRP.
SHPMODCLCD: Promotion for a for catalog entry, relate CALCODE and SHIPMODE.

Sample query to retrieve list of all valid OrderLevelPromotion

SELECT PX.CODE, PX.PX_PROMOTION_ID, PX.STARTDATE,PX.ENDDATE , PX.PRIORITY, PX.NAME, PX.PERORDLMT FROM PX_PROMOTION PX , PX_GROUP GRP
WHERE GRP.PX_GROUP_ID in (SELECT PX_GROUP_ID FROM PX_GROUP WHERE GRPNAME='OrderLevelPromotion' ) AND PX.CODE IS NULL AND GRP.PX_GROUP_ID = PX.PX_GROUP_ID AND PX.STOREENT_ID = 10151 AND PX.ENDDATE >= CURRENT_DATE AND PX.STATUS =1 ORDER BY PX.STARTDATE

Working of a Promotion Engine

When the promotion engine is called, it processes any promotions for the current order, and returns a PromotionArgument. The order subsystem is then responsible for interpreting the results (PromotionArgument) returned by the promotion engine and storing the results the respective order and order item adjustment tables. Due to limitations in the order subsystem, not all Adjustments are supported by the order subsystem. List of the Adjustments fully supported by the order subsystem are as follows:

  • FreePurchasableGiftAdjustment
  • FixedAmountOffAdjustment
  • FixedAmountOffPriceAdjustment
  • FixedAmountOffVolumeDiscountAdjustment
  • FixedCostAdjustment
  • FixedCostShippingAdjustment
  • PercentOffAdjustment
  • PercentOffPriceAdjustment
  • VoucherAdjustment
If an Adjustment type that is unsupported by the order subsystem is used, the order subsystem will simply ignore the Adjustment returned by the promotion engine. The author of this new adjustment type is then responsible for applying this adjustment when the promotion is finalized.


Customizing components of a promotion engine

The components of the promotion engine are configurable. These are specified in a configuration XML file called WCSPromotionEngineConfig.xml. The promotion engine is configured per WebSphere Commerce instance and it is not possible to have different configurations for stores in the same instance. The configuration file is present in the following path /WC_installdir/instances/instance_name/xml/PromotionEngineConfiguration/ directory.


How to evaluate promotion without user adding the item to cart ?


WCS OOB cannot evaluate order level promotions, without adding them to cart. This can be achieved using a workaround.
For catentry level promotions, OOB PromotionalPriceDataBean can be used.

The below are the 2 objects that the promotion engine acts upon.
  • com.ibm.commerce.marketing.promotion.integration.dependency.WCSOrder
  • com.ibm.commerce.marketing.promotion.integration.dependency.WCSOrderItem
Sample Code
WCSOrder order = null;
WCSOrderItem orderItem = null;
List orderItemList = null;

//Populate the OrderItemId, store, catentry information to the WCSOrderItem Object
orderItem.setKey(new OrderItemKey(new Long("1"));
orderItem.setStore(sKey);
orderItem.setCatalogEntry(catKey);
orderItem.setBaseCurrency(getCommandContext().getCurrency());
orderItem.setCurrency(getCommandContext().getCurrency());              
orderItem.setStandardPrice(100);
orderItem.setPrice(itemPrice);
orderItem.setQuantity(new BigDecimal(1));                                  
orderItem.setShippingCharge(new BigDecimal(10));
orderItem.setShippingCarrier("UPS");
orderItem.setShippingCode("Ground");
orderItemList.add(orderItem);
       
// Populate the WCSOrder Object with order related data
order.setKey(new OrderKey(new Long(this.ucOrderDataBean.getWCSorderId())));
order.setStoreId(this.storeId);
order.setCurrency(getCommandContext().getCurrency());
order.setOwner(getCommandContext().getUserId());
order.setLastUpdate(getCommandContext().getTimestamp());                       
order.setTotal(new BigDecimal(110);
 order.setTotalShippingCharge(new BigDecimal(10));
       
 // Populate the order Items information to the wcsOrder
OrderItem[] orderItems = new WCSOrderItem[this.orderItemList.size()];
orderItems = (WCSOrderItem[])this.orderItemList.toArray(orderItems);
order.setItems(orderItems);

DefaultAdvancedPromotionEngine defaultPromotionEngine = null;                        
                               
//Get the default promotion engine
PromotionEngine promotionEngine = PromotionEngineHome.getDefaultEngine();          
                               
if(promotionEngine instanceof DefaultAdvancedPromotionEngine){
    defaultPromotionEngine = (DefaultAdvancedPromotionEngine)promotionEngine;                                          
}
               
PromotionContext promotionContext = defaultPromotionEngine.createPromotionContext(this.order, getCommandContext(), "All Promotions", null, false);
promotionContext.getAgenda().setShippingChargePresent(true);
               
//Invoke the promotion context to apply the promotions to the order
 defaultPromotionEngine.invoke(promotionContext);
                    
//Get the promotion Arugement, which has the applied promotion details
this.promotionArgument = promotionContext.getArgument();

// Iterate over the list of promotion execution records returned by the promotion engine
Iterator aIterator = promoResult.getPromotionExecutionRecords();

while (aIterator.hasNext()) {
    PromotionExecutionRecord aPromotionExecutionRecord = (PromotionExecutionRecord)aIterator.next();
    if (16 == aPromotionExecutionRecord.getState()) {
        BigDecimal currentDiscount = aPromotionExecutionRecord.getMonetaryAdjustmentForOrder(1);
        LineItemSet[]  lineItemSets = aPromotionExecutionRecord.getAffectedItems();
        for(int i=0; i<lineItemSets.length; i++) {
            LineItemSet lineItemSet = lineItemSets[i];
            AssociatedOrderItem[] associatedOrderItems = lineItemSet.getAssociatedOrderItems();
            for(int j=0; j<associatedOrderItems.length; j++) {
                 //AssociatedOrderItem has the list of all order items and the promotions against them
                AssociatedOrderItem associatedOrderItem = associatedOrderItems[j];
            }
        }
    }
}  

7 comments: