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)); })); }
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)); } }
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); }
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); }