/// <summary> /// Add a product to shopping cart /// </summary> /// <param name="customer">Customer</param> /// <param name="product">Product</param> /// <param name="shoppingCartType">Shopping cart type</param> /// <param name="storeId">Store identifier</param> /// <param name="selectedAttributes">Selected attributes</param> /// <param name="customerEnteredPrice">The price enter by a customer</param> /// <param name="quantity">Quantity</param> /// <param name="automaticallyAddRequiredProductsIfEnabled">Automatically add required products if enabled</param> /// <param name="shoppingCartItemId">Identifier fo the new shopping cart item</param> /// <param name="parentItemId">Identifier of the parent shopping cart item</param> /// <param name="bundleItem">Product bundle item</param> /// <returns>Warnings</returns> public virtual IList<string> AddToCart(Customer customer, Product product, ShoppingCartType shoppingCartType, int storeId, string selectedAttributes, decimal customerEnteredPrice, int quantity, bool automaticallyAddRequiredProductsIfEnabled, out int shoppingCartItemId, int? parentItemId = null, ProductBundleItem bundleItem = null) { shoppingCartItemId = 0; if (customer == null) throw new ArgumentNullException("customer"); if (product == null) throw new ArgumentNullException("product"); var warnings = new List<string>(); if (shoppingCartType == ShoppingCartType.ShoppingCart && !_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart, customer)) { warnings.Add("Shopping cart is disabled"); return warnings; } if (shoppingCartType == ShoppingCartType.Wishlist && !_permissionService.Authorize(StandardPermissionProvider.EnableWishlist, customer)) { warnings.Add("Wishlist is disabled"); return warnings; } if (quantity <= 0) { warnings.Add(_localizationService.GetResource("ShoppingCart.QuantityShouldPositive")); return warnings; } if (parentItemId.HasValue && (parentItemId.Value == 0 || bundleItem == null || bundleItem.Id == 0)) { warnings.Add(_localizationService.GetResource("ShoppingCart.Bundle.BundleItemNotFound").FormatWith(bundleItem.GetLocalizedName())); return warnings; } //reset checkout info _customerService.ResetCheckoutData(customer, storeId); var cart = customer.GetCartItems(shoppingCartType, storeId); OrganizedShoppingCartItem shoppingCartItem = null; if (bundleItem == null) { shoppingCartItem = FindShoppingCartItemInTheCart(cart, shoppingCartType, product, selectedAttributes, customerEnteredPrice); } if (shoppingCartItem != null) { //update existing shopping cart item int newQuantity = shoppingCartItem.Item.Quantity + quantity; warnings.AddRange( GetShoppingCartItemWarnings(customer, shoppingCartType, product, storeId, selectedAttributes, customerEnteredPrice, newQuantity, automaticallyAddRequiredProductsIfEnabled, bundleItem: bundleItem) ); if (warnings.Count == 0) { shoppingCartItem.Item.AttributesXml = selectedAttributes; shoppingCartItem.Item.Quantity = newQuantity; shoppingCartItem.Item.UpdatedOnUtc = DateTime.UtcNow; _customerService.UpdateCustomer(customer); //event notification _eventPublisher.EntityUpdated(shoppingCartItem.Item); } } else { //new shopping cart item warnings.AddRange( GetShoppingCartItemWarnings(customer, shoppingCartType, product, storeId, selectedAttributes, customerEnteredPrice, quantity, automaticallyAddRequiredProductsIfEnabled, bundleItem: bundleItem) ); if (warnings.Count == 0) { //maximum items validation switch (shoppingCartType) { case ShoppingCartType.ShoppingCart: if (cart.Count >= _shoppingCartSettings.MaximumShoppingCartItems) { warnings.Add(_localizationService.GetResource("ShoppingCart.MaximumShoppingCartItems")); return warnings; } break; case ShoppingCartType.Wishlist: if (cart.Count >= _shoppingCartSettings.MaximumWishlistItems) { warnings.Add(_localizationService.GetResource("ShoppingCart.MaximumWishlistItems")); return warnings; } break; default: break; } DateTime now = DateTime.UtcNow; var cartItem = new ShoppingCartItem() { ShoppingCartType = shoppingCartType, StoreId = storeId, Product = product, AttributesXml = selectedAttributes, CustomerEnteredPrice = customerEnteredPrice, Quantity = quantity, CreatedOnUtc = now, UpdatedOnUtc = now, ParentItemId = parentItemId }; if (bundleItem != null) cartItem.BundleItemId = bundleItem.Id; customer.ShoppingCartItems.Add(cartItem); _customerService.UpdateCustomer(customer); shoppingCartItemId = cartItem.Id; //event notification _eventPublisher.EntityInserted(cartItem); } } return warnings; }
/// <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; }
/// <summary> /// Validates required products (products which require other variant to be added to the cart) /// </summary> /// <param name="customer">Customer</param> /// <param name="shoppingCartType">Shopping cart type</param> /// <param name="product">Product</param> /// <param name="storeId">Store identifier</param> /// <param name="automaticallyAddRequiredProductsIfEnabled">Automatically add required products if enabled</param> /// <returns>Warnings</returns> public virtual IList<string> GetRequiredProductWarnings(Customer customer, ShoppingCartType shoppingCartType, Product product, int storeId, bool automaticallyAddRequiredProductsIfEnabled) { if (customer == null) throw new ArgumentNullException("customer"); if (product == null) throw new ArgumentNullException("product"); var cart = customer.GetCartItems(shoppingCartType, storeId); var warnings = new List<string>(); if (product.RequireOtherProducts) { var requiredProducts = new List<Product>(); foreach (var id in product.ParseRequiredProductIds()) { var rp = _productService.GetProductById(id); if (rp != null) requiredProducts.Add(rp); } foreach (var rp in requiredProducts) { //ensure that product is in the cart bool alreadyInTheCart = false; foreach (var sci in cart) { if (sci.Item.ProductId == rp.Id) { alreadyInTheCart = true; break; } } //not in the cart if (!alreadyInTheCart) { if (product.AutomaticallyAddRequiredProducts) { //add to cart (if possible) if (automaticallyAddRequiredProductsIfEnabled) { //pass 'false' for 'automaticallyAddRequiredProducsIfEnabled' to prevent circular references int shoppingCartItemId; var addToCartWarnings = AddToCart(customer, rp, shoppingCartType, storeId, "", decimal.Zero, 1, false, out shoppingCartItemId); if (addToCartWarnings.Count > 0) { //a product wasn't atomatically added for some reasons //don't display specific errors from 'addToCartWarnings' variable //display only generic error warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.RequiredProductWarning"), rp.GetLocalized(x => x.Name))); } } else { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.RequiredProductWarning"), rp.GetLocalized(x => x.Name))); } } else { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.RequiredProductWarning"), rp.GetLocalized(x => x.Name))); } } } } return warnings; }
/// <summary> /// Add product to cart /// </summary> /// <param name="customer">The customer</param> /// <param name="product">The product</param> /// <param name="cartType">Cart type</param> /// <param name="storeId">Store identifier</param> /// <param name="selectedAttributes">Selected attributes</param> /// <param name="customerEnteredPrice">Price entered by customer</param> /// <param name="quantity">Quantity</param> /// <param name="automaticallyAddRequiredProductsIfEnabled">Whether to add required products</param> /// <param name="ctx">Add to cart context</param> /// <returns>List with warnings</returns> public virtual List<string> AddToCart(Customer customer, Product product, ShoppingCartType cartType, int storeId, string selectedAttributes, decimal customerEnteredPrice, int quantity, bool automaticallyAddRequiredProductsIfEnabled, AddToCartContext ctx = null) { if (customer == null) throw new ArgumentNullException("customer"); if (product == null) throw new ArgumentNullException("product"); var warnings = new List<string>(); var bundleItem = (ctx == null ? null : ctx.BundleItem); if (ctx != null && bundleItem != null && ctx.Warnings.Count > 0) return ctx.Warnings; // warnings while adding bundle items to cart -> no need for further processing if (cartType == ShoppingCartType.ShoppingCart && !_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart, customer)) { warnings.Add("Shopping cart is disabled"); return warnings; } if (cartType == ShoppingCartType.Wishlist && !_permissionService.Authorize(StandardPermissionProvider.EnableWishlist, customer)) { warnings.Add("Wishlist is disabled"); return warnings; } if (quantity <= 0) { warnings.Add(_localizationService.GetResource("ShoppingCart.QuantityShouldPositive")); return warnings; } //if (parentItemId.HasValue && (parentItemId.Value == 0 || bundleItem == null || bundleItem.Id == 0)) //{ // warnings.Add(_localizationService.GetResource("ShoppingCart.Bundle.BundleItemNotFound").FormatWith(bundleItem.GetLocalizedName())); // return warnings; //} //reset checkout info _customerService.ResetCheckoutData(customer, storeId); var cart = customer.GetCartItems(cartType, storeId); OrganizedShoppingCartItem existingCartItem = null; if (bundleItem == null) { existingCartItem = FindShoppingCartItemInTheCart(cart, cartType, product, selectedAttributes, customerEnteredPrice); } if (existingCartItem != null) { //update existing shopping cart item int newQuantity = existingCartItem.Item.Quantity + quantity; warnings.AddRange( GetShoppingCartItemWarnings(customer, cartType, product, storeId, selectedAttributes, customerEnteredPrice, newQuantity, automaticallyAddRequiredProductsIfEnabled, bundleItem: bundleItem) ); if (warnings.Count == 0) { existingCartItem.Item.AttributesXml = selectedAttributes; existingCartItem.Item.Quantity = newQuantity; existingCartItem.Item.UpdatedOnUtc = DateTime.UtcNow; _customerService.UpdateCustomer(customer); //event notification _eventPublisher.EntityUpdated(existingCartItem.Item); } } else { //new shopping cart item warnings.AddRange( GetShoppingCartItemWarnings(customer, cartType, product, storeId, selectedAttributes, customerEnteredPrice, quantity, automaticallyAddRequiredProductsIfEnabled, bundleItem: bundleItem) ); if (warnings.Count == 0) { //maximum items validation if (cartType == ShoppingCartType.ShoppingCart && cart.Count >= _shoppingCartSettings.MaximumShoppingCartItems) { warnings.Add(_localizationService.GetResource("ShoppingCart.MaximumShoppingCartItems")); return warnings; } else if (cartType == ShoppingCartType.Wishlist && cart.Count >= _shoppingCartSettings.MaximumWishlistItems) { warnings.Add(_localizationService.GetResource("ShoppingCart.MaximumWishlistItems")); return warnings; } var now = DateTime.UtcNow; var cartItem = new ShoppingCartItem() { ShoppingCartType = cartType, StoreId = storeId, Product = product, AttributesXml = selectedAttributes, CustomerEnteredPrice = customerEnteredPrice, Quantity = quantity, CreatedOnUtc = now, UpdatedOnUtc = now, ParentItemId = null //parentItemId }; if (bundleItem != null) cartItem.BundleItemId = bundleItem.Id; if (ctx == null) { customer.ShoppingCartItems.Add(cartItem); _customerService.UpdateCustomer(customer); _eventPublisher.EntityInserted(cartItem); } else { if (bundleItem == null) { Debug.Assert(ctx.Item == null, "Add to cart item already specified"); ctx.Item = cartItem; } else { ctx.ChildItems.Add(cartItem); } } } } return warnings; }