public override IDiscountResult ApplyPromotion(IPromotionUsage promotionUsage, IRuleContext ruleContext, IDiscountContext discountContext, Func <IDiscountResult> resultFactory) { IDiscountResult retVal = resultFactory(); retVal.DiscountType = this.DiscountType; retVal.SequenceType = (PromotionSequence)SequenceNumber; switch (DiscountType) { case DiscountType.Fixed: retVal.OrderTotal = -this.DiscountAmount; break; case DiscountType.Percentage: retVal.OrderTotal = -discountContext.OrderTotal * this.DiscountAmount; break; } if (discountContext.OrderTotal + retVal.OrderTotal < 0) { retVal.OrderTotal = discountContext.OrderTotal * -1; } return(retVal); }
public IDiscountResult ApplyPromotion(IPromotionUsage promotionUsage, IRuleContext ruleContext, IDiscountContext discountContext, Func <IDiscountResult> resultFactory, IPromotionController promotionController) { if (!ValidatePromotion(promotionUsage.Promotion, ruleContext, true).All(vr => vr.IsValid)) { return(null); } IDiscountResult retVal = resultFactory(); retVal.Promotion = promotionUsage.Promotion; List <DiscountedItem> discountedItems = new List <DiscountedItem>(); foreach (IPromotionDiscount promotionDiscount in promotionUsage.Promotion.PromotionDiscounts) { IDiscountResult result = promotionDiscount.ApplyPromotion(promotionUsage, ruleContext, discountContext, resultFactory); if (result.DiscountedItems != null) { discountedItems.AddRange(result.DiscountedItems); } retVal.LineItemTotal += result.LineItemTotal; retVal.ShippingTotal += result.ShippingTotal; retVal.OrderTotal += result.OrderTotal; retVal.GiftProductTotal += result.GiftProductTotal; } retVal.DiscountedItems = discountedItems; return(retVal); }
public override IDiscountResult ApplyPromotion(IPromotionUsage promotionUsage, IRuleContext ruleContext, IDiscountContext discountContext, Func <IDiscountResult> resultFactory) { IDiscountResult retVal = resultFactory(); retVal.DiscountType = this.DiscountType; retVal.SequenceType = (PromotionSequence)SequenceNumber; List <DiscountedItem> discountedItems = new List <DiscountedItem>(); Decimal lineItemTotal = decimal.Zero; foreach (DiscountableItem item in discountContext.DiscountableItems) { DiscountedItem discountedItem = new DiscountedItem(); discountedItem.CartPrice = item.CartPrice; discountedItem.IsAGift = false; discountedItem.ProductId = item.ProductId; discountedItem.Quantity = item.Quantity; discountedItem.ShoppingCartRecordId = item.ShoppingCartRecordId; discountedItem.Sku = item.Sku; discountedItem.Subtotal = item.Subtotal; discountedItem.VariantId = item.VariantId; discountedItem.DiscountPercentage = decimal.Zero; discountedItem.DiscountType = this.DiscountType; discountedItem.PromotionUsage = promotionUsage; switch (DiscountType) { case DiscountType.Fixed: Decimal maximumDiscount = this.DiscountAmount; if (this.DiscountAmount > discountedItem.CartPrice) { maximumDiscount = discountedItem.CartPrice; } Decimal fixedDiscount = -(maximumDiscount) * item.Quantity; lineItemTotal += fixedDiscount; discountedItem.DiscountAmount = fixedDiscount; break; case DiscountType.Percentage: Decimal percentDiscount = -item.Subtotal * this.DiscountAmount; lineItemTotal += percentDiscount; discountedItem.DiscountAmount = percentDiscount; discountedItem.DiscountPercentage = this.DiscountAmount; break; } Data.ContextController.TrackLineItemDiscount(discountedItem); discountedItems.Add(discountedItem); } retVal.LineItemTotal = lineItemTotal; retVal.DiscountedItems = discountedItems; return(retVal); }
public static IList <IDiscountResult> GetDiscountResultList(IRuleContext ruleContext) { IList <IDiscountResult> discountResults = new List <IDiscountResult>(); if (IsValidCartType(ruleContext)) { return(discountResults); } IDiscountResult discountResult = GetPromotionDiscount(ruleContext, out discountResults); return(discountResults); }
public IDiscountResult CombineShippingDiscounts(IEnumerable <IDiscountResult> discounts, Func <IDiscountResult> resultFactory) { IDiscountResult result = resultFactory(); if (discounts.Where(d => d.ShippingTotal < 0).Count() > 0) { decimal minShippingTotalPriority = 0; if (discounts.Where(d => d.ShippingTotal < 0 && d.Promotion.Priority != 0).Any()) { minShippingTotalPriority = discounts.Where(d => d.ShippingTotal < 0 && d.Promotion.Priority != 0).Min(d => d.Promotion.Priority); } result.ShippingTotal = discounts.Where(d => d.Promotion.Priority == minShippingTotalPriority || d.Promotion.Priority == 0).Sum(d => d.ShippingTotal); } return(result); }
public static decimal GetFinalDiscount(IDiscountResult discountResult, decimal cartTotal) { decimal finalDiscount = decimal.Zero; decimal currentDiscount = discountResult.TotalDiscount * -1; if (currentDiscount > cartTotal) { finalDiscount = cartTotal; } else { finalDiscount = currentDiscount; } return(finalDiscount * -1); }
public static IDiscountResult GetPromotionDiscount(IRuleContext ruleContext, out IList <IDiscountResult> discountResults) { PromotionController promotionController = CreatePromotionController(); discountResults = new List <IDiscountResult>(); IQueryable <PromotionsData.PromotionUsage> promotionUsages = GetPromotionUsagesByCustomer(ruleContext.CustomerId).Where(p => p.Complete == false); Dictionary <IPromotionUsage, IPromotionDiscount> AllPromotionDiscounts = new Dictionary <IPromotionUsage, IPromotionDiscount>(); //Need to loop all promos and all discount types in those promos so we can build up a list of all the discounts on this order foreach (PromotionsData.PromotionUsage promotionUsage in promotionUsages) { foreach (IPromotionDiscount promoDiscount in promotionUsage.Promotion.PromotionDiscounts) { //We need to add only one item per promo usage but we want to order by the non-shipping option when it has shipping plus another discount type on one promo //this only works becuase we restrict promos to shipping plus one other type of discount. if (promotionUsage.Promotion.PromotionDiscounts.Count == 1 || promoDiscount.SequenceNumber != (int)PromotionDiscountBase.PromotionSequence.Shipping) { AllPromotionDiscounts.Add(promotionUsage, promoDiscount); } } } //Sort the discounts, this is incase we need to deal with line item -vs- order level coupon priority var sortedPromotionDiscounts = AllPromotionDiscounts.ToArray().OrderBy(apd => apd.Key.Id).OrderBy(apd => apd.Value.SequenceNumber); var discountContext = CreateDiscountContext(ruleContext); foreach (KeyValuePair <IPromotionUsage, IPromotionDiscount> discountPair in sortedPromotionDiscounts) { var promotionRuleContext = CreateRuleContext(ruleContext, discountPair.Key.PromotionId); List <DiscountableItem> discountableItems = GetDiscountableItems(promotionRuleContext, discountPair.Key.PromotionId); var promotionDiscountContext = CreateDiscountContext(discountContext, discountableItems); IDiscountResult discountResult = promotionController.ApplyPromotion(discountPair.Key, promotionRuleContext, promotionDiscountContext, () => new SimpleDiscountResult(), CreatePromotionController(), AppLogic.CustomerLevelAllowsCoupons(ruleContext.CustomerLevel)); if (discountResult != null) { discountResults.Add(discountResult); } } return(promotionController.CombineDiscounts(discountResults, delegate() { return new SimpleDiscountResult(); })); }
public override IDiscountResult ApplyPromotion(IPromotionUsage promotionUsage, IRuleContext ruleContext, IDiscountContext discountContext, Func <IDiscountResult> resultFactory) { Data.EntityContextDataContext context = new Data.EntityContextDataContext(); IDiscountResult retVal = resultFactory(); Decimal totalDiscount = Decimal.Zero; List <DiscountedItem> discountedItems = new List <DiscountedItem>(); Int32 quantity = 1; Int32 contextQuantity = discountContext.DiscountableItems.Sum(s => s.Quantity); Int32 shoppingCartRecordId = 0; if (MatchQuantities && contextQuantity > 0) { quantity = discountContext.DiscountableItems.Sum(s => s.Quantity); } foreach (Int32 productId in GiftProductIds) { Data.ShoppingCart cart = null; //Try to find an existing free gift in the promotionlineitem table for this promousage PromotionLineItem giftItem = context.PromotionLineItems.FirstOrDefault(pli => pli.productId == productId && pli.isAGift && pli.PromotionUsageId == promotionUsage.Id); //Try to grab the shopping cart item for the promolineitem if (giftItem != null) { cart = context.ShoppingCarts.FirstOrDefault(sc => sc.ShoppingCartRecID == giftItem.shoppingCartRecordId); } //Add the free item to the shoppingcart if it doesn't already exist if (cart == null) { int variantId = context.ProductVariants.FirstOrDefault(pv => pv.ProductID == productId && pv.IsDefault == 1).VariantID; if (ruleContext.AddItemToCart != null) { shoppingCartRecordId = ruleContext.AddItemToCart(productId, variantId, quantity); } cart = context.ShoppingCarts.FirstOrDefault(sc => sc.ShoppingCartRecID == shoppingCartRecordId); } else { //Make sure our quantities match up. cart.Quantity = quantity; context.SubmitChanges(); } if (cart != null) { DiscountedItem discountedItem = new DiscountedItem(); //We store the original price of the item in the promotionlineitem table, we want to use that original price if we already have a promo line item discountedItem.CartPrice = giftItem == null ? (decimal)cart.ProductPrice : giftItem.cartPrice; discountedItem.IsAGift = true; discountedItem.ProductId = productId; discountedItem.Quantity = cart.Quantity; discountedItem.ShoppingCartRecordId = cart.ShoppingCartRecID; discountedItem.Sku = cart.ProductSKU; discountedItem.Subtotal = (decimal)cart.ProductPrice * cart.Quantity; discountedItem.VariantId = cart.VariantID; discountedItem.PromotionUsage = promotionUsage; decimal discount = -(discountedItem.CartPrice) * (GiftDiscountPercentage * .01m); //Make sure our price won't go negative discount = Math.Abs(discount) > discountedItem.CartPrice ? -(discountedItem.CartPrice) : discount; //The discount is already baked into the cart price we will record the discount in gift amount instead discountedItem.DiscountAmount = 0.0M; discountedItem.GiftAmount = discount * cart.Quantity; totalDiscount += discountedItem.GiftAmount; discountedItem.DiscountPercentage = GiftDiscountPercentage; Data.ContextController.TrackLineItemDiscount(discountedItem); discountedItems.Add(discountedItem); cart.ProductPrice = discountedItem.CartPrice + discount; cart.IsGift = true; cart.CustomerEntersPrice = 1; context.SubmitChanges(); } } retVal.DiscountedItems = discountedItems; retVal.DiscountType = DiscountType.Fixed; retVal.GiftProductTotal = totalDiscount; retVal.SequenceType = (PromotionSequence)SequenceNumber; return(retVal); }