/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="overriddenProductPrice">Overridden product price. If specified, then it'll be used instead of a product price. For example, used with product attribute combinations</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="rentalStartDate">Rental period start date (for rental products)</param> /// <param name="rentalEndDate">Rental period end date (for rental products)</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscounts">Applied discounts</param> /// <returns>Final price</returns> public virtual decimal GetFinalPrice(Product product, Customer customer, decimal?overriddenProductPrice, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime?rentalStartDate, DateTime?rentalEndDate, out decimal discountAmount, out List <DiscountForCaching> appliedDiscounts) { if (product == null) { throw new ArgumentNullException("product"); } discountAmount = decimal.Zero; appliedDiscounts = new List <DiscountForCaching>(); var cacheTime = _catalogSettings.CacheProductPrices ? 60 : 0; //we do not cache price for rental products //otherwise, it can cause memory leaks (to store all possible date period combinations) if (product.IsRental) { cacheTime = 0; } var result = new ProductPriceForCaching(); //initial price decimal price = overriddenProductPrice.HasValue ? overriddenProductPrice.Value : product.Price; //tier prices var tierPrice = product.GetPreferredTierPrice(customer, _storeContext.CurrentStore.Id, quantity); if (tierPrice != null) { price = tierPrice.Price; } //additional charge price = price + additionalCharge; //rental products if (product.IsRental) { if (rentalStartDate.HasValue && rentalEndDate.HasValue) { price = price * product.GetRentalPeriods(rentalStartDate.Value, rentalEndDate.Value); } } if (includeDiscounts) { //discount List <DiscountForCaching> tmpAppliedDiscounts; decimal tmpDiscountAmount = GetDiscountAmount(product, customer, price, out tmpAppliedDiscounts); price = price - tmpDiscountAmount; if (tmpAppliedDiscounts != null) { result.AppliedDiscounts = tmpAppliedDiscounts; result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) { price = decimal.Zero; } result.Price = price; var cachedPrice = result; if (includeDiscounts) { if (cachedPrice.AppliedDiscounts.Any()) { appliedDiscounts.AddRange(cachedPrice.AppliedDiscounts); discountAmount = cachedPrice.AppliedDiscountAmount; } } return(cachedPrice.Price); }
/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="rentalStartDate">Rental period start date (for rental products)</param> /// <param name="rentalEndDate">Rental period end date (for rental products)</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Final price</returns> public virtual async Task <(decimal finalPrice, decimal discountAmount, List <AppliedDiscount> appliedDiscounts, TierPrice preferredTierPrice)> GetFinalPrice(Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime?rentalStartDate, DateTime?rentalEndDate) { if (product == null) { throw new ArgumentNullException("product"); } var discountAmount = decimal.Zero; var appliedDiscounts = new List <AppliedDiscount>(); async Task <ProductPriceForCaching> PrepareModel() { var result = new ProductPriceForCaching(); //initial price decimal price = product.Price; //tier prices var tierPrice = product.GetPreferredTierPrice(customer, _storeContext.CurrentStore.Id, quantity); if (tierPrice != null) { price = tierPrice.Price; result.PreferredTierPrice = tierPrice; } //customer product price if (_catalogSettings.CustomerProductPrice) { var customerPrice = await _customerProductService.GetPriceByCustomerProduct(customer.Id, product.Id); if (customerPrice.HasValue && customerPrice.Value < price) { price = customerPrice.Value; } } //additional charge price = price + additionalCharge; //reservations if (product.ProductType == ProductType.Reservation) { if (rentalStartDate.HasValue && rentalEndDate.HasValue) { decimal d = 0; if (product.IncBothDate) { decimal.TryParse(((rentalEndDate - rentalStartDate).Value.TotalDays + 1).ToString(), out d); } else { decimal.TryParse((rentalEndDate - rentalStartDate).Value.TotalDays.ToString(), out d); } price = price * d; } } if (includeDiscounts) { //discount var discountamount = await GetDiscountAmount(product, customer, price); decimal tmpDiscountAmount = discountamount.discountAmount; List <AppliedDiscount> tmpAppliedDiscounts = discountamount.appliedDiscounts; price = price - tmpDiscountAmount; if (tmpAppliedDiscounts != null) { result.AppliedDiscounts = tmpAppliedDiscounts.ToList(); result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) { price = decimal.Zero; } //rounding if (_shoppingCartSettings.RoundPricesDuringCalculation) { var primaryCurrency = await _currencyService.GetPrimaryExchangeRateCurrency(); result.Price = RoundingHelper.RoundPrice(price, primaryCurrency); } else { result.Price = price; } return(result); } var modelprice = await PrepareModel(); if (includeDiscounts) { appliedDiscounts = modelprice.AppliedDiscounts.ToList(); if (appliedDiscounts.Any()) { discountAmount = modelprice.AppliedDiscountAmount; } } return(modelprice.Price, discountAmount, appliedDiscounts, modelprice.PreferredTierPrice); }
/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="overriddenProductPrice">Overridden product price. If specified, then it'll be used instead of a product price. For example, used with product attribute combinations</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="rentalStartDate">Rental period start date (for rental products)</param> /// <param name="rentalEndDate">Rental period end date (for rental products)</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscounts">Applied discounts</param> /// <returns>Final price</returns> public virtual decimal GetFinalPrice(Product product, Customer customer, decimal? overriddenProductPrice, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime? rentalStartDate, DateTime? rentalEndDate, out decimal discountAmount, out List<Discount> appliedDiscounts) { if (product == null) throw new ArgumentNullException("product"); discountAmount = decimal.Zero; appliedDiscounts = new List<Discount>(); var cacheKey = string.Format(PriceCacheEventConsumer.PRODUCT_PRICE_MODEL_KEY, product.Id, overriddenProductPrice.HasValue ? overriddenProductPrice.Value.ToString(CultureInfo.InvariantCulture) : null, additionalCharge.ToString(CultureInfo.InvariantCulture), includeDiscounts, quantity, string.Join(",", customer.GetCustomerRoleIds()), _storeContext.CurrentStore.Id); var cacheTime = _catalogSettings.CacheProductPrices ? 60 : 0; //we do not cache price for rental products //otherwise, it can cause memory leaks (to store all possible date period combinations) if (product.IsRental) cacheTime = 0; var cachedPrice = _cacheManager.Get(cacheKey, cacheTime, () => { var result = new ProductPriceForCaching(); //initial price decimal price = overriddenProductPrice.HasValue ? overriddenProductPrice.Value : product.Price; //special price var specialPrice = product.GetSpecialPrice(); if (specialPrice.HasValue) price = specialPrice.Value; //tier prices if (product.HasTierPrices) { decimal? tierPrice = GetMinimumTierPrice(product, customer, quantity); if (tierPrice.HasValue) price = Math.Min(price, tierPrice.Value); } //additional charge price = price + additionalCharge; //rental products if (product.IsRental) if (rentalStartDate.HasValue && rentalEndDate.HasValue) price = price * product.GetRentalPeriods(rentalStartDate.Value, rentalEndDate.Value); if (includeDiscounts) { //discount List<Discount> tmpAppliedDiscounts; decimal tmpDiscountAmount = GetDiscountAmount(product, customer, price, out tmpAppliedDiscounts); price = price - tmpDiscountAmount; if (tmpAppliedDiscounts != null) { result.AppliedDiscountIds = tmpAppliedDiscounts.Select(x=>x.Id).ToList(); result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) price = decimal.Zero; result.Price = price; return result; }); if (includeDiscounts) { //Discount instance cannnot be cached between requests (when "catalogSettings.CacheProductPrices" is "true) //This is limitation of Entity Framework //That's why we load it here after working with cache foreach (var appliedDiscountId in cachedPrice.AppliedDiscountIds) { var appliedDiscount = _discountService.GetDiscountById(appliedDiscountId); if (appliedDiscount != null) appliedDiscounts.Add(appliedDiscount); } if (appliedDiscounts.Any()) { discountAmount = cachedPrice.AppliedDiscountAmount; } } return cachedPrice.Price; }
/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="rentalStartDate">Rental period start date (for rental products)</param> /// <param name="rentalEndDate">Rental period end date (for rental products)</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Final price</returns> public virtual decimal GetFinalPrice(Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime?rentalStartDate, DateTime?rentalEndDate, out decimal discountAmount, out Discount appliedDiscount) { if (product == null) { throw new ArgumentNullException("product"); } discountAmount = decimal.Zero; appliedDiscount = null; var cacheKey = string.Format(PriceCacheEventConsumer.PRODUCT_PRICE_MODEL_KEY, product.Id, additionalCharge.ToString(CultureInfo.InvariantCulture), includeDiscounts, quantity, string.Join(",", customer.CustomerRoles.Where(cr => cr.Active).Select(cr => cr.Id).ToList()), _storeContext.CurrentStore.Id); var cacheTime = _catalogSettings.CacheProductPrices ? 60 : 0; //we do not cache price for rental products //otherwise, it can cause memory leaks (to store all possible date period combinations) if (product.IsRental) { cacheTime = 0; } var cachedPrice = _cacheManager.Get(cacheKey, cacheTime, () => { var result = new ProductPriceForCaching(); //initial price decimal price = product.Price; //special price var specialPrice = product.GetSpecialPrice(); if (specialPrice.HasValue) { price = specialPrice.Value; } //tier prices if (product.HasTierPrices) { decimal?tierPrice = GetMinimumTierPrice(product, customer, quantity); if (tierPrice.HasValue) { price = Math.Min(price, tierPrice.Value); } } //additional charge price = price + additionalCharge; //rental products if (product.IsRental) { if (rentalStartDate.HasValue && rentalEndDate.HasValue) { price = price * GetRentalPeriods(product, rentalStartDate.Value, rentalEndDate.Value); } } if (includeDiscounts) { //discount Discount tmpAppliedDiscount; decimal tmpDiscountAmount = GetDiscountAmount(product, customer, price, out tmpAppliedDiscount); price = price - tmpDiscountAmount; if (tmpAppliedDiscount != null) { result.AppliedDiscountId = tmpAppliedDiscount.Id; result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) { price = decimal.Zero; } result.Price = price; return(result); }); if (includeDiscounts) { //Discount instance cannnot be cached between requests (when "catalogSettings.CacheProductPrices" is "true) //This is limitation of Entity Framework //That's why we load it here after working with cache appliedDiscount = _discountService.GetDiscountById(cachedPrice.AppliedDiscountId); if (appliedDiscount != null) { discountAmount = cachedPrice.AppliedDiscountAmount; } } return(cachedPrice.Price); }
/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="overriddenProductPrice">Overridden product price. If specified, then it'll be used instead of a product price. For example, used with product attribute combinations</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="rentalStartDate">Rental period start date (for rental products)</param> /// <param name="rentalEndDate">Rental period end date (for rental products)</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscounts">Applied discounts</param> /// <returns>Final price</returns> public virtual decimal GetFinalPrice(Product product, Customer customer, decimal?overriddenProductPrice, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime?rentalStartDate, DateTime?rentalEndDate, out decimal discountAmount, out List <DiscountForCaching> appliedDiscounts) { if (product == null) { throw new ArgumentNullException(nameof(product)); } discountAmount = decimal.Zero; appliedDiscounts = new List <DiscountForCaching>(); var cacheKey = string.Format(PriceCacheEventConsumer.PRODUCT_PRICE_MODEL_KEY, product.Id, overriddenProductPrice.HasValue ? overriddenProductPrice.Value.ToString(CultureInfo.InvariantCulture) : null, additionalCharge.ToString(CultureInfo.InvariantCulture), includeDiscounts, quantity, string.Join(",", customer.GetCustomerRoleIds()), _storeContext.CurrentStore.Id); var cacheTime = _catalogSettings.CacheProductPrices ? 60 : 0; //we do not cache price for rental products //otherwise, it can cause memory leaks (to store all possible date period combinations) if (product.IsRental) { cacheTime = 0; } var cachedPrice = _cacheManager.Get(cacheKey, cacheTime, () => { var result = new ProductPriceForCaching(); //initial price var price = overriddenProductPrice.HasValue ? overriddenProductPrice.Value : product.Price; //tier prices var tierPrice = product.GetPreferredTierPrice(customer, _storeContext.CurrentStore.Id, quantity); if (tierPrice != null) { price = tierPrice.Price; } //additional charge price = price + additionalCharge; //rental products if (product.IsRental) { if (rentalStartDate.HasValue && rentalEndDate.HasValue) { price = price * product.GetRentalPeriods(rentalStartDate.Value, rentalEndDate.Value); } } if (includeDiscounts) { //discount var tmpDiscountAmount = GetDiscountAmount(product, customer, price, out List <DiscountForCaching> tmpAppliedDiscounts); price = price - tmpDiscountAmount; if (tmpAppliedDiscounts != null) { result.AppliedDiscounts = tmpAppliedDiscounts; result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) { price = decimal.Zero; } result.Price = price; return(result); }); if (includeDiscounts) { if (cachedPrice.AppliedDiscounts.Any()) { appliedDiscounts.AddRange(cachedPrice.AppliedDiscounts); discountAmount = cachedPrice.AppliedDiscountAmount; } } return(cachedPrice.Price); }
/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="rentalStartDate">Rental period start date (for rental products)</param> /// <param name="rentalEndDate">Rental period end date (for rental products)</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Final price</returns> public virtual decimal GetFinalPrice(Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime?rentalStartDate, DateTime?rentalEndDate, out decimal discountAmount, out List <AppliedDiscount> appliedDiscounts) { if (product == null) { throw new ArgumentNullException("product"); } discountAmount = decimal.Zero; appliedDiscounts = new List <AppliedDiscount>(); var cacheKey = string.Format(PriceCacheEventConsumer.PRODUCT_PRICE_MODEL_KEY, product.Id, additionalCharge.ToString(CultureInfo.InvariantCulture), includeDiscounts, quantity, string.Join(",", customer.GetCustomerRoleIds()), _storeContext.CurrentStore.Id); var cacheTime = _catalogSettings.CacheProductPrices ? 60 : 0; //we do not cache price for reservation products //otherwise, it can cause memory leaks (to store all possible date period combinations) if (product.ProductType == ProductType.Reservation) { cacheTime = 0; } ProductPriceForCaching PrepareModel() { var result = new ProductPriceForCaching(); //initial price decimal price = product.Price; //customer product price var customerPrice = _customerService.GetPriceByCustomerProduct(customer.Id, product.Id); if (customerPrice.HasValue && customerPrice.Value < price) { price = customerPrice.Value; } //tier prices var tierPrice = product.GetPreferredTierPrice(customer, _storeContext.CurrentStore.Id, quantity); if (tierPrice != null) { price = tierPrice.Price; } //additional charge price = price + additionalCharge; //reservations if (product.ProductType == ProductType.Reservation) { if (rentalStartDate.HasValue && rentalEndDate.HasValue) { decimal d = 0; if (product.IncBothDate) { decimal.TryParse(((rentalEndDate - rentalStartDate).Value.TotalDays + 1).ToString(), out d); } else { decimal.TryParse((rentalEndDate - rentalStartDate).Value.TotalDays.ToString(), out d); } price = price * d; } } if (includeDiscounts) { //discount List <AppliedDiscount> tmpAppliedDiscounts; decimal tmpDiscountAmount = GetDiscountAmount(product, customer, price, out tmpAppliedDiscounts); price = price - tmpDiscountAmount; if (tmpAppliedDiscounts != null) { result.AppliedDiscountIds = tmpAppliedDiscounts.Select(x => x.DiscountId).ToList(); result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) { price = decimal.Zero; } //rounding if (_shoppingCartSettings.RoundPricesDuringCalculation) { var primaryCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryExchangeRateCurrencyId); result.Price = RoundingHelper.RoundPrice(price, primaryCurrency); } else { result.Price = price; } return(result); } var cachedPrice = cacheTime > 0 ? _cacheManager.Get(cacheKey, cacheTime, () => { return(PrepareModel()); }) : PrepareModel(); if (includeDiscounts) { foreach (var appliedDiscountId in cachedPrice.AppliedDiscountIds) { var appliedDiscount = _discountService.GetDiscountById(appliedDiscountId); if (appliedDiscount != null) { appliedDiscounts.Add(new AppliedDiscount() { DiscountId = appliedDiscount.Id, IsCumulative = appliedDiscount.IsCumulative }); } } if (appliedDiscounts.Any()) { discountAmount = cachedPrice.AppliedDiscountAmount; } } return(cachedPrice.Price); }
/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="rentalStartDate">Rental period start date (for rental products)</param> /// <param name="rentalEndDate">Rental period end date (for rental products)</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Final price</returns> public virtual decimal GetFinalPrice(Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime?rentalStartDate, DateTime?rentalEndDate, out decimal discountAmount, out List <Discount> appliedDiscounts) { if (product == null) { throw new ArgumentNullException("product"); } discountAmount = decimal.Zero; appliedDiscounts = new List <Discount>(); var cacheKey = string.Format(PriceCacheEventConsumer.PRODUCT_PRICE_MODEL_KEY, product.Id, additionalCharge.ToString(CultureInfo.InvariantCulture), includeDiscounts, quantity, string.Join(",", customer.GetCustomerRoleIds()), _storeContext.CurrentStore.Id); var cacheTime = _catalogSettings.CacheProductPrices ? 60 : 0; //we do not cache price for rental products //otherwise, it can cause memory leaks (to store all possible date period combinations) if (product.IsRental) { cacheTime = 0; } //var cachedPrice = _cacheManager.Get(cacheKey, cacheTime, () => //{ var result = new ProductPriceForCaching(); //initial price decimal price = product.Price; //tier prices var tierPrice = product.GetPreferredTierPrice(customer, _storeContext.CurrentStore.Id, quantity); if (tierPrice != null) { price = tierPrice.Price; } //additional charge price = price + additionalCharge; //rental products if (product.IsRental) { if (rentalStartDate.HasValue && rentalEndDate.HasValue) { price = price * product.GetRentalPeriods(rentalStartDate.Value, rentalEndDate.Value); } } if (false) //includeDiscounts) { //discount List <Discount> tmpAppliedDiscounts; decimal tmpDiscountAmount = GetDiscountAmount(product, customer, price, out tmpAppliedDiscounts); price = price - tmpDiscountAmount; if (tmpAppliedDiscounts != null) { result.AppliedDiscountIds = tmpAppliedDiscounts.Select(x => x.Id).ToList(); result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) { price = decimal.Zero; } result.Price = price; //return result; //}); //rtl var cachedPrice = result; if (false)//includeDiscounts) { //Discount instance cannnot be cached between requests (when "catalogSettings.CacheProductPrices" is "true) //This is limitation of Entity Framework //That's why we load it here after working with cache foreach (var appliedDiscountId in cachedPrice.AppliedDiscountIds) { var appliedDiscount = _discountService.GetDiscountById(appliedDiscountId); if (appliedDiscount != null) { appliedDiscounts.Add(appliedDiscount); } } if (appliedDiscounts.Any()) { discountAmount = cachedPrice.AppliedDiscountAmount; } } return(cachedPrice.Price); }
/// <summary> /// Gets the final price /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param> /// <param name="quantity">Shopping cart item quantity</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Final price</returns> public virtual decimal GetFinalPrice(Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, out decimal discountAmount, out Discount appliedDiscount) { if (product == null) throw new ArgumentNullException("product"); discountAmount = decimal.Zero; appliedDiscount = null; var cacheKey = string.Format(PriceCacheEventConsumer.PRODUCT_PRICE_MODEL_KEY, product.Id, additionalCharge.ToString(CultureInfo.InvariantCulture), includeDiscounts, quantity, string.Join(",", customer.CustomerRoles.Where(cr => cr.Active).Select(cr => cr.Id).ToList()), _storeContext.CurrentStore.Id); var cacheTime = _catalogSettings.CacheProductPrices ? 60 : 0; var cachedPrice = _cacheManager.Get(cacheKey, cacheTime, () => { var result = new ProductPriceForCaching(); //initial price decimal price = product.Price; //special price var specialPrice = GetSpecialPrice(product); if (specialPrice.HasValue) price = specialPrice.Value; //tier prices if (product.HasTierPrices) { decimal? tierPrice = GetMinimumTierPrice(product, customer, quantity); if (tierPrice.HasValue) price = Math.Min(price, tierPrice.Value); } //additional charge price = price + additionalCharge; if (includeDiscounts) { //discount Discount tmpAppliedDiscount = null; decimal tmpDiscountAmount = GetDiscountAmount(product, customer, price, out tmpAppliedDiscount); price = price - tmpDiscountAmount; if (tmpAppliedDiscount != null) { result.AppliedDiscountId = tmpAppliedDiscount.Id; result.AppliedDiscountAmount = tmpDiscountAmount; } } if (price < decimal.Zero) price = decimal.Zero; result.Price = price; return result; }); if (includeDiscounts) { //Discount instance cannnot be cached between requests (when "catalogSettings.CacheProductPrices" is "true) //This is limitation of Entity Framework //That's why we load it here after working with cache appliedDiscount = _discountService.GetDiscountById(cachedPrice.AppliedDiscountId); if (appliedDiscount != null) { discountAmount = cachedPrice.AppliedDiscountAmount; } } return cachedPrice.Price; }