Is it possible to restrict promotions so that you can only have one per entry? For example, if you have a active promotion for on specific entry, and tries to add another one that affects that entry. This should not be possible to do.
There are two concepts regarding limiting promotions:
- First one is the redemption count. You can make sure that only one entry is applied in each promotion
- Second one is exclusion. You can make a promotion excludes other promotions, or all of them (i.e. if this promotion is applied then all other promotion will be excluded, and vice versa, if any other promotion is already applied then this promotion will not be applied)
Those two are available out of the box. Another quite common scenario is that only most benefial promotion will be applied. Such requirement will need custom implementation.
There's no built in way to do this that covers all cases.On entry promotions which make use of the "DiscountItems"-block you can choose how many times a discount can be applied for that specific instance of the promotion. If you put this limit to 1 only one item from the list can get a discount, even if the customer has two different ones from the list.There's also an option to exclude promotions from being able to be applied together. Whenever you create an entry promotion you can add all other entry promotions to the list of promotions that this new one can't be combined with. This is of course very tedious and prone to user error depending on how many promotions you intend to have active at the same time.
Regarding a custom implementation route you could go with is to setup the IoC to use your own Processors for each entry promotion, where you ensure that an entry can only be an AffectedItem once. I've written up an example below, but note that I haven't tested this approach and it is only theorycrafting on my part:
[ServiceConfiguration(typeof(BuyQuantityGetItemDiscountProcessor), Lifecycle = ServiceInstanceScope.Singleton)]
public class MyBuyQuantityGetItemDiscountProcessor : BuyQuantityGetItemDiscountProcessor
public MyBuyQuantityGetItemDiscountProcessor(FulfillmentEvaluator fulfillmentEvaluator, LocalizationService localizationService)
: base(fulfillmentEvaluator, localizationService)
protected override RewardDescription Evaluate(BuyQuantityGetItemDiscount promotionData, PromotionProcessorContext context)
var description = base.Evaluate(promotionData, context);
// Check which entries were affected
// Check context if an affected entry has a discount already, if so remove it from affectedentries in the description
// Return the description, or a failed description if no entries are left.
Note that this approach applies discounts based on sort order, so only the first promotion applied will be the final discount. Even if a better one might come later in the sort order, additional custom logic would be needed to account for this.
Epi exclusion is based on the order. Not for line item.
Jafet idea worked for me.
We already added support for unit level exclusion in Commerce 11.3 : https://world.episerver.com/documentation/developer-guides/commerce/marketing/promotion-exclusions/