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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }