public override bool CheckRequirement(CheckDiscountRequirementRequest request)
        {
			if (request == null)
				throw new ArgumentNullException("request");

			if (request.DiscountRequirement == null)
				throw new SmartException("Discount requirement is not set");

			if (request.DiscountRequirement.SpentAmount == decimal.Zero)
				return true;

			if (request.Customer == null)
				return false;

			var settings = DeserializeSettings(request.DiscountRequirement.ExtraData);

			if (settings.LimitToCurrentBasketSubTotal)
			{
				return CheckCurrentSubTotalRequirement(request);
			}
			else
			{
				return CheckTotalHistoryRequirement(request);
			}
        }
		/// <summary>
		/// Check discount requirement
		/// </summary>
		/// <param name="request">Object that contains all information required to check the requirement (Current customer, discount, etc)</param>
		/// <returns>true - requirement is met; otherwise, false</returns>
		public bool CheckRequirement(CheckDiscountRequirementRequest request)
		{
			if (request == null)
				throw new ArgumentNullException("request");

			if (request.DiscountRequirement == null)
				throw new SmartException("Discount requirement is not set");

			if (request.Customer == null)
				return false;

			var storeId = request.DiscountRequirement.RestrictedToStoreId ?? 0;

			if (storeId == 0)
				return false;

			bool result = request.Store.Id == storeId;
			return result;
		}
		public override bool CheckRequirement(CheckDiscountRequirementRequest request)
        {
            if (request == null)
                throw new ArgumentNullException("request");
            
            if (request.DiscountRequirement == null)
                throw new SmartException("Discount requirement is not set");

            if (request.Customer == null)
                return false;

            if (request.Customer.BillingAddress == null)
                return false;

            if (request.DiscountRequirement.BillingCountryId == 0)
                return false;

            bool result = request.Customer.BillingAddress.CountryId == request.DiscountRequirement.BillingCountryId;
            return result;
        }
		public override bool CheckRequirement(CheckDiscountRequirementRequest request)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            if (request.DiscountRequirement == null)
                throw new SmartException("Discount requirement is not set");

            if (request.Customer == null)
                return false;

            if (!request.DiscountRequirement.RestrictedToCustomerRoleId.HasValue)
                return false;

            foreach (var customerRole in request.Customer.CustomerRoles.Where(cr => cr.Active).ToList())
                if (request.DiscountRequirement.RestrictedToCustomerRoleId == customerRole.Id)
                    return true;

            return false;
        }
		private bool CheckTotalHistoryRequirement(CheckDiscountRequirementRequest request)
		{
			if (request.Customer.IsGuest())
				return false;

			var orders = _orderService.SearchOrders(
				request.Store.Id,
				request.Customer.Id,
				null,
				null,
				new int[] { (int)OrderStatus.Complete },
				null,
				null,
				null,
				null,
				null,
				0,
				int.MaxValue);

			decimal spentAmount = orders.Sum(o => o.OrderTotal);
			return spentAmount >= request.DiscountRequirement.SpentAmount;
		}
        public virtual bool IsDiscountValid(Discount discount, Customer customer, string couponCodeToValidate)
        {
            Guard.NotNull(discount, nameof(discount));

            // Check coupon code
            if (discount.RequiresCouponCode)
            {
                if (discount.CouponCode.IsEmpty())
                {
                    return(false);
                }

                if (!discount.CouponCode.Equals(couponCodeToValidate, StringComparison.InvariantCultureIgnoreCase))
                {
                    return(false);
                }
            }

            // Check date range
            var now   = DateTime.UtcNow;
            var store = _storeContext.CurrentStore;

            if (discount.StartDateUtc.HasValue)
            {
                var startDate = DateTime.SpecifyKind(discount.StartDateUtc.Value, DateTimeKind.Utc);
                if (startDate.CompareTo(now) > 0)
                {
                    return(false);
                }
            }

            if (discount.EndDateUtc.HasValue)
            {
                var endDate = DateTime.SpecifyKind(discount.EndDateUtc.Value, DateTimeKind.Utc);
                if (endDate.CompareTo(now) < 0)
                {
                    return(false);
                }
            }

            if (!CheckDiscountLimitations(discount, customer))
            {
                return(false);
            }

            // better not to apply discounts if there are gift cards in the cart cause the customer could "earn" money through that.
            if (discount.DiscountType == DiscountType.AssignedToOrderTotal || discount.DiscountType == DiscountType.AssignedToOrderSubTotal)
            {
                var cart = customer.GetCartItems(ShoppingCartType.ShoppingCart, store.Id);
                if (cart.Any(x => x.Item?.Product != null && x.Item.Product.IsGiftCard))
                {
                    return(false);
                }
            }

            // discount requirements
            var requirements = discount.DiscountRequirements;

            foreach (var req in requirements)
            {
                var requirementRule = LoadDiscountRequirementRuleBySystemName(req.DiscountRequirementRuleSystemName, store.Id);
                if (requirementRule == null)
                {
                    continue;
                }

                var request = new CheckDiscountRequirementRequest
                {
                    DiscountRequirement = req,
                    Customer            = customer,
                    Store = store
                };

                // TODO: cache result... CheckRequirement is called very often
                if (!requirementRule.Value.CheckRequirement(request))
                {
                    return(false);
                }
            }

            return(true);
        }
		private bool CheckCurrentSubTotalRequirement(CheckDiscountRequirementRequest request)
		{
			var cartItems = request.Customer.GetCartItems(ShoppingCartType.ShoppingCart, request.Store.Id);

			decimal spentAmount = decimal.Zero;
			decimal taxRate = decimal.Zero;
			foreach (var sci in cartItems)
			{
				// includeDiscounts == true produces a stack overflow!
				spentAmount += sci.Item.Quantity * _taxService.GetProductPrice(sci.Item.Product, _priceCalculationService.GetUnitPrice(sci, false), out taxRate);
			}

			return spentAmount >= request.DiscountRequirement.SpentAmount;
		}
Esempio n. 8
0
        /// <summary>
        /// Check discount requirements
        /// </summary>
        /// <param name="discount">Discount</param>
        /// <param name="customer">Customer</param>
        /// <param name="couponCodeToValidate">Coupon code to validate</param>
        /// <returns>true - requirement is met; otherwise, false</returns>
        public virtual bool IsDiscountValid(Discount discount, Customer customer, string couponCodeToValidate)
        {
            if (discount == null)
            {
                throw new ArgumentNullException("discount");
            }

            //check coupon code
            if (discount.RequiresCouponCode)
            {
                if (String.IsNullOrEmpty(discount.CouponCode))
                {
                    return(false);
                }
                if (!discount.CouponCode.Equals(couponCodeToValidate, StringComparison.InvariantCultureIgnoreCase))
                {
                    return(false);
                }
            }

            //check date range
            DateTime now = DateTime.UtcNow;

            if (discount.StartDateUtc.HasValue)
            {
                DateTime startDate = DateTime.SpecifyKind(discount.StartDateUtc.Value, DateTimeKind.Utc);
                if (startDate.CompareTo(now) > 0)
                {
                    return(false);
                }
            }
            if (discount.EndDateUtc.HasValue)
            {
                DateTime endDate = DateTime.SpecifyKind(discount.EndDateUtc.Value, DateTimeKind.Utc);
                if (endDate.CompareTo(now) < 0)
                {
                    return(false);
                }
            }

            if (!CheckDiscountLimitations(discount, customer))
            {
                return(false);
            }

            //discount requirements
            var requirements = discount.DiscountRequirements;

            foreach (var req in requirements)
            {
                var requirementRule = LoadDiscountRequirementRuleBySystemName(req.DiscountRequirementRuleSystemName);
                if (requirementRule == null)
                {
                    continue;
                }
                if (!(_storeContext.CurrentStore.Id == 0 ||
                      _settingService.GetSettingByKey <string>(requirementRule.PluginDescriptor.GetSettingKey("LimitedToStores")).ToIntArrayContains(_storeContext.CurrentStore.Id, true)))
                {
                    continue;
                }

                var request = new CheckDiscountRequirementRequest()
                {
                    DiscountRequirement = req,
                    Customer            = customer,
                    Store = _storeContext.CurrentStore
                };
                if (!requirementRule.CheckRequirement(request))
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Check discount requirements
        /// </summary>
        /// <param name="discount">Discount</param>
        /// <param name="customer">Customer</param>
        /// <param name="couponCodeToValidate">Coupon code to validate</param>
        /// <returns>true - requirement is met; otherwise, false</returns>
        public virtual bool IsDiscountValid(Discount discount, Customer customer, string couponCodeToValidate)
        {
            if (discount == null)
                throw new ArgumentNullException("discount");

            //check coupon code
            if (discount.RequiresCouponCode)
            {
                if (String.IsNullOrEmpty(discount.CouponCode))
                    return false;
                if (!discount.CouponCode.Equals(couponCodeToValidate, StringComparison.InvariantCultureIgnoreCase))
                    return false;
            }

            //check date range
            DateTime now = DateTime.UtcNow;
			int storeId = _storeContext.CurrentStore.Id;

            if (discount.StartDateUtc.HasValue)
            {
                DateTime startDate = DateTime.SpecifyKind(discount.StartDateUtc.Value, DateTimeKind.Utc);
                if (startDate.CompareTo(now) > 0)
                    return false;
            }
            if (discount.EndDateUtc.HasValue)
            {
                DateTime endDate = DateTime.SpecifyKind(discount.EndDateUtc.Value, DateTimeKind.Utc);
                if (endDate.CompareTo(now) < 0)
                    return false;
            }

            if (!CheckDiscountLimitations(discount, customer))
                return false;

            // discount requirements
            var requirements = discount.DiscountRequirements;
            foreach (var req in requirements)
            {
				var requirementRule = LoadDiscountRequirementRuleBySystemName(req.DiscountRequirementRuleSystemName, storeId);
                if (requirementRule == null)
                    continue;

                var request = new CheckDiscountRequirementRequest()
                {
                    DiscountRequirement = req,
                    Customer = customer,
					Store = _storeContext.CurrentStore
                };
                if (!requirementRule.Value.CheckRequirement(request))
                    return false;
            }

			// better not to apply discounts if there are gift cards in the cart cause the customer could "earn" money through that.
			if (discount.DiscountType == DiscountType.AssignedToOrderTotal || discount.DiscountType == DiscountType.AssignedToOrderSubTotal)
			{
				var cart = customer.GetCartItems(ShoppingCartType.ShoppingCart, storeId);

				if (cart.Any(x => x.Item.Product.IsGiftCard))
					return false;
			}

            return true;
        }
        public override bool CheckRequirement(CheckDiscountRequirementRequest request)
        {
			if (request == null)
				throw new ArgumentNullException("request");

			if (request.DiscountRequirement == null)
				throw new SmartException("Discount requirement is not set");

			if (String.IsNullOrWhiteSpace(request.DiscountRequirement.RestrictedProductIds))
				return true;

			if (request.Customer == null)
				return false;

			//we support three ways of specifying products:
			//1. The comma-separated list of product identifiers (e.g. 77, 123, 156).
			//2. The comma-separated list of product identifiers with quantities.
			//      {Product ID}:{Quantity}. For example, 77:1, 123:2, 156:3
			//3. The comma-separated list of product identifiers with quantity range.
			//      {Product ID}:{Min quantity}-{Max quantity}. For example, 77:1-3, 123:2-5, 156:3-8
			var restrictedProducts = request.DiscountRequirement.RestrictedProductIds
				.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				.Select(x => x.Trim())
				.ToList();
			if (restrictedProducts.Count == 0)
				return false;

			//cart
			var cart = request.Customer.GetCartItems(ShoppingCartType.ShoppingCart, request.Store.Id);

			bool allFound = true;
			foreach (var restrictedProduct in restrictedProducts)
			{
				if (String.IsNullOrWhiteSpace(restrictedProduct))
					continue;

				bool found1 = false;
				foreach (var sci in cart)
				{
					if (restrictedProduct.Contains(":"))
					{
						if (restrictedProduct.Contains("-"))
						{
							//the third way (the quantity rage specified)
							//{Product ID}:{Min quantity}-{Max quantity}. For example, 77:1-3, 123:2-5, 156:3-8
							int restrictedProductId = 0;
							if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[0], out restrictedProductId))
								//parsing error; exit;
								return false;
							int quantityMin = 0;
							if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[1].Split(new[] { '-' })[0], out quantityMin))
								//parsing error; exit;
								return false;
							int quantityMax = 0;
							if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[1].Split(new[] { '-' })[1], out quantityMax))
								//parsing error; exit;
								return false;

							if (sci.Item.ProductId == restrictedProductId && quantityMin <= sci.Item.Quantity && sci.Item.Quantity <= quantityMax)
							{
								found1 = true;
								break;
							}
						}
						else
						{
							//the second way (the quantity specified)
							//{Product ID}:{Quantity}. For example, 77:1, 123:2, 156:3
							int restrictedProductId = 0;
							if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[0], out restrictedProductId))
								//parsing error; exit;
								return false;
							int quantity = 0;
							if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[1], out quantity))
								//parsing error; exit;
								return false;

							if (sci.Item.ProductId == restrictedProductId && sci.Item.Quantity == quantity)
							{
								found1 = true;
								break;
							}
						}
					}
					else
					{
						//the first way (the quantity is not specified)
						int restrictedProductId = int.Parse(restrictedProduct);
						if (sci.Item.ProductId == restrictedProductId)
						{
							found1 = true;
							break;
						}
					}
				}

				if (!found1)
				{
					allFound = false;
					break;
				}
			}

			if (allFound)
				return true;

			return false;
        }
 /// <summary>
 /// Check discount requirement
 /// </summary>
 /// <param name="request">Object that contains all information required to check the requirement (Current customer, discount, etc)</param>
 /// <returns>true - requirement is met; otherwise, false</returns>
 public bool CheckRequirement(CheckDiscountRequirementRequest request)
 {
     return true;
 }
		public abstract bool CheckRequirement(CheckDiscountRequirementRequest request);
        /// <summary>
        /// Check discount requirements
        /// </summary>
        /// <param name="discount">Discount</param>
        /// <param name="customer">Customer</param>
        /// <param name="couponCodeToValidate">Coupon code to validate</param>
        /// <returns>true - requirement is met; otherwise, false</returns>
        public virtual bool IsDiscountValid(Discount discount, Customer customer, string couponCodeToValidate)
        {
            if (discount == null)
                throw new ArgumentNullException("discount");

            //check coupon code
            if (discount.RequiresCouponCode)
            {
                if (String.IsNullOrEmpty(discount.CouponCode))
                    return false;
                if (!discount.CouponCode.Equals(couponCodeToValidate, StringComparison.InvariantCultureIgnoreCase))
                    return false;
            }

            //check date range
            DateTime now = DateTime.UtcNow;
            if (discount.StartDateUtc.HasValue)
            {
                DateTime startDate = DateTime.SpecifyKind(discount.StartDateUtc.Value, DateTimeKind.Utc);
                if (startDate.CompareTo(now) > 0)
                    return false;
            }
            if (discount.EndDateUtc.HasValue)
            {
                DateTime endDate = DateTime.SpecifyKind(discount.EndDateUtc.Value, DateTimeKind.Utc);
                if (endDate.CompareTo(now) < 0)
                    return false;
            }

            if (!CheckDiscountLimitations(discount, customer))
                return false;

            //discount requirements
            var requirements = discount.DiscountRequirements;
            foreach (var req in requirements)
            {
                var requirementRule = LoadDiscountRequirementRuleBySystemName(req.DiscountRequirementRuleSystemName);
                if (requirementRule == null)
                    continue;
				if (!(_storeContext.CurrentStore.Id == 0 || 
					_settingService.GetSettingByKey<string>(requirementRule.PluginDescriptor.GetSettingKey("LimitedToStores")).ToIntArrayContains(_storeContext.CurrentStore.Id, true)))
					continue;

                var request = new CheckDiscountRequirementRequest()
                {
                    DiscountRequirement = req,
                    Customer = customer,
					Store = _storeContext.CurrentStore
                };
                if (!requirementRule.CheckRequirement(request))
                    return false;
            }
            return true;
        }