Last active
June 17, 2021 07:24
-
-
Save davidknipe/3c69253730b0872e2b5a79d6723f2d8d to your computer and use it in GitHub Desktop.
Custom promotion to allow unique coupon codes created in Episerver Campaign to be used in Episerver Commerce discounts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) { } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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