Hi! when a user adds something to the cart and the cart is calculated, I need a way to get the ids of all campaigns that are now active for this current user.
Am guessing litium caches all the campaign conditions a user/session meets? So it knows whats prices to render in the lists. Can I somehow access that?
ps: I need all the campaigns that now applies/affect this user, not just the one currently in the cart.
CampaignEngine calculates the campaign price each time a product price is shown. It is not cached in user session since the user, product or the shopping cart total can meet the conditions depending on the users behaviour on the site. Why do you want to have the campaigns that can affect the user?
All campaigns with all the conditions is cached global, not per user. For each execution the condition for the campaign are evaluated, for campaigns that passing all condition the action will be applied. Campaign prices are not cached, they are calculated when needed.
“For each execution the condition for the campaign are evaluated, for campaigns that passing all condition the action will be applied.”
Can I somehow decorated that method? Whenever a price is calkulated and all conditions are passed, I want to add that campaigns I’d to the user session.
No, it’s not possible to do that on an easy way, you can always implement your own ICampaignProcessor that will do all this work. When the campaign engine are executed all campaigns condition is not even evaluated depend on how the campaigns can be combined or if the campaign cant be combined with any other campaigns.
I haven’t try myself to get all campaigns that is active and may affect the users prices on this way. If we using the ICampaignHandler we can get all campaigns that are active for the current execution (all active campaigns), but that is not the same as the campaigns that may affect the prices for the user. Each campaign have conditions that will be evaluated that is a combination of conditions created from the campaign action and the campaign conditions. If you have a Reduce price for product X, the Cart contains product X will be added as a condition. It is possible to build up an own service that will use the information from ICampaignHandler and by itself looping over all campaigns and processing all the conditions that is relevant, example skipping the Cart contains product X condition, to get a list with all campaigns that may have impact on the price.
Ok, if I switch approach then. What whould be the prefered point of attack to make it so that only campaigns that are active for everyone (eg only have a date-range/list condition) alter the price in the list and product views. Campaigns with more komplex condition should only affect the price in the cart/checkout.
So lets say we have a campaign buy two and get 20% off, the price adjustment that whould be displayed in the listings after adding the first one to the cart should only be reflected in the cart/checkout, and not anyware else.
Something like this I think will work, code is not verified that it return correct information for your use case and additional error handling logic may be needed.
using System;
using System.Collections.Generic;
using System.Linq;
using Litium.Foundation.Modules.ECommerce.Plugins.Campaigns;
using Litium.Foundation.Modules.ECommerce.ShoppingCarts;
using Litium.Web.Routing;
namespace Litium.Accelerator.Mvc.App_Start
{
public class ActiveCampaignService
{
private readonly RouteRequestLookupInfoAccessor _routeRequestLookupInfoAccessor;
private readonly CartAccessor _cartAccessor;
private readonly ICampaignHandler _campaignHandler;
private readonly HashSet<Type> _removeCampaignWithCondition = new HashSet<Type>(new[] {
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.ArticleCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.ArticleQuantityCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.AssortmentCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.OrderTotalCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.ProductGroupCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.ProductSetCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.UserBelongsToGroupCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.UserBelongsToOrganizationCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.UserBelongsToTargetGroupCondition),
typeof(Foundation.Modules.ECommerce.Plugins.Campaigns.Conditions.VoucherCodeCondition),
});
public ActiveCampaignService(
RouteRequestLookupInfoAccessor routeRequestLookupInfoAccessor,
CartAccessor cartAccessor,
ICampaignHandler campaignHandler)
{
_routeRequestLookupInfoAccessor = routeRequestLookupInfoAccessor;
_cartAccessor = cartAccessor;
_campaignHandler = campaignHandler;
}
public IEnumerable<Guid> GetUserCampaigns()
{
RouteRequestLookupInfo info = _routeRequestLookupInfoAccessor.RouteRequestLookupInfo;
if (info is null)
{
return Enumerable.Empty<Guid>();
}
DateTime dte = DateTime.Now;
Guid currencySystemId = _cartAccessor.Cart.OrderCarrier.CurrencyID;
return _campaignHandler.GetCampaigns(new CampaignHandlerArgs
{
ChannelId = info.Channel.SystemId,
OnlyProductCampaigns = true,
OrderContainsCampaignInfo = false
})
.Where(x =>
x.StartDate < dte
&& x.EndDate > dte
&& x.CurrencyId == currencySystemId
&& x.OrderedConditions.All(z => !_removeCampaignWithCondition.Contains(z.Condition.GetType())))
.Select(x => x.CampaignID);
}
}
}