protected virtual List <OrderLine> GetOrderLinesInScope(CouponTemplateData couponTemplate, Order order, Dictionary <Guid, ProductDto> productDict) { if (couponTemplate.IsUnscoped) { return(order.OrderLines); } var expectedOrderLines = new List <OrderLine>(); foreach (var scope in couponTemplate.Scopes.Where(scope => scope.StoreId == order.StoreId)) { expectedOrderLines.AddRange(order.OrderLines .WhereIf(scope.ProductGroupName != null, x => productDict[x.ProductId].ProductGroupName == scope.ProductGroupName) .WhereIf(scope.ProductId.HasValue, x => x.ProductId == scope.ProductId) .WhereIf(scope.ProductSkuId.HasValue, x => x.ProductSkuId == scope.ProductSkuId)); } if (expectedOrderLines.IsNullOrEmpty()) { throw new OrderDoesNotMeetCouponUsageConditionException(); } if (expectedOrderLines.Sum(x => GetOrderLineProductPrice(x, productDict) * x.Quantity) < couponTemplate.ConditionAmount) { throw new OrderDoesNotMeetCouponUsageConditionException(); } return(expectedOrderLines); }
protected virtual void DiscountOrderLines(CouponTemplateData couponTemplate, Order order, List <OrderLine> orderLinesInScope) { // Todo: support Custom coupon. if (couponTemplate.CouponType == CouponType.Custom) { throw new NotSupportedException(); } var totalOrderLineActualTotalPrice = orderLinesInScope.Sum(x => x.ActualTotalPrice); var totalDiscountedAmount = couponTemplate.CouponType == CouponType.PerMeet ? couponTemplate.DiscountAmount * Math.Floor(totalOrderLineActualTotalPrice / couponTemplate.ConditionAmount) : couponTemplate.DiscountAmount; if (totalDiscountedAmount > totalOrderLineActualTotalPrice) { totalDiscountedAmount = totalOrderLineActualTotalPrice; } var remainingDiscountedAmount = totalDiscountedAmount; // Todo: https://github.com/EasyAbp/EShop/issues/104 const int accuracy = 2; foreach (var orderLine in orderLinesInScope) { var maxDiscountAmount = Math.Round(orderLine.ActualTotalPrice / totalOrderLineActualTotalPrice * totalDiscountedAmount, accuracy, MidpointRounding.ToZero); var discountAmount = maxDiscountAmount > orderLine.ActualTotalPrice ? orderLine.ActualTotalPrice : maxDiscountAmount; order.AddDiscount(orderLine.Id, discountAmount); remainingDiscountedAmount -= discountAmount; } foreach (var orderLine in orderLinesInScope.OrderByDescending(x => x.ActualTotalPrice)) { if (remainingDiscountedAmount == decimal.Zero) { break; } var discountAmount = remainingDiscountedAmount > orderLine.ActualTotalPrice ? orderLine.ActualTotalPrice : remainingDiscountedAmount; order.AddDiscount(orderLine.Id, discountAmount); remainingDiscountedAmount -= discountAmount; } if (remainingDiscountedAmount != decimal.Zero) { throw new ApplicationException(); } order.SetProperty(CouponsConsts.OrderCouponDiscountAmountPropertyName, totalDiscountedAmount); }
protected virtual bool IsCurrencyExpected(CouponTemplateData couponTemplate, Order order) { return(couponTemplate.Currency == order.Currency); }