World is now on Opti ID! Learn more

Remove variant from Reward.Items if out of stock

Vote:
 

HI!

I would like to rmove a variant from a promotion reward when it goes out of stock but the reward collection is read-only.

I would like to do something liek this:

var promotions = promotionEngine.Service.GetPromotionItemsForCampaign(campaign.ContentLink);
foreach (var promotionData in promotions.Where(p => p.Promotion.IsActive))
{
    if (promotionData.Reward.Items.Contains(new EPiServer.Core.ContentReference(1234)))
    {
        promotionData.Reward.Items.Remove(new EPiServer.Core.ContentReference(1234))
    }
}

Is this doable?

Thanks!

/Kristoffer

#337257
Mar 19, 2025 13:40
Vote:
 

You can, in theory, do something like this

var targetItems = new CatalogItemSelection(promotionItems.Reward.Items.Except(outOfStockItems), promotionItems.Reward.Type, promotionItems.Reward.IncludesSubcategories);
return new PromotionItems(promotionItems.Promotion, promotionItems.Condition, targetItems);

I am not sure what you are using the PromotionItems for so no further comment. but you can (and have to) reconstruct the object 

#337412
Mar 20, 2025 8:25
Vote:
 

Thanks, I would like to remove from the saved content, something like this:

var promotionItems = _promotionProcessor.Service.GetPromotionItems(promotionData);

var clone = (PromotionData) promotionData.CreateWritableClone();
var targetItems = new CatalogItemSelection(promotionItems.Reward.Items.Except(outOfStockItems), 
    promotionItems.Reward.Type, 
    promotionItems.Reward.IncludesSubcategories);

clone.? //TargetItems
_contentRepository.Service.Save(clone);

Is that doable? 

I guess I could use:

clone.ExcludedItems.Add(variantLink);

Which probably is the best, then it will work even if it is a product in the rewards.

#337416
Edited, Mar 20, 2025 10:17
Vote:
 

It seems you have to update promotionData.Condition.Items, but it depends on the actual promotion content type. Condition is a block of type PurchaseQuantity which available on several built in promotions, but not all 

#337417
Mar 20, 2025 10:32
Vote:
 

I could not find Condtion on the PromotionData, but this code actually worked just fine:

var variantLink = _referenceConverter.Service.GetContentLink(lineItem.Code);
if (promotionData.ExcludedCatalogItems == null || !promotionData.ExcludedCatalogItems.Contains(variantLink))
{
    var clone = (PromotionData)promotionData.CreateWritableClone();
    if (clone.ExcludedCatalogItems == null)
    {
        clone.ExcludedCatalogItems = new List<ContentReference>();
    }

    clone.ExcludedCatalogItems.Add(variantLink);
    _contentRepository.Service.Publish(clone, EPiServer.Security.AccessLevel.NoAccess);
}

Even though Items and ExcludedItems will contain the same variant in this case, the result is what I wanted.

/Kristoffer

#337418
Mar 20, 2025 10:55
Vote:
 

You need to cast the PromotionData to specific types that have Condition property - it's not available on the base type.

using ExcludedCatalogItems is a bit hacky as it should be used for things you want to exclude from discount. Like Gift cards etc.

Another approach is to implement IEntryFilter (easiest = inherit from EntryFilter), and filter out out of stock items. That means you won't have to care about updating your promotions dynamically 

#337419
Mar 20, 2025 11:09
Vote:
 

Agree, a bit hacky it is.

Thanks, I think I will solve it on some way from here.

#337420
Mar 20, 2025 12:18
Vote:
 

Hmm, what should I cast it to? Condition seems to be at the PromotionItems and not the PromotionData?

#337422
Mar 20, 2025 12:35
Vote:
 

You need to cast it to BuyQuantityGetFreeItems, BuyQuantityGetOrderDiscount, BuyQuantityGetSelectedItemsDiscount etc. Unfortunately there is no universal interface to cast to. With that said, IEntryFilter is a more general approach 

#337424
Mar 20, 2025 13:07
Vote:
 

Thanks Quan, really appriciated with all the input.

#337425
Mar 20, 2025 13:21
Vote:
 

Implemenation, at this moment:

var buyQuantityGetFreeItems = promotionData as BuyQuantityGetFreeItems;
if (buyQuantityGetFreeItems != null)
{
    var clone = (BuyQuantityGetFreeItems)buyQuantityGetFreeItems.CreateWritableClone();
    clone.Condition.Items.Remove(variantLink);
    _contentRepository.Service.Save(clone, SaveAction.Publish | SaveAction.SkipValidation, EPiServer.Security.AccessLevel.NoAccess);
}

#337426
Mar 20, 2025 13:54
Vote:
 

Implemenation, at this moment:

var buyQuantityGetFreeItems = promotionData as BuyQuantityGetFreeItems;
if (buyQuantityGetFreeItems != null)
{
    var clone = (BuyQuantityGetFreeItems)buyQuantityGetFreeItems.CreateWritableClone();
    clone.Condition.Items.Remove(variantLink);
    _contentRepository.Service.Save(clone, SaveAction.Publish | SaveAction.SkipValidation, EPiServer.Security.AccessLevel.NoAccess);
}

#337427
Mar 20, 2025 13:54
* 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.