// todo: centralize and test /// <summary> /// The discount value in cents, based on catalog information /// </summary> /// <param name="productId">The product unique identifier.</param> /// <returns></returns> public int GetDiscountAmountInCents(int productId = 0, OrderInfo order = null) { var product = DomainHelper.GetProductById(productId); var productPrice = 0; if (product != null) { if (product.Ranges != null && product.Ranges.Any()) { var range = product.Ranges.FirstOrDefault(x => x.From <= 1 && x.PriceInCents != 0); if (range != null) { productPrice = range.PriceInCents; } } else { //productPrice = product.Price.BeforeDiscount.ValueInCents; this doesn't work, because IsDiscounted will call this function, creating a loop } } if (order == null) { order = OrderHelper.GetOrder(); } var orderCount = 0; if (order != null) { orderCount = order.OrderLines.Select(l => l.ProductInfo).Where(p => p.OriginalId == productId).Sum(p => p.Quantity); } var discountValue = RangedDiscountValue(orderCount); if (DiscountType == DiscountType.NewPrice) { return(discountValue - productPrice); } if (DiscountType == DiscountType.Amount) { return(Math.Max(discountValue, productPrice)); } if (DiscountType == DiscountType.Percentage) { return(DiscountHelper.PercentageCalculation(discountValue, productPrice)); } return(0); }
/// <summary> /// Gets the adjusted price. /// </summary> /// <param name="discount">The discount.</param> /// <param name="priceBeforeDiscount">The price before discount.</param> /// <returns></returns> public static int GetAdjustedPrice(this IProductDiscount discount, int priceBeforeDiscount, int orderTotalItemCount = 0) { if (discount == null || discount.Type == DiscountType.FreeShipping) { return(priceBeforeDiscount); } var discountValue = discount.DiscountValue; // discount.RangedDiscountValue(orderTotalItemCount); if (discount.Type == DiscountType.Percentage) { return(priceBeforeDiscount - DiscountHelper.PercentageCalculation(priceBeforeDiscount, discountValue)); } if (discount.Type == DiscountType.Amount) { return(priceBeforeDiscount - discountValue); } if (discount.Type == DiscountType.NewPrice) { return(discountValue); } return(priceBeforeDiscount); }
public int DiscountAmountForOrder(IOrderDiscount discount, OrderInfo orderInfo, bool applyDiscountEffects = false) //, IAuthenticationProvider authenticationProvider = null) { if (!string.IsNullOrEmpty(discount.CouponCode) && !orderInfo.CouponCodes.Contains(discount.CouponCode)) { return(0); } if (orderInfo.Status == OrderStatus.Incomplete) { var coupons = _couponCodeService.GetAllForDiscount(discount.Id); if (coupons.Any()) // { var availableCoupons = coupons.Where(c => c.NumberAvailable > 0).Select(c => c.CouponCode); if (!availableCoupons.Intersect(orderInfo.CouponCodes).Any()) { return(0); } } } var authenticationProvider = IO.Container.Resolve <IAuthenticationProvider>(); if (discount.MemberGroups.Any() && !discount.MemberGroups.Intersect(authenticationProvider.RolesForCurrentUser).Any()) { return(0); } if (discount.OncePerCustomer && !string.IsNullOrEmpty(authenticationProvider.CurrentLoginName)) { var ordersforCurrentMember = OrderHelper.GetOrdersForCustomer(authenticationProvider.CurrentLoginName).Where(x => x.Status != OrderStatus.Incomplete && x.Status != OrderStatus.Cancelled && x.Status != OrderStatus.Returned); if (ordersforCurrentMember.Any(x => x.Discounts.Any(d => d.OriginalId == discount.Id))) { return(0); } } var applicableOrderLines = !discount.AffectedOrderlines.Any() ? orderInfo.OrderLines : _orderService.GetApplicableOrderLines(orderInfo, discount.AffectedOrderlines); if (discount.AffectedProductTags != null && discount.AffectedProductTags.Any()) { applicableOrderLines = applicableOrderLines.Where(line => line.ProductInfo.Tags.Intersect(discount.AffectedProductTags).Any()).ToList(); } var isSellableUnitDiscount = discount.AffectedOrderlines.Any() || (discount.AffectedProductTags != null && discount.AffectedProductTags.Any()); var orderSellableUnits = new List <SellableUnit>(); foreach (var line in applicableOrderLines) { //for (var i = 0; i < line.ProductInfo.ItemCount; i++) orderSellableUnits.AddRange(line.SellableUnits); // maak een lijst met de prijzen van alle (losse) items van de order } var numberOfItemsLeftOutOfSets = discount.NumberOfItemsCondition == 0 ? 0 : applicableOrderLines.Sum(line => line.ProductInfo.ItemCount.GetValueOrDefault(1)) % discount.NumberOfItemsCondition; var applicableSellableUnits = orderSellableUnits.OrderBy(item => item.PriceInCents).Take(orderSellableUnits.Count - numberOfItemsLeftOutOfSets).ToList(); var rangedDiscountValue = RangedDiscountValueForOrder(discount, orderInfo); // todo: not localized var discountAmount = rangedDiscountValue; var maximumDiscountableAmount = 0L; var timesApplicable = 1; if (discount.Condition == DiscountOrderCondition.None) { maximumDiscountableAmount = applicableOrderLines.Sum(orderline => orderline.AmountInCents - (orderline.GetOriginalAmount(false, true) - orderline.GetOriginalAmount(true, true))); timesApplicable = applicableOrderLines.Sum(orderLine => orderLine.ProductInfo.ItemCount.GetValueOrDefault(1)); } else if (discount.Condition == DiscountOrderCondition.OnTheXthItem && discount.NumberOfItemsCondition > 0) { isSellableUnitDiscount = true; // todo: test discountAmount = discountAmount * applicableSellableUnits.Count() / discount.NumberOfItemsCondition; applicableSellableUnits = applicableSellableUnits.Take(orderSellableUnits.Count / discount.NumberOfItemsCondition).ToList(); maximumDiscountableAmount = applicableSellableUnits.Sum(su => su.PriceInCents); // bereken de korting over de x goedkoopste items, waarbij x het aantal sets in de order is } else if (discount.Condition == DiscountOrderCondition.PerSetOfXItems && discount.NumberOfItemsCondition > 0) { isSellableUnitDiscount = true; timesApplicable = applicableSellableUnits.Count() / discount.NumberOfItemsCondition; if (discount.DiscountType == DiscountType.Amount) { applicableSellableUnits = applicableSellableUnits.Take(orderSellableUnits.Count / discount.NumberOfItemsCondition).ToList(); } discountAmount = discountAmount * applicableSellableUnits.Count() / discount.NumberOfItemsCondition; maximumDiscountableAmount = applicableSellableUnits.Sum(su => su.PriceInCents); } if (discount.IncludeShippingInOrderDiscountableAmount) { maximumDiscountableAmount += orderInfo.ShippingProviderAmountInCents; } if (discount.DiscountType == DiscountType.Amount) { // currently not on SellableUnits, because that would break existing functionality if (applyDiscountEffects) { var amountDiscountEffect = new AmountDiscountEffect { Amount = rangedDiscountValue }; if (isSellableUnitDiscount) { foreach (var su in applicableSellableUnits) { su.SellableUnitDiscountEffects.AddEffect(amountDiscountEffect); } } else { orderInfo.OrderDiscountEffects.AddEffect(amountDiscountEffect); } } return((int)Math.Min(discountAmount, maximumDiscountableAmount)); } if (discount.DiscountType == DiscountType.Percentage) { // wanneer SellableUnit/OrderLine/Order if (applyDiscountEffects) { var percentageDiscountEffect = new PercentageDiscountEffect { Percentage = rangedDiscountValue / 10000m }; if (isSellableUnitDiscount) { foreach (var su in applicableSellableUnits) { su.SellableUnitDiscountEffects.AddEffect(percentageDiscountEffect); } } else { orderInfo.OrderDiscountEffects.AddEffect(percentageDiscountEffect); } } return(DiscountHelper.PercentageCalculation(rangedDiscountValue, maximumDiscountableAmount)); } if (discount.DiscountType == DiscountType.NewPrice) { if (applyDiscountEffects) { var newPriceDiscountEffect = new NewPriceDiscountEffect { NewPrice = rangedDiscountValue }; foreach (var applicableSellableUnit in applicableSellableUnits) { applicableSellableUnit.SellableUnitDiscountEffects.AddEffect(newPriceDiscountEffect); } } if (discount.Condition == DiscountOrderCondition.OnTheXthItem && discount.NumberOfItemsCondition > 0) { return(applicableSellableUnits.Take(orderSellableUnits.Count / discount.NumberOfItemsCondition).Select(su => Math.Max(0, su.PriceInCents - discountAmount)).Sum()); } return((int)Math.Max(0, maximumDiscountableAmount - rangedDiscountValue * timesApplicable)); } return(0); }