November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
I'm looking for a ways to do this, and fouhnd that you can add manual fromotion as described in this thread:
private static void AddDiscount( IOrderForm orderForm, string lineItemCode, decimal discountValue, string discountName) { var promotionInformation = new PromotionInformation { Name = discountName, Description = discountName, DiscountType = EPiServer.Commerce.Marketing.DiscountType.Manual, Entries = new List<PromotionInformationEntry> { new PromotionInformationEntry { EntryCode = lineItemCode, SavedAmount = discountValue } }, OrderForm = new PromotionInformationOrderForm { SavedAmount = 0 } }; orderForm.Promotions.Add(promotionInformation); }
However, this doesn't seem to do anything in version I use (9.24). What could be wrong?
Are you running _promotionEngine.Run after you've added your manual promotion to the orderform?
Currenly, I'm adding this inside PromotionProcessor as a workaround to have multiple discounts from one promotion. But it doesn't seem to work.
Or actually it seems that you need to run cart.ApplyDiscounts(). From what I can see, _promotionEngine.Run doesn't care about manual discounts in the orderForm.Promotions, but if you run cart.ApplyDiscounts() it will apply them as well.
cart.ApplyDiscounts() will in itself run _promotionEngine.Run and you can provide the PromotionEngineSettings to ApplyDiscounts as well.
Ah, no, then I see why it wouldn't work. PromotionInformation is just a describing class of a seemingly applied promotion. But if you want to add a manual promotion by first creating the PromotionInformation, you still need to actually do something to apply them. By themselves PromotionInformations do nothing.
Therefore I'm not sure you can actually set your manual PromotionInformation from inside a processor. Since the promotion engine runs the processor, you have gone beyond the point where it would take care of manual promotions. So it would never be applied price wise (to the discountedPrice on any lineitem, where the actual discount values are stored after being calculated by the whole promotion engine schbang).
The flow as I see it (haven't tested it, just theorizing):
So creating PromotionInformations outside of this flow won't impact the actual prices.
That seems wrong, because we wanted to use new promotion engine specifically to avoid such mess. It looked very promising until we stumbled upon this inability to apply multiple discounts.
Also, I looked at Episrever code and your solution also look as if it wont work. ApplyDiscounts look like this:
public static IEnumerable<RewardDescription> ApplyDiscounts(this IOrderGroup orderGroup, IPromotionEngine promotionEngine, PromotionEngineSettings settings) { return promotionEngine.Run(orderGroup, settings); }
Regards,
Ah, perhaps I'm actually talking about something that was implemented after 9.24 :(
ApplyDiscounts in 11.2 looks like this:
So I guess somewhere along the line of 9.24 to 11.2 manual discounts were implemented in the new promotion system. Or there is some other way of enabling/using it.
Yes, it seems to be different in the version I use. However, this still would be no help to me because I need this discount to be proceesed before some others.
Hi Joel
I tried the above logic by adding AddDiscount method to my Custom Promotion Processor, and then in the processor, i'm trying not to calculate discount, so that its only handled by ApplyDiscounts method. However, my items are getting double discounts. Plus, each refresh of the cart applies the double discounts again, until the total price on line item becomes 0.
Also, i've added logic in CanBefulfilled method to not apply discounts when condition product isn't in cart and that part works. But once i have it in cart and my discount applies, if i remove the condition item, the discount still stays. It shouldn't. How and where can i handle this if I'm using above ApplyDiscounts logic?
Hi,
Which ApplyDiscounts logic are you talking about? ApplyDiscounts is just an extension method to IOrderGroup that will run _promotionEngine.Run().
What I'm saying in the above answer is that the use case Giedrius is talking about cannot be solved with Manual Promotions. And in order to run manual promotions you need to run cart.ApplyDiscounts instead of _promotionEngine.Run because it's in that method it will take into consideration the manual promotions existing on the orderform :)
I'm not sure where the problems you're having are originating, it would help if you pasted your processor code here so I can take a look at what you are doing.
Hi Joel
What I implemented is the AddDiscount method posted by Giedrius, in my processor logic, so i can set different promotion for different line item on the OrderForm.Promotions, as manual DiscountType. Once i've done this for all my reward scenarios, i still have to return a RewardDescription object on the Evaluate method. There, i'm not passing any redemptions or discount amount to calculate discounts in the processor. The only useful thing i'm returning in RewardDescription is the FulfillmentStatus.Fulfilled. After doing so, the extension method ApplyDiscounts automatically pulls those promotions and applies them to cart, which works for my requirement. But, i have some issues with the way its working:
This si my processor logic :
protected override RewardDescription Evaluate(MultipleDiscountPromotion promotionData, PromotionProcessorContext context) { //first reward var condition1 = promotionData.Reward1.PromoItems; SetupPerReward(condition1, "Reward1", promotionData, context, promotionData.Reward1); //second reward var condition2 = promotionData.Reward2.PromoItems; SetupPerReward(condition2, "Reward2", promotionData, context, promotionData.Reward2); //third reward var condition3 = promotionData.Reward3.PromoItems; SetupPerReward(condition3, "Reward3", promotionData, context, promotionData.Reward3); var reward = this.CreateRewardDescription(promotionData, null, FulfillmentStatus.Fulfilled); return reward; } private void SetupPerReward(IList<ContentReference> targetItems, string rewardName, MultipleDiscountPromotion promotionData, PromotionProcessorContext context, CustomRewardBlock reward) { IOrderForm orderForm = context.OrderForm; var lineItems = GetLineItems(orderForm); var condition = targetItems; var applicableCodes = _targetEvaluator.GetApplicableCodes(lineItems, condition, true); var affectedEntries = context.EntryPrices.ExtractEntries(applicableCodes, lineItems.Sum(l => l.Quantity) + 1); IEnumerable<RedemptionDescription> redemptions = this.GetRedemptions(applicableCodes, promotionData, context); foreach (var redemption in redemptions) { foreach (var item in redemption.AffectedEntries.PriceEntries) { string lineItemCode = item.ParentItem.Code; decimal price = item.Price; decimal discount = item.Price * (reward.Discount / 100); AddDiscount(orderForm, lineItemCode, discount, rewardName); } } }
private void AddDiscount(IOrderForm orderForm, string lineItemCode, decimal discountValue, string discountName) { bool IsNewPromo = true; foreach(var promo in orderForm.Promotions) { if (promo.Name.Equals(discountName)) { IsNewPromo = false; break; } } if (IsNewPromo) { var promotionInformation = new PromotionInformation { Name = discountName, Description = discountName, DiscountType = DiscountType.Manual, Entries = new List<PromotionInformationEntry> { new PromotionInformationEntry { EntryCode = lineItemCode, SavedAmount = discountValue } }, OrderForm = new PromotionInformationOrderForm { SavedAmount = 0 }, IsRedeemed = true }; orderForm.Promotions.Add(promotionInformation); } }
protected override bool CanBeFulfilled(MultipleDiscountPromotion promotionData, PromotionProcessorContext context) { if (promotionData.Reward1.Discount <= 0 && promotionData.Reward2.Discount <= 0 && promotionData.Reward3.Discount <= 0) { return false; } IOrderForm orderForm = context.OrderForm; var lineItems = GetLineItems(orderForm); var conditionItems = promotionData.ConditionItems; var applicableCodes = _targetEvaluator.GetApplicableCodes(lineItems, conditionItems, true); if(applicableCodes.Count <= 0) { return false; } if (!lineItems.Any()) { return false; } return true; }
Hey,
So my response would be quite long, I recorded it instead :D
I fucked up the sound a bit, so it's very low. So up the volume and enable subtitles!
https://www.youtube.com/watch?v=bBXowqDZrGA
Hi Joel
I understand what you tried to explain, but the code that I shared actually does apply discounts in the cart. It shows saved amount next to each line item. the only issue i have is it doubles the saved amount than what it actually should be, and every postback keeps adding that double discount to each line item. My understanding is this happens because of the no. of time the Evaluate method is called by the PromotionEngine.. and it seems like multiple times, because when i put a breakpoint on the Evaluate method, it gets hit atleast 3 times on one postback. If this is true to how this functions, why is that?
And maybe i might have to jump back to my original post, because ultimately my goal is to be able to return multiple reward descriptions, pertaining to different line items and i don't see such an option on PromotionProcessor. There is however a bunch of overloaded Evaluate methods on IPromotionEngine interface, that return an IEnumerable<RewardDescription>. Is there a way to override these, so we can add the custom logic for multiple rewards in single promotion inside it? If so, how and where can we do that?
Interesting. I would be interested to see why it actually works... But regardless, Evaluate will be called once per promotion that can be applied. Do you maybe have several of that custom promotion set up?
If no, could you print screen the stack trace for each of the 3 times you hit Evaluate in that custom promotion?
Hello,
I need to have different discounts applied to lineitems based on various rules. However, it seems that promotion processor allows only one reward description to be created. Is there any provisions to have multiple?
For example, I want lineItem1 to get 10% discount and lineitem2 to get 20% percent discount.
I cannot use multiple promotion processors, because these percentages are dynamic.
What is the best way to do this?
Regards,