It sounds like custom promotion is the wrong place to do the filter. Did you look into IEntryFilter instead?
Thanks for quick reply quan,
But we are filtering the lineitem based on our condition so it not fixed one.
which IEntryFilter you can do pretty much any filter with the lineitem based on your conditions.
Hi Karyan,
As I understand that PromotionEngine.Evaluate(contentLink...) just can evaluate promotions based on entries, market,currency. You cannot use this method to evaluate promotion based on line items.
The workaround you can use to do your bussiness is creating a appropriated memory order with your line items and using PromotionEngine.Run
Here is the example:
public IEnumerable<RewardDescription> GetEntryPromotions(EntryContentBase entry, decimal quantity, Money placedPrice, IMarket market, Currency marketCurrency)
{
return _promotionEngine.Run(CreateInMemoryOrderGroup(entry, quantity, placedPrice, market, marketCurrency)).Where(x => x.Promotion.DiscountType == DiscountType.LineItem);
}
private IOrderGroup CreateInMemoryOrderGroup(EntryContentBase entry, decimal quantity, Money placedPrice, IMarket market, Currency marketCurrency)
{
InMemoryOrderGroup memoryOrderGroup = new InMemoryOrderGroup(market, marketCurrency);
ICollection<ILineItem> lineItems = memoryOrderGroup.Forms.First().Shipments.First().LineItems;
InMemoryLineItem inMemoryLineItem = new InMemoryLineItem
{
Quantity = quantity,
Code = entry.Code,
PlacedPrice = placedPrice.Amount
};
lineItems.Add(inMemoryLineItem);
return memoryOrderGroup;
}
Hope this help!
Please provide any sample code to filter the line items using IEntryFilter.I do not find any sample codes.
Quan I forgot to mention one thing we are filtering line-item based on the line-item quantity (should be greater than promotion required quantity)
A custom promotion seem the right way to do it to me but i wonder how your evaluate method in the promotion processor looks, could you post the code?
My initial thought is that your processor should return FulfillmentStatus.PartiallyFulfilled if it is the right entry but not enough required quantity.
Then when loading the product page you evaluate using:
_promotionEngine.Evaluate(contentLink, market, currency, RequestFulfillmentStatus.Fulfilled | RequestFulfillmentStatus.PartiallyFulfilled)
protected override RewardDescription Evaluate(xxxEntryPromotion promotionData, PromotionProcessorContext context)
{
var condition = promotionData.Condition;
var filteredLineItems = GetFilteredLineItems(GetLineItems(context.OrderForm), condition.RequiredQuantity);
var applicableCodes = targetEvaluator.GetApplicableCodes(filteredLineItems, condition.Targets, condition.MatchRecursive);
var fulfillmentStatus = fulfillmentEvaluator.GetStatusForBuyQuantityPromotion(
applicableCodes,
filteredLineItems,
condition.RequiredQuantity,
condition.RequiredQuantity);
return RewardDescription.CreatePercentageReward(
fulfillmentStatus,
GetRedemptions(applicableCodes, promotionData, context, lineItems),
promotionData,
promotionData.Percentage,
fulfillmentStatus.GetRewardDescriptionText(localizationService));
}
----------------
protected override bool CanBeFulfilled(xxxEntryPromotion promotionData, PromotionProcessorContext context)
{
if (promotionData.Percentage <= 0)
{
return false;
}
var lineItems = GetLineItems(context.OrderForm);
if (!lineItems.Any())
{
return false;
}
return true;
}
--------------------
private IEnumerable<RedemptionDescription> GetRedemptions(IEnumerable<string> applicableCodes, xxxEntryPromotion promotionData, PromotionProcessorContext context, IEnumerable<ILineItem> lineItems)
{
var redemptions = new List<RedemptionDescription>();
var requiredQuantity = lineItems.Where(x => applicableCodes.Contains(x.Code)).Sum(l => l.Quantity);
var maxRedemptions = GetMaxRedemptions(promotionData.RedemptionLimits);
for (int i = 0; i < maxRedemptions; i++)
{
var affectedEntries = context.EntryPrices.ExtractEntries(applicableCodes, requiredQuantity, promotionData);
if (affectedEntries == null)
{
break;
}
redemptions.Add(CreateRedemptionDescription(affectedEntries));
}
return redemptions;
}
That's strange, the promotion would already disqualify line items that do not satisfy the condition. So if you have a "buy three of A get 10% off" promotion, and you only have 2 items of A in the cart, then the promotion would not apply. Or am I misunderstanding you?
You can also use this when Commerce 13 comes out https://world.episerver.com/blogs/Quan-Mai/Dates/2019/2/new-feature-in-commerce-13-exclude-catalog-items-per-promotion/ so basically you get the line item codes and the promotion data to decide which to filter
Quan,
We filtered the line based on the required quantity. Every line item should be greater than the required quantity.
Ex: buy 10 or more items get a discount on that item only.
item1 - 11qty,item2 - 4qty
Here item1 only will get a discount. (But default epi promotion both item will get discount)
So we filtered the line-item based on the required quantity.
var condition = promotionData.Condition;
var filteredLineItems = GetFilteredLineItems(GetLineItems(context.OrderForm), condition.RequiredQuantity);
var applicableCodes = targetEvaluator.GetApplicableCodes(filteredLineItems, condition.Targets, condition.MatchRecursive);
Should probably be replaced with something along these lines:
var condition = promotionData.Condition;
var applicableCodes = targetEvaluator.GetApplicableCodes(GetLineItems(context.OrderForm), condition.Targets, condition.MatchRecursive);
if(!applicableCodes.Any())
{
return new RewardDescription(FulfillmentStatus.NotFulfilled, ...);
}
if(!lineItems.Any(li => applicableCodes.Contains(li.Code) && li.Quantity >= condition.RequiredQuantity)
{
return new RewardDescription(FulfillmentStatus.PartiallyFulfilled, ...);
}
Or at the very least call the fulfillmentEvaluator before you filter the lineitems
Hi Team,
when I am trying to use evaluate method to display promotion detail in the product listing page.
My custom promotion logic: In my custom promotion filtered the line items based on the required quantity(line items should > than required qty)
My problem: I am using PromotionEngine.Evaluate(contentLink...) method to find the product has a promotion or not. But as per our custom logic promotion is not applied to the products.
So based on the OrderGroup type(cart, InMemoryOrderGroup) can I skip my filter?
Is this the right way to do or else any suggestions are welcome.