public async Task <IActionResult> Check([FromBody] CartPromotionCheckModel cart)
 {
     return(await this.Execute(isAdmin : false, checkState : true, function : async() =>
     {
         return this.Ok(await this.promotions.CalculatePromotion(cart));
     }));
 }
예제 #2
0
        public async Task <CartPromotionResultModel> CalculatePromotion(CartPromotionCheckModel data)
        {
            Promotion promotion = await this.db.Promotions
                                  .FirstOrDefaultAsync(p => p.PromoCode == data.PromoCode);

            if (promotion == null)
            {
                throw new ArgumentException("Invalid PromoCode");
            }
            ;

            if (!await this.IsActive(promotion.StartDate, promotion.EndDate))
            {
                throw new ArgumentException("Promotion is not active");
            }

            if (!await this.IsWithinQuota(promotion.UsedQuota, promotion.Quota))
            {
                throw new ArgumentException("Quota exceeded");
            }

            //The products included in the promotion
            ICollection <string> productsInPromotion = await this.GetProductsInPromotion(data.PromoCode);

            //The number of products in the cart that are included in the promotion
            int productsInPromotionCount = 0;

            foreach (ProductInCartModel product in data.Products)
            {
                if (productsInPromotion.Contains(product.Id))
                {
                    productsInPromotionCount += product.Quantity;
                }
            }

            //The ids of products included in the promotion from the cart
            IList <string> productsInPromotionFromCart = data.Products
                                                         .Where(p => productsInPromotion.Contains(p.Id))
                                                         .Select(p => p.Id)
                                                         .ToList();

            if (!await this.IsProductsCountConditionMet(productsInPromotionCount, promotion.ProductsCount))
            {
                throw new ArgumentException("No promotion available for selected products/ products quantity");
            }

            if (promotion.IsInclusive)
            {
                return(await this.CaclulateInclusivePromotion(promotion, data, productsInPromotionCount, productsInPromotionFromCart));
            }

            else
            {
                return(await CalculateNotInclusivePromotion(promotion, data, productsInPromotionCount, productsInPromotionFromCart));
            }
        }
예제 #3
0
        private async Task <CartPromotionResultModel> CaclulateInclusivePromotion(Promotion promotion, CartPromotionCheckModel data, int productsInPromotionCount, IList <string> productsInPromotionFromCart)
        {
            CartPromotionResultModel result = new CartPromotionResultModel
            {
                Cart = new List <ProductInCartModel>()
            };

            int quantityToBeGivenAsPromotion = promotion.IsAccumulative
                ? (productsInPromotionCount / promotion.ProductsCount) * promotion.DiscountedProductsCount
                : promotion.DiscountedProductsCount;

            int quantityGivenAsPromotion = 0;

            bool includePriceDiscounts = promotion.IncludePriceDiscounts;

            decimal promotionDisount = promotion.Discount;

            data.Products = await this.OrderProductsInCart(data.Products, includePriceDiscounts);

            foreach (ProductInCartModel product in data.Products)
            {
                int remainingQuantityToBeGivenAsPromotion = quantityToBeGivenAsPromotion - quantityGivenAsPromotion;

                ProductDetailsModel currentProduct = await this.products.Get(product.Id);

                if (remainingQuantityToBeGivenAsPromotion > 0 && productsInPromotionFromCart.Contains(product.Id))
                {
                    if (includePriceDiscounts)
                    {
                        promotionDisount += currentProduct.Discount;
                    }

                    if (promotionDisount > 100)
                    {
                        promotionDisount = 100;
                    }

                    if (product.Quantity > remainingQuantityToBeGivenAsPromotion)
                    {
                        ProductInCartModel discounted = new ProductInCartModel
                        {
                            Id       = product.Id,
                            Name     = currentProduct.Name,
                            ImageUrl = currentProduct.Images
                                       .Reverse()
                                       .FirstOrDefault(),

                            Quantity = remainingQuantityToBeGivenAsPromotion,
                            Price    = currentProduct.Price,
                            Discount = promotionDisount
                        };

                        ProductInCartModel productNotDiscounted = new ProductInCartModel
                        {
                            Id       = product.Id,
                            Name     = currentProduct.Name,
                            ImageUrl = currentProduct.Images
                                       .Reverse()
                                       .FirstOrDefault(),

                            Quantity = product.Quantity - remainingQuantityToBeGivenAsPromotion,
                            Price    = currentProduct.Price,
                            Discount = includePriceDiscounts ? currentProduct.Discount : 0
                        };

                        result.Cart.Add(discounted);

                        result.Cart.Add(productNotDiscounted);

                        quantityGivenAsPromotion += remainingQuantityToBeGivenAsPromotion;
                    }

                    else
                    {
                        ProductInCartModel discounted = new ProductInCartModel
                        {
                            Id       = product.Id,
                            Name     = currentProduct.Name,
                            ImageUrl = currentProduct.Images
                                       .Reverse()
                                       .FirstOrDefault(),

                            Quantity = product.Quantity,
                            Price    = currentProduct.Price,
                            Discount = promotionDisount
                        };

                        result.Cart.Add(discounted);

                        quantityGivenAsPromotion += product.Quantity;
                    }
                }

                else
                {
                    product.Name = currentProduct.Name;

                    product.ImageUrl = currentProduct.Images.Reverse().FirstOrDefault();

                    product.Price = currentProduct.Price;

                    product.Discount = !includePriceDiscounts && productsInPromotionFromCart.Contains(product.Id) ? 0 : currentProduct.Discount;

                    result.Cart.Add(product);
                }
            }

            return(result);
        }
예제 #4
0
        private async Task <CartPromotionResultModel> CalculateNotInclusivePromotion(Promotion promotion, CartPromotionCheckModel data, int productsInPromotionCount, IList <string> productsInPromotionFromCart)
        {
            CartPromotionResultModel result = new CartPromotionResultModel
            {
                Cart = new List <ProductInCartModel>()
            };

            int quantityToBeGivenAsPromotion = promotion.IsAccumulative
                ? (productsInPromotionCount / promotion.ProductsCount) * promotion.DiscountedProductsCount
                : promotion.DiscountedProductsCount;

            bool includePriceDiscounts = promotion.IncludePriceDiscounts;

            decimal promotionDiscount = promotion.Discount;

            IList <string> freeProductIds = await this.db.DiscountedProductsPromotions
                                            .Where(d => d.PromotionId == promotion.Id)
                                            .Select(p => p.ProductId)
                                            .ToListAsync();

            //if (freeProductIds.Count == 1)
            //{
            //    string freeProductId = freeProductIds.FirstOrDefault();

            //    ProductDetailsModel productDetails = await this.products.Get(freeProductId);

            //    if (includePriceDiscounts) promotionDiscount += productDetails.Discount;

            //    if (promotionDiscount > 100) promotionDiscount = 100;

            //    ProductInCartModel freeProduct = new ProductInCartModel
            //    {
            //        Id = freeProductId,
            //        Name = productDetails.Name,
            //        ImageUrl = productDetails.Images.Reverse().FirstOrDefault(),

            //        Quantity = quantityToBeGivenAsPromotion,
            //        Price = productDetails.Price,
            //        Discount = promotionDiscount
            //    };

            //    result.Cart.Add(freeProduct);
            //}
            //else
            //{

            result.DiscountedProductsCount = quantityToBeGivenAsPromotion;

            result.DiscountedProducts = new List <ProductDetailsModel>();

            foreach (string id in freeProductIds)
            {
                ProductDetailsModel product = await this.products.Get(id);

                result.DiscountedProducts.Add(product);
            }

            if (!includePriceDiscounts)
            {
                foreach (ProductDetailsModel product in result.DiscountedProducts)
                {
                    product.Discount = promotion.Discount;
                }
            }
            else
            {
                foreach (ProductDetailsModel product in result.DiscountedProducts)
                {
                    product.Discount += promotionDiscount;

                    if (product.Discount > 100)
                    {
                        product.Discount = 100;
                    }
                }
            }
            //}

            foreach (ProductInCartModel product in data.Products)
            {
                ProductDetailsModel currentProduct = await this.products.Get(product.Id);

                decimal discount = currentProduct.Discount;

                if (productsInPromotionFromCart.Contains(currentProduct.Id) && !includePriceDiscounts)
                {
                    discount = 0;
                }

                ProductInCartModel modifiedProduct = new ProductInCartModel
                {
                    Id       = product.Id,
                    Name     = currentProduct.Name,
                    ImageUrl = currentProduct.Images
                               .Reverse()
                               .FirstOrDefault(),

                    Quantity = product.Quantity,
                    Price    = currentProduct.Price,
                    Discount = discount
                };

                result.Cart.Add(modifiedProduct);
            }

            return(result);
        }