Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Custom promotion to allow unique coupon codes created in Episerver Campaign to be used in Episerver Commerce discounts
using System;
using System.Collections.Generic;
using System.Linq;
using Campaign.CouponServices.Interfaces;
using EPiServer.Commerce.Marketing;
using EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Discount;
using EPiServer.Security;
using Mediachase.Commerce.Security;
namespace EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.CouponFilter
{
/// <summary>
/// Used to filter out promotions that use Episerver Campaign to issue coupon codes
/// </summary>
public class CampaignCouponFilter : ICouponFilter
{
private readonly ICampaignCoupons _campaignCoupons;
public CampaignCouponFilter(ICampaignCoupons campaignCoupons)
{
_campaignCoupons = campaignCoupons;
}
public PromotionFilterContext Filter(PromotionFilterContext filterContext, IEnumerable<string> couponCodes)
{
var codes = couponCodes.ToList();
var userEmail = PrincipalInfo.CurrentPrincipal?.GetCustomerContact()?.Email;
foreach (var includedPromotion in filterContext.IncludedPromotions)
{
// Check if this is the right promotion type, if not ignore
var couponDrivenDiscount = includedPromotion as ICampaignCouponDiscount;
if (couponDrivenDiscount == null) continue;
// If we don't have any codes to check or the users email then unique
// coupon code promotion types are not valid so exclude them
if (!codes.Any() || string.IsNullOrEmpty(userEmail))
{
filterContext.ExcludePromotion(includedPromotion, FulfillmentStatus.CouponCodeRequired,
filterContext.RequestedStatuses.HasFlag(RequestFulfillmentStatus.NotFulfilled));
continue;
}
long couponBlockId;
if (long.TryParse(couponDrivenDiscount.CouponType, out couponBlockId))
{
foreach (var couponCode in codes)
{
// Check if the code its assigned to the user and that has not been used
if (_campaignCoupons.IsCouponAssigned(userEmail, couponBlockId, couponCode) &&
_campaignCoupons.IsCouponUsed(couponBlockId, couponCode) == false)
{
// The code hasn't been used and is assigned to the user so we can
// allow this to be connected to the promotion for this user
filterContext.AddCouponCode(includedPromotion.ContentGuid, couponCode);
}
else
{
// Exclude this promotion as its been used and/or it isn't assigned to the user
filterContext.ExcludePromotion(includedPromotion, FulfillmentStatus.CouponCodeRequired,
filterContext.RequestedStatuses.HasFlag(RequestFulfillmentStatus.NotFulfilled));
}
}
}
}
return filterContext;
}
protected virtual IEqualityComparer<string> GetCodeEqualityComparer()
{
return StringComparer.OrdinalIgnoreCase;
}
}
}
using System.Collections.Generic;
using Campaign.CouponServices.Interfaces;
using EPiServer.ServiceLocation;
using EPiServer.Shell.ObjectEditing;
namespace EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Discount
{
public class CouponCodeTypesSelectionFactory : ISelectionFactory
{
private readonly ICampaignCouponDefinition _campaignCouponDefinition;
public CouponCodeTypesSelectionFactory()
{
_campaignCouponDefinition = ServiceLocator.Current.GetInstance<ICampaignCouponDefinition>();
}
public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
{
var allCouponDefinitions = _campaignCouponDefinition.GetAllCouponDefinitions();
var couponItems = new List<ISelectItem>();
foreach (var couponDefinition in allCouponDefinitions)
{
couponItems.Add(new SelectItem()
{
Text = couponDefinition.CouponName + " (" + couponDefinition.CouponSource + ")",
Value = couponDefinition.CouponId
});
}
return couponItems;
}
}
}
using System.Collections.Generic;
using Campaign.CouponServices.Interfaces;
using EPiServer.Commerce.Marketing;
using EPiServer.Core;
using EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Discount;
namespace EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Reporting
{
public class CouponUsageImpl : ICouponUsage
{
private readonly ICampaignCoupons _campaignCoupons;
private readonly IContentRepository _contentRepository;
public CouponUsageImpl(IContentRepository contentRepository, ICampaignCoupons campaignCoupons)
{
_contentRepository = contentRepository;
_campaignCoupons = campaignCoupons;
}
public void Report(IEnumerable<PromotionInformation> appliedPromotions)
{
// This method allows us to report couple usage so we
// will look for all promotions with a coupon applied
foreach (var promotion in appliedPromotions)
{
var content = _contentRepository.Get<IContent>(promotion.PromotionGuid);
var promotionData = content as SpendAmountGetOrderDiscountWithCoupon;
long couponTypeId;
if (promotionData == null || long.TryParse(promotionData.CouponType, out couponTypeId) == false) return;
// Safe to mark the coupon as used
_campaignCoupons.MarkCouponAsUsed(couponTypeId, promotion.CouponCode);
}
}
}
}
namespace EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Discount
{
/// <summary>
/// Used to identify promotion types that use coupons issued by Episerver Campaign
/// </summary>
public interface ICampaignCouponDiscount
{
string CouponType { get; set; }
}
}
using EPiServer.Commerce.Marketing;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.CouponFilter;
using EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Reporting;
using EPiServer.ServiceLocation;
using EPiServer.ServiceLocation.Compatibility;
namespace EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Init
{
[InitializableModule]
[ModuleDependency(typeof(ServiceContainerInitialization))]
[ModuleDependency(typeof(EPiServer.Commerce.Initialization.InitializationModule))]
public class RegisterImplementations : IConfigurableModule
{
public void ConfigureContainer(ServiceConfigurationContext context)
{
// Coupon filter for discounts using unique coupon codes from Campaign
//context.Services.AddSingleton<ICouponFilter, CampaignCouponFilter>();
context.Services.Configure(
c =>
{
c.For<ICouponFilter>().Use<CampaignCouponFilter>();
});
context.Services.Configure(
c =>
{
c.For<ICouponUsage>().Use<CouponUsageImpl>();
});
}
public void Initialize(InitializationEngine context) { }
public void Uninitialize(InitializationEngine context) { }
}
}
using System.ComponentModel.DataAnnotations;
using EPiServer.Commerce.Marketing;
using EPiServer.Commerce.Marketing.DataAnnotations;
using EPiServer.Commerce.Marketing.Promotions;
using EPiServer.DataAnnotations;
using EPiServer.Shell.ObjectEditing;
namespace EPiServer.Reference.Commerce.Site.Features.CampaignCoupons.Discount
{
[ContentType(GUID = "F6B2B6EC-AA3F-415D-8802-C3FE18DA74A8"
, DisplayName = "Get a discount using a unique coupon code created by Episerver Campaign"
, Description = "Used to give discounts for individual coupon codes that have been sent to the user by Episerver Campaign")]
[AvailableContentTypes(Include = new[] {typeof(PromotionData)})]
[ImageUrl("~/Features/CampaignCoupons/campaign.png")]
public class SpendAmountGetOrderDiscountWithCoupon : SpendAmountGetOrderDiscount, ICampaignCouponDiscount
{
// Hide the default coupon code
[ScaffoldColumn(false)]
public override CouponData Coupon { get; set; }
[PromotionRegion(PromotionRegionName.Condition)]
[SelectOne(SelectionFactoryType = typeof(CouponCodeTypesSelectionFactory))]
[Display(
Order = 1,
Name = "Coupon of this type has been sent to the user")]
public virtual string CouponType { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.