Working with promotions in Optimizely Commerce Cloud
A popular and commonly used promotion within Optimizely Commerce Cloud is the 3-for-2 promotion type.
"BuyQuantityGetFreeItems" - Buy at least X items, get the cheapest Y for free.
This could be configured across multiple lineitems or within several categories. Here is an example with 2 different skus:
If I create an order where I buy 2 of SKU 102326 and 1 of SKU 102383, the cheapest item gets price 0.
This is how the order looks in Commerce Manager
In terms of code the "free" item/sku can be retrieved in the following way
// fetching all active promotions on orderForm
foreach (var promotion in orderForm.Promotions)
{
var skuIds = promotion.Entries.Select(e => e.EntryCode).ToList();
}
The problem with price of zero
If you are sending the order to an ERP or OMS system it does not make sense to have an item with price 0.
This becomes more evident if you take returns into account - you don't want to get zero money back if you return the "free" item.
What you typically want to do is to distribute the discount amount among the 3 items you have bought.
I will not go into details on calculations, because different systems might have different rules, but I will show you how to retrieve the relevant data needed for the calculations.
First step is to retrieve all lineitems/skus affected by the campaign. This can be done by looking at the RewardDescription.
// retrieve orderForm rewardDescriptions
IEnumerable<RewardDescription> rewardDescriptions = orderForm.Promotions.Where(p => p.DiscountType != DiscountType.Shipping).ToList();
// on a reward use redemptions to get skuIds
var skuIds = new List<string>();
foreach (var redemption in reward.Redemptions)
{
var skus = redemption.AffectedEntries.PriceEntries.Select(e =>
e.ParentItem.Code).Distinct();
skuIds.AddRange(skus);
}
The code above would give us both line items part of the promotion/discount; SKU 102326 and SKU 102383.
In order to get details like number of discounted items and required buy amount you need to load promotion data and then check if the promotion is of the type we are looking for.
// retrieve original promotion data
var promotionData = _contentLoader.Get<PromotionData>(promotion.PromotionGuid);
if (promotionData is BuyQuantityGetFreeItems buyXGetYFreePromotion)
{
//Number of discounted items if required buy amount is fulfilled
var numberOfDiscountedItems =
(int)buyXGetYFreePromotion.Condition.PartiallyFulfilledThreshold;
//Required amount of items to buy to get a discount on additional items
var requiredBuyAmount = buyXGetYFreePromotion.Condition.RequiredQuantity
}
Here is an example of how the order above would look in an OMS and/or ERP system with discount evenly distributed based on original price.
79,90 is distributed with SKU 102326 has a discount of NOK 53.27 while SKU 102383 has a discount of NOK 26,63.
If the customer decides to return an item, and is entitled for a refund, the correct amount is refunded.