Always provide best possible item price from combination of discounts

Vote:
 

Hi

Say I have the following active discount types:

Line item discounts

  1. Buy Products for Discount on All Selections

    • Buy at least item: 1
    • From entries: Product A
    • At the follwing discount: 10 % off
  2. Buy Products for Discount on All Selections

    • Buy at least item: 1
    • From entries: Product B
    • At the follwing discount: 25 % off
  3. Buy Products for Discount on All Selections

    • Buy at least item: 1
    • From entries: Product C
    • At the follwing discount: 30 % off

With one of each products the cart now looks something like this:

Product Quantity Product placed price Percentage off and saved amount Product discount price Product Total
Product A 1 769 10 % - 76,9 692,1 692,1
Product B 1 1399 25 % - 349,75 1049,25 1049,25
Product C 1 999 30 % - 299,70 699,30 699,30

I also have another discount which gives 20 % off the entire order if the spent amount is more than 2000 including VAT:

Order discounts

  1. Spend for Discount on Order

    • Spend at least: 2000 (incl. VAT)
    • Get the follwing discount: 20 % off

Because I always want to provide the best (lowest) possible price I want the 10 % line item discount to be replaced with a 20 % off that item. The products which get 25 % and 30 % off should remain as their discounts are better than the 20 % provided by the order campaign.

I have tried a few different setups, but I am not able to fully acheive what I want:

  • If i leave the discounts as explained above and let the order discount have lower priority than the line item discounts, the order discount takes another 20 % off all the discounted products and any other products in the cart.
            Money orderDiscountTotal = _orderGroupCalculator.GetOrderDiscountTotal(cart);

 This is as expected as it returns the sum of all line items OrderDiscountValue, but it is not what I want.

  • If provide a line item discount of 20 % when spent amount is more than 2000 (incl. VAT) another 20 % is taken off all products. Even previously discounted ones. I have tried playing around with sorting order and exclusion rules, but no luck.
  • I have also tried finding the entries related to a given promotion, and checking the if the EntryDiscountValue is smaller than OrderDiscountValue.

If I do that, and set the EntryDiscountValue = OrderDiscountValue I sort of get what I want, but I'm unsure how this will affect any other cart totals retrievals down the line fx. when I create summary for order email etc.

Rough code from trying that out:

            foreach (ILineItem affectedLineItem in affectedLineItems)
            {
                var entryDiscountValue = affectedLineItem.GetEntryDiscountValue();
                var orderDiscountValue = affectedLineItem.GetOrderDiscountValue();

                if (entryDiscountValue < orderDiscountValue)
                {
                    decimal percentage = fulfilledOrderRewardDescriptions.FirstOrDefault().Percentage;
                    var result = affectedLineItem.PlacedPrice - (affectedLineItem.PlacedPrice - (affectedLineItem.PlacedPrice * percentage / 100));

                    cart.GetFirstForm().GetAllLineItems().FirstOrDefault(x => x.Code == affectedLineItem.Code).SetEntryDiscountValue(result);
                    _orderRepository.Save(cart);
                }

            }

Has anyone had to implement something similar to my use case? Or perhaps someone can point me towards are proper approach?

#206983
Edited, Sep 05, 2019 12:29
Vote:
 

"If provide a line item discount of 20 % when spent amount is more than 2000 (incl. VAT) another 20 % is taken off all products. Even previously discounted ones. I have tried playing around with sorting order and exclusion rules, but no luck."
- I believe this is the way to go. The sorting order has to be in falling percentage: Product C, Product B, Spend 2000, Product A. Also the Spend 2000 promotion has to excluded the other three.

What I am guessing you are missing is that you have to enforce entry level exclusion:

_promotionEngine.Run(cart, new PromotionEngineSettings { ExclusionLevel = ExclusionLevel.Unit });

The default is ExclusionLevel.Order. Unit was introduced a while back to support the use cases we at avensia had from our customers.

#207075
Sep 09, 2019 16:50
Toke Frostholm - Sep 10, 2019 13:35
I have now added the entry level exclusion.

The problem is that the line item discount of 20 % when spent amount is more than 2000, applies to the entire catalog.
So because Product C and Product B is part of that catalog, the spent amount discount will never get applied to the other items discounts because Spend 2000 excludes the other discounts which has higher priority. Actually it doesn't even get applied to items that have no specific line item discounts.

I have searched through the code and I now don't have any places where I run the promotion engine without ExclusionLevel.Unit.

I would have preferred to be able to use the built-in Spend Amount for Discount order discount, but it doesn't seem like that is possible.

Any ideas where I might be doing something wrong?
Vote:
 

Before you ask: No, there is no built-in way to avoid this behavior.

#207109
Sep 10, 2019 15:43
Toke Frostholm - Sep 11, 2019 8:40
Edit: Just removed the Accepted Answer check in case someone else has an idea on how to solve this.
Erik Norberg - Sep 11, 2019 15:53
I think the suggestion I got from episerver to get the wanted behavior would be to override the promotion engine. A custom promotion won't be enough, unfortunately. Of course with a custom promotion engine you will likely miss out on updates and bug fixes.
Toke Frostholm - Sep 11, 2019 19:00
I was thinking about overriding the promotion engine as well, but as we are currently running commerce 12.17 with an update to latest version in the pipeline, I don't want to embark on that journey right now :)
Vote:
 

Bummer. I appreciate your help though.

#207116
Sep 10, 2019 17:51
Erik Norberg - Sep 11, 2019 15:50
I did a bug report to episerver about this back in February, I still remember my disappointment when they said it was by design. :'(
Vote:
 

I took the time and wrote up a feature request:
https://world.episerver.com/forum/developer-forum/Feature-requests/Thread-Container/2019/9/spend-for-amount-promotion-with-unit-level-exclusion/
Please upvote it if you would like episerver to implement it. ^^

#207167
Sep 11, 2019 16:50
Vote:
 

Hi Toke,

I'm not sure I understand your scenario correctly and you still interest in this case.

If you just want discount for those items once time (I mean it will not apply combine with other promotion), then why did you setup an order level promotion? That 100% take a discount for whole order.

It should be Spend amount for items promotion type, which have a property like DiscountTarget. Then you can customize a little bit in the processor, to filter that all target items should not apply any promotion before.

/Tuan

#209491
Nov 15, 2019 10:09
Vote:
 

Hi, Tuan.

If we setup an order level promotion it will be multiplied with a line promotion and that is not what we want to. The question is that if it is possible to have such setup with promotions from the box. From the support team we get an advice to have something like that: 

cart.ApplyDiscounts(_promotionEngine, new PromotionEngineSettings
{
ExclusionLevel = ExclusionLevel.Unit,
RequestedStatuses = RequestFulfillmentStatus.Fulfilled
})

But seems like it does not change something.

So the biggest discount of the first item will be applied (order discount) but others will stay the same (line discounts). As i understand from your post it is not possible from the box to have such setup.

#210416
Edited, Nov 22, 2019 9:38
* 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.