SaaS CMS has officially launched! Learn more now.

problem with promotionEngine.Evaluate() when using custom promotion.


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.

Feb 09, 2019 12:38

It sounds like custom promotion is the wrong place to do the filter. Did you look into IEntryFilter instead?

Feb 09, 2019 22:47

Thanks for quick reply quan,

But we are filtering the lineitem based on our condition so it not fixed one.

Feb 10, 2019 18:36

which IEntryFilter you can do pretty much any filter with the lineitem based on your conditions.

Feb 10, 2019 22:37

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
            return memoryOrderGroup;

Hope this help!

Feb 11, 2019 2:50

Thanks quan,Binh Nguyen I will try Ientryfilter.

Feb 11, 2019 4:04

Please provide any sample code to filter the line items using IEntryFilter.I do not find any sample codes.

Feb 11, 2019 5:17

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)

Feb 11, 2019 5:50

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)
Feb 11, 2019 16:34
        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(

            return RewardDescription.CreatePercentageReward(
                GetRedemptions(applicableCodes, promotionData, context, lineItems),

        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)
            return redemptions;
Feb 12, 2019 17:38

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 so basically you get the line item codes and the promotion data to decide which to filter 

Feb 13, 2019 9:29


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.

Edited, Feb 13, 2019 9:39

So a custom promotion, like @Erik said, would be your best bet

Feb 13, 2019 11:20

Thanks Quan,

How to escape from this problem(when using evaluate()),

Feb 13, 2019 15:12
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);
    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

Feb 13, 2019 16:22

Thanks Erik ,

Feb 15, 2019 9:42
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.