public void Can_save_and_load_shoppingCartItem() { var sci = new ShoppingCartItem { ShoppingCartType = ShoppingCartType.ShoppingCart, AttributesXml = "AttributesXml 1", CustomerEnteredPrice = 1.1M, Quantity= 2, CreatedOnUtc = new DateTime(2010, 01, 01), UpdatedOnUtc = new DateTime(2010, 01, 02), Customer = GetTestCustomer(), ProductVariant = GetTestProductVariant() }; var fromDb = SaveAndLoadEntity(sci); fromDb.ShouldNotBeNull(); fromDb.ShoppingCartType.ShouldEqual(ShoppingCartType.ShoppingCart); fromDb.AttributesXml.ShouldEqual("AttributesXml 1"); fromDb.CustomerEnteredPrice.ShouldEqual(1.1M); fromDb.Quantity.ShouldEqual(2); fromDb.CreatedOnUtc.ShouldEqual(new DateTime(2010, 01, 01)); fromDb.UpdatedOnUtc.ShouldEqual(new DateTime(2010, 01, 02)); fromDb.Customer.ShouldNotBeNull(); fromDb.ProductVariant.ShouldNotBeNull(); }
public void Can_get_shoppingCart_totalWeight_without_attributes() { var sci1 = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, Product = new Product() { Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M } }; var sci2 = new ShoppingCartItem() { AttributesXml = "", Quantity = 4, Product = new Product() { Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M } }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; _shippingService.GetShoppingCartTotalWeight(cart).ShouldEqual(50.5M); }
public void Can_get_shoppingCartItem_additional_shippingCharge() { var sci1 = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, ProductVariant = new ProductVariant() { Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M, AdditionalShippingCharge = 5.5M, IsShipEnabled = true, } }; var sci2 = new ShoppingCartItem() { AttributesXml = "", Quantity = 4, ProductVariant = new ProductVariant() { Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 6.5M, IsShipEnabled = true, } }; //sci3 is not shippable var sci3 = new ShoppingCartItem() { AttributesXml = "", Quantity = 5, ProductVariant = new ProductVariant() { Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 7.5M, IsShipEnabled = false, } }; var cart = new List<ShoppingCartItem>() { sci1, sci2, sci3 }; _shippingService.GetShoppingCartAdditionalShippingCharge(cart).ShouldEqual(42.5M); }
public void Can_get_shoppingCartItem_totalWeight_without_attributes() { var sci = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, Product = new Product() { Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M } }; _shippingService.GetShoppingCartItemTotalWeight(sci).ShouldEqual(4.5M); }
public ProductMappingItem RetrieveFromShoppingCartItem(ShoppingCartItem shoppingCartItem) { string attributesXml = string.Empty; var product = _productService.GetProductById(shoppingCartItem.ProductId); if (product.ProductAttributeMappings != null && product.ProductAttributeMappings.Count > 0) attributesXml = shoppingCartItem.AttributesXml; if (product.ProductAttributeCombinations != null && product.ProductAttributeCombinations.Count > 0) attributesXml = shoppingCartItem.AttributesXml; if (product.ProductAttributeMappings != null && product.ProductAttributeMappings.Count > _promoSettings.MaximumAttributesForVariants) attributesXml = string.Empty; return this._repository.Table.Where(pm => pm.EntityId == product.Id && pm.EntityName == EntityAttributeName.Product && (pm.AttributesXml ?? string.Empty).Equals((attributesXml ?? string.Empty), StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); }
/// <summary> /// Add a product variant to shopping cart /// </summary> /// <param name="customer">Customer</param> /// <param name="productVariant">Product variant</param> /// <param name="shoppingCartType">Shopping cart type</param> /// <param name="selectedAttributes">Selected attributes</param> /// <param name="customerEnteredPrice">The price enter by a customer</param> /// <param name="quantity">Quantity</param> /// <param name="automaticallyAddRequiredProductVariantsIfEnabled">Automatically add required product variants if enabled</param> /// <returns>Warnings</returns> public virtual IList<string> AddToCart(Customer customer, ProductVariant productVariant, ShoppingCartType shoppingCartType, string selectedAttributes, decimal customerEnteredPrice, int quantity, bool automaticallyAddRequiredProductVariantsIfEnabled) { if (customer == null) throw new ArgumentNullException("customer"); if (productVariant == null) throw new ArgumentNullException("productVariant"); 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; } //reset checkout info _customerService.ResetCheckoutData(customer); var cart = customer.ShoppingCartItems.Where(sci=>sci.ShoppingCartType == shoppingCartType).ToList(); var shoppingCartItem = FindShoppingCartItemInTheCart(cart, shoppingCartType, productVariant, selectedAttributes, customerEnteredPrice); if (shoppingCartItem != null) { //update existing shopping cart item int newQuantity = shoppingCartItem.Quantity + quantity; warnings.AddRange(GetShoppingCartItemWarnings(customer, shoppingCartType, productVariant, selectedAttributes, customerEnteredPrice, newQuantity, automaticallyAddRequiredProductVariantsIfEnabled)); if (warnings.Count == 0) { shoppingCartItem.AttributesXml = selectedAttributes; shoppingCartItem.Quantity = newQuantity; shoppingCartItem.UpdatedOnUtc = DateTime.UtcNow; _customerService.UpdateCustomer(customer); //event notification _eventPublisher.EntityUpdated(shoppingCartItem); } } else { //new shopping cart item warnings.AddRange(GetShoppingCartItemWarnings(customer, shoppingCartType, productVariant, selectedAttributes, customerEnteredPrice, quantity, automaticallyAddRequiredProductVariantsIfEnabled)); if (warnings.Count == 0) { //maximum items validation switch (shoppingCartType) { case ShoppingCartType.ShoppingCart: { if (cart.Count >= _shoppingCartSettings.MaximumShoppingCartItems) return warnings; } break; case ShoppingCartType.Wishlist: { if (cart.Count >= _shoppingCartSettings.MaximumWishlistItems) return warnings; } break; default: break; } DateTime now = DateTime.UtcNow; shoppingCartItem = new ShoppingCartItem() { ShoppingCartType = shoppingCartType, ProductVariant = productVariant, AttributesXml = selectedAttributes, CustomerEnteredPrice = customerEnteredPrice, Quantity = quantity, CreatedOnUtc = now, UpdatedOnUtc = now }; customer.ShoppingCartItems.Add(shoppingCartItem); _customerService.UpdateCustomer(customer); //event notification _eventPublisher.EntityInserted(shoppingCartItem); } } return warnings; }
public void Can_get_shopping_cart_total_discount() { //customer var customer = new Customer() { Id = 10, }; //shopping cart var productVariant1 = new ProductVariant { Id = 1, Name = "Product variant name 1", Price = 10M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 1, Name = "Product name 1", Published = true } }; var sci1 = new ShoppingCartItem() { ProductVariant = productVariant1, ProductVariantId = productVariant1.Id, Quantity = 2, }; var productVariant2 = new ProductVariant { Id = 2, Name = "Product variant name 2", Price = 12M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 2, Name = "Product name 2", Published = true } }; var sci2 = new ShoppingCartItem() { ProductVariant = productVariant2, ProductVariantId = productVariant2.Id, Quantity = 3 }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); //discounts var discount1 = new Discount() { Id = 1, Name = "Discount 1", DiscountType = DiscountType.AssignedToOrderTotal, DiscountAmount = 3, DiscountLimitation = DiscountLimitationType.Unlimited, }; _discountService.Expect(ds => ds.IsDiscountValid(discount1, customer)).Return(true); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToOrderTotal)).Return(new List<Discount>() { discount1 }); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToCategories)).Return(new List<Discount>()); _genericAttributeService.Expect(x => x.GetAttributesForEntity(customer.Id, "Customer")) .Return(new List<GenericAttribute>() { new GenericAttribute() { StoreId = _store.Id, EntityId = customer.Id, Key = SystemCustomerAttributeNames.SelectedPaymentMethod, KeyGroup = "Customer", Value = "test1" } }); _paymentService.Expect(ps => ps.GetAdditionalHandlingFee(cart, "test1")).Return(20); decimal discountAmount; Discount appliedDiscount; List<AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; //shipping is taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; //56 - items, 10 - shipping (fixed), 20 - payment fee, 8.6 - tax, [-3] - discount _orderTotalCalcService.GetShoppingCartTotal(cart, out discountAmount, out appliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount) .ShouldEqual(91.6M); discountAmount.ShouldEqual(3); appliedDiscount.ShouldNotBeNull(); appliedDiscount.Name.ShouldEqual("Discount 1"); }
public void Can_get_shopping_cart_subTotal_discount_including_tax() { //customer Customer customer = new Customer(); //shopping cart var productVariant1 = new ProductVariant { Id = 1, Name = "Product variant name 1", Price = 12.34M, CustomerEntersPrice = false, Published = true, Product = new Product() { Id = 1, Name = "Product name 1", Published = true } }; var sci1 = new ShoppingCartItem() { ProductVariant = productVariant1, ProductVariantId = productVariant1.Id, Quantity = 2, }; var productVariant2 = new ProductVariant { Id = 2, Name = "Product variant name 2", Price = 21.57M, CustomerEntersPrice = false, Published = true, Product = new Product() { Id = 2, Name = "Product name 2", Published = true } }; var sci2 = new ShoppingCartItem() { ProductVariant = productVariant2, ProductVariantId = productVariant2.Id, Quantity = 3 }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); //discounts var discount1 = new Discount() { Id = 1, Name = "Discount 1", DiscountType = DiscountType.AssignedToOrderSubTotal, DiscountAmount = 3, DiscountLimitation = DiscountLimitationType.Unlimited, }; _discountService.Expect(ds => ds.IsDiscountValid(discount1, customer)).Return(true); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToOrderSubTotal)).Return(new List<Discount>() { discount1 }); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToCategories)).Return(new List<Discount>()); decimal discountAmount; Discount appliedDiscount; decimal subTotalWithoutDiscount; decimal subTotalWithDiscount; SortedDictionary<decimal, decimal> taxRates; _orderTotalCalcService.GetShoppingCartSubTotal(cart, true, out discountAmount, out appliedDiscount, out subTotalWithoutDiscount, out subTotalWithDiscount, out taxRates); //TODO strange. Why does the commented test fail? discountAmount.ShouldEqual(3.3); //discountAmount.ShouldEqual(3.3); appliedDiscount.ShouldNotBeNull(); appliedDiscount.Name.ShouldEqual("Discount 1"); subTotalWithoutDiscount.ShouldEqual(98.329); subTotalWithDiscount.ShouldEqual(95.029); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(8.639); }
public void Can_get_shipping_total_discount_including_tax() { var sci1 = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, ProductVariant = new ProductVariant() { Id = 1, Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M, AdditionalShippingCharge = 5.5M, IsShipEnabled = true, } }; var sci2 = new ShoppingCartItem() { AttributesXml = "", Quantity = 4, ProductVariant = new ProductVariant() { Id = 2, Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 6.5M, IsShipEnabled = true, } }; //sci3 is not shippable var sci3 = new ShoppingCartItem() { AttributesXml = "", Quantity = 5, ProductVariant = new ProductVariant() { Id = 3, Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 7.5M, IsShipEnabled = false, } }; var cart = new List<ShoppingCartItem>() { sci1, sci2, sci3 }; var customer = new Customer(); cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); //discounts var discount1 = new Discount() { Id = 1, Name = "Discount 1", DiscountType = DiscountType.AssignedToShipping, DiscountAmount = 3, DiscountLimitation = DiscountLimitationType.Unlimited, }; _discountService.Expect(ds => ds.IsDiscountValid(discount1, customer)).Return(true); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToShipping)).Return(new List<Discount>() { discount1 }); decimal taxRate = decimal.Zero; Discount appliedDiscount = null; decimal? shipping = null; shipping = _orderTotalCalcService.GetShoppingCartShippingTotal(cart, true, out taxRate, out appliedDiscount); appliedDiscount.ShouldNotBeNull(); appliedDiscount.Name.ShouldEqual("Discount 1"); shipping.ShouldNotBeNull(); //10 - default fixed shipping rate, 42.5 - additional shipping change, -3 - discount shipping.ShouldEqual(54.45); //10 - default fixed tax rate taxRate.ShouldEqual(10); }
public void Shipping_should_be_free_when_customer_is_in_role_with_free_shipping() { var sci1 = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, ProductVariant = new ProductVariant() { Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M, IsFreeShipping = false, IsShipEnabled = true, } }; var sci2 = new ShoppingCartItem() { AttributesXml = "", Quantity = 4, ProductVariant = new ProductVariant() { Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, IsFreeShipping = false, IsShipEnabled = true, } }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; var customer = new Customer(); var customerRole1 = new CustomerRole() { Active = true, FreeShipping = true, }; var customerRole2 = new CustomerRole() { Active = true, FreeShipping = false, }; customer.CustomerRoles.Add(customerRole1); customer.CustomerRoles.Add(customerRole2); cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); _orderTotalCalcService.IsFreeShipping(cart).ShouldEqual(true); }
/// <summary> /// Gets the shopping cart unit price (one item) /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <returns>Shopping cart unit price (one item)</returns> public virtual decimal GetUnitPrice(ShoppingCartItem shoppingCartItem, bool includeDiscounts) { var customer = shoppingCartItem.Customer; decimal finalPrice = decimal.Zero; var productVariant = shoppingCartItem.ProductVariant; if (productVariant != null) { decimal attributesTotalPrice = decimal.Zero; var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.AttributesXml); if (pvaValues != null) { foreach (var pvaValue in pvaValues) { attributesTotalPrice += pvaValue.PriceAdjustment; } } if (productVariant.CustomerEntersPrice) { finalPrice = shoppingCartItem.CustomerEnteredPrice; } else { finalPrice = GetFinalPrice(productVariant, customer, attributesTotalPrice, includeDiscounts, shoppingCartItem.Quantity); } } if (_shoppingCartSettings.RoundPricesDuringCalculation) finalPrice = Math.Round(finalPrice, 2); return finalPrice; }
/// <summary> /// Get dimensions of associated products (for quantity 1) /// </summary> /// <param name="shoppingCartItem">Shopping cart item</param> /// <param name="width">Width</param> /// <param name="length">Length</param> /// <param name="height">Height</param> public virtual void GetAssociatedProductDimensions(ShoppingCartItem shoppingCartItem, out decimal width, out decimal length, out decimal height) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); width = length = height = decimal.Zero; //attributes if (String.IsNullOrEmpty(shoppingCartItem.AttributesXml)) return; //bundled products (associated attributes) var attributeValues = _productAttributeParser.ParseProductAttributeValues(shoppingCartItem.AttributesXml) .Where(x => x.AttributeValueType == AttributeValueType.AssociatedToProduct) .ToList(); foreach (var attributeValue in attributeValues) { var associatedProduct = _productService.GetProductById(attributeValue.AssociatedProductId); if (associatedProduct != null && associatedProduct.IsShipEnabled) { width += associatedProduct.Width*attributeValue.Quantity; length += associatedProduct.Length * attributeValue.Quantity; height += associatedProduct.Height*attributeValue.Quantity; } } }
/// <summary> /// Gets shopping cart item weight (of one item) /// </summary> /// <param name="shoppingCartItem">Shopping cart item</param> /// <returns>Shopping cart item weight</returns> public virtual decimal GetShoppingCartItemWeight(ShoppingCartItem shoppingCartItem) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); if (shoppingCartItem.Product == null) return decimal.Zero; //attribute weight decimal attributesTotalWeight = decimal.Zero; if (!String.IsNullOrEmpty(shoppingCartItem.AttributesXml)) { var attributeValues = _productAttributeParser.ParseProductAttributeValues(shoppingCartItem.AttributesXml); foreach (var attributeValue in attributeValues) { switch (attributeValue.AttributeValueType) { case AttributeValueType.Simple: { //simple attribute attributesTotalWeight += attributeValue.WeightAdjustment; } break; case AttributeValueType.AssociatedToProduct: { //bundled product var associatedProduct = _productService.GetProductById(attributeValue.AssociatedProductId); if (associatedProduct != null && associatedProduct.IsShipEnabled) { attributesTotalWeight += associatedProduct.Weight * attributeValue.Quantity; } } break; } } } var weight = shoppingCartItem.Product.Weight + attributesTotalWeight; return weight; }
/// <summary> /// Gets the shopping cart item sub total /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscounts">Applied discounts</param> /// <returns>Shopping cart item sub total</returns> public virtual decimal GetSubTotal(ShoppingCartItem shoppingCartItem, bool includeDiscounts, out decimal discountAmount, out List<Discount> appliedDiscounts) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); decimal subTotal; //unit price var unitPrice = GetUnitPrice(shoppingCartItem, includeDiscounts, out discountAmount, out appliedDiscounts); //discount if (appliedDiscounts.Any()) { //we can properly use "MaximumDiscountedQuantity" property only for one discount (not cumulative ones) Discount oneAndOnlyDiscount = null; if (appliedDiscounts.Count == 1) oneAndOnlyDiscount = appliedDiscounts.First(); if (oneAndOnlyDiscount != null && oneAndOnlyDiscount.MaximumDiscountedQuantity.HasValue && shoppingCartItem.Quantity > oneAndOnlyDiscount.MaximumDiscountedQuantity.Value) { //we cannot apply discount for all shopping cart items var discountedQuantity = oneAndOnlyDiscount.MaximumDiscountedQuantity.Value; var discountedSubTotal = unitPrice * discountedQuantity; discountAmount = discountAmount * discountedQuantity; var notDiscountedQuantity = shoppingCartItem.Quantity - discountedQuantity; var notDiscountedUnitPrice = GetUnitPrice(shoppingCartItem, false); var notDiscountedSubTotal = notDiscountedUnitPrice*notDiscountedQuantity; subTotal = discountedSubTotal + notDiscountedSubTotal; } else { //discount is applied to all items (quantity) //calculate discount amount for all items discountAmount = discountAmount * shoppingCartItem.Quantity; subTotal = unitPrice * shoppingCartItem.Quantity; } } else { subTotal = unitPrice * shoppingCartItem.Quantity; } return subTotal; }
/// <summary> /// Gets the shopping cart item sub total /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <returns>Shopping cart item sub total</returns> public virtual decimal GetSubTotal(ShoppingCartItem shoppingCartItem, bool includeDiscounts = true) { decimal discountAmount; List<Discount> appliedDiscounts; return GetSubTotal(shoppingCartItem, includeDiscounts, out discountAmount, out appliedDiscounts); }
/// <summary> /// Gets discount amount /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Discount amount</returns> public virtual decimal GetDiscountAmount(ShoppingCartItem shoppingCartItem, out Discount appliedDiscount) { var customer = shoppingCartItem.Customer; appliedDiscount = null; decimal discountAmount = decimal.Zero; var productVariant = shoppingCartItem.ProductVariant; if (productVariant != null) { decimal attributesTotalPrice = decimal.Zero; var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.AttributesXml); foreach (var pvaValue in pvaValues) { attributesTotalPrice += pvaValue.PriceAdjustment; } decimal productVariantDiscountAmount = GetDiscountAmount(productVariant, customer, attributesTotalPrice, shoppingCartItem.Quantity, out appliedDiscount); discountAmount = productVariantDiscountAmount * shoppingCartItem.Quantity; } if (_shoppingCartSettings.RoundPricesDuringCalculation) discountAmount = Math.Round(discountAmount, 2); return discountAmount; }
/// <summary> /// Gets the shopping cart item sub total /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <returns>Shopping cart item sub total</returns> public virtual decimal GetSubTotal(ShoppingCartItem shoppingCartItem, bool includeDiscounts) { return GetUnitPrice(shoppingCartItem, includeDiscounts) * shoppingCartItem.Quantity; }
/// <summary> /// Gets discount amount /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Discount amount</returns> public virtual decimal GetDiscountAmount(ShoppingCartItem shoppingCartItem, out Discount appliedDiscount) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); var customer = shoppingCartItem.Customer; appliedDiscount = null; decimal totalDiscountAmount = decimal.Zero; var product = shoppingCartItem.Product; if (product != null) { decimal attributesTotalPrice = decimal.Zero; var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.AttributesXml); foreach (var pvaValue in pvaValues) { attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue); } decimal productDiscountAmount = GetDiscountAmount(product, customer, attributesTotalPrice, shoppingCartItem.Quantity, out appliedDiscount); totalDiscountAmount = productDiscountAmount * shoppingCartItem.Quantity; } if (_shoppingCartSettings.RoundPricesDuringCalculation) totalDiscountAmount = Math.Round(totalDiscountAmount, 2); return totalDiscountAmount; }
public void Can_get_tax_total() { //customer var customer = new Customer() { Id = 10, }; //shopping cart var productVariant1 = new ProductVariant { Id = 1, Name = "Product variant name 1", Price = 10M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 1, Name = "Product name 1", Published = true } }; var sci1 = new ShoppingCartItem() { ProductVariant = productVariant1, ProductVariantId = productVariant1.Id, Quantity = 2, }; var productVariant2 = new ProductVariant { Id = 2, Name = "Product variant name 2", Price = 12M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 2, Name = "Product name 2", Published = true } }; var sci2 = new ShoppingCartItem() { ProductVariant = productVariant2, ProductVariantId = productVariant2.Id, Quantity = 3 }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); _genericAttributeService.Expect(x => x.GetAttributesForEntity(customer.Id, "Customer")) .Return(new List<GenericAttribute>() { new GenericAttribute() { StoreId = _store.Id, EntityId = customer.Id, Key = SystemCustomerAttributeNames.SelectedPaymentMethod, KeyGroup = "Customer", Value = "test1" } }); _paymentService.Expect(ps => ps.GetAdditionalHandlingFee(cart, "test1")).Return(20); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToCategories)).Return(new List<Discount>()); //56 - items, 10 - shipping (fixed), 20 - payment fee //1. shipping is taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; SortedDictionary<decimal, decimal> taxRates; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(8.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(8.6); //2. shipping is taxable, payment fee is not taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = false; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(6.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(6.6); //3. shipping is not taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = false; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(7.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(7.6); //3. shipping is not taxable, payment fee is not taxable _taxSettings.ShippingIsTaxable = false; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = false; _orderTotalCalcService.GetTaxTotal(cart, out taxRates).ShouldEqual(5.6); taxRates.ShouldNotBeNull(); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(5.6); }
/// <summary> /// Gets the shopping cart item sub total /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <returns>Shopping cart item sub total</returns> public virtual decimal GetSubTotal(ShoppingCartItem shoppingCartItem, bool includeDiscounts) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); return GetUnitPrice(shoppingCartItem, includeDiscounts) * shoppingCartItem.Quantity; }
public void Shipping_should_not_be_free_when_some_of_shoppingCartItems_are_not_marked_as_freeShipping() { var sci1 = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, ProductVariant = new ProductVariant() { Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M, IsFreeShipping = true, IsShipEnabled = true, } }; var sci2 = new ShoppingCartItem() { AttributesXml = "", Quantity = 4, ProductVariant = new ProductVariant() { Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, IsFreeShipping = false, IsShipEnabled = true, } }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; var customer = new Customer(); cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); _orderTotalCalcService.IsFreeShipping(cart).ShouldEqual(false); }
/// <summary> /// Gets the shopping cart unit price (one item) /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <returns>Shopping cart unit price (one item)</returns> public virtual decimal GetUnitPrice(ShoppingCartItem shoppingCartItem, bool includeDiscounts) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); var customer = shoppingCartItem.Customer; decimal finalPrice = decimal.Zero; var product = shoppingCartItem.Product; if (product != null) { var combination = _productAttributeParser.FindProductVariantAttributeCombination(product, shoppingCartItem.AttributesXml); if (combination != null && combination.OverriddenPrice.HasValue) { finalPrice = combination.OverriddenPrice.Value; } else { //summarize price of all attributes decimal attributesTotalPrice = decimal.Zero; var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.AttributesXml); if (pvaValues != null) { foreach (var pvaValue in pvaValues) { attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue); } } //get price of a product (with previously calculated price of all attributes) if (product.CustomerEntersPrice) { finalPrice = shoppingCartItem.CustomerEnteredPrice; } else { var qty = 0; if (_shoppingCartSettings.GroupTierPricesForDistinctShoppingCartItems) { //the same products with distinct product attributes could be stored as distinct "ShoppingCartItem" records //so let's find how many of the current products are in the cart qty = customer.ShoppingCartItems .Where(x => x.ProductId == shoppingCartItem.ProductId) .Where(x => x.ShoppingCartTypeId == shoppingCartItem.ShoppingCartTypeId) .Sum(x => x.Quantity); if (qty == 0) { qty = shoppingCartItem.Quantity; } } else { qty = shoppingCartItem.Quantity; } finalPrice = GetFinalPrice(product, customer, attributesTotalPrice, includeDiscounts, qty); } } } //rounding if (_shoppingCartSettings.RoundPricesDuringCalculation) finalPrice = Math.Round(finalPrice, 2); return finalPrice; }
public void Can_get_shipping_total_with_fixed_shipping_rate_including_tax() { var sci1 = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, ProductVariant = new ProductVariant() { Id = 1, Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M, AdditionalShippingCharge = 5.5M, IsShipEnabled = true, } }; var sci2 = new ShoppingCartItem() { AttributesXml = "", Quantity = 4, ProductVariant = new ProductVariant() { Id = 2, Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 6.5M, IsShipEnabled = true, } }; //sci3 is not shippable var sci3 = new ShoppingCartItem() { AttributesXml = "", Quantity = 5, ProductVariant = new ProductVariant() { Id = 3, Weight = 11.5M, Height = 12.5M, Length = 13.5M, Width = 14.5M, AdditionalShippingCharge = 7.5M, IsShipEnabled = false, } }; var cart = new List<ShoppingCartItem>() { sci1, sci2, sci3 }; var customer = new Customer(); cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); decimal taxRate = decimal.Zero; Discount appliedDiscount = null; decimal? shipping = null; shipping = _orderTotalCalcService.GetShoppingCartShippingTotal(cart, true, out taxRate, out appliedDiscount); shipping.ShouldNotBeNull(); //10 - default fixed shipping rate, 42.5 - additional shipping change shipping.ShouldEqual(57.75); appliedDiscount.ShouldBeNull(); //10 - default fixed tax rate taxRate.ShouldEqual(10); }
protected virtual PictureModel PrepareCartItemPictureModel(ShoppingCartItem sci, int pictureSize, bool showDefaultPicture, string productName) { var pictureCacheKey = string.Format(ModelCacheEventConsumer.CART_PICTURE_MODEL_KEY, sci.Id, pictureSize, true, _workContext.WorkingLanguage.Id, _webHelper.IsCurrentConnectionSecured(), _storeContext.CurrentStore.Id); var model = _cacheManager.Get(pictureCacheKey, //as we cache per user (shopping cart item identifier) //let's cache just for 3 minutes 3, () => { //shopping cart item picture Picture sciPicture = null; //first, let's see whether a shopping cart item has some attribute values with custom pictures var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(sci.AttributesXml); foreach (var pvaValue in pvaValues) { var pvavPicture = _pictureService.GetPictureById(pvaValue.PictureId); if (pvavPicture != null) { sciPicture = pvavPicture; break; } } //now let's load the default product picture var product = sci.Product; if (sciPicture == null) { sciPicture = _pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault(); } //let's check whether this product has some parent "grouped" product if (sciPicture == null && !product.VisibleIndividually && product.ParentGroupedProductId > 0) { sciPicture = _pictureService.GetPicturesByProductId(product.ParentGroupedProductId, 1).FirstOrDefault(); } return new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(sciPicture, pictureSize, showDefaultPicture), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), productName), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), productName), }; }); return model; }
public void Can_get_shopping_cart_subTotal_including_tax() { //customer Customer customer = new Customer(); //shopping cart var productVariant1 = new ProductVariant { Id = 1, Name = "Product variant name 1", Price = 12.34M, CustomerEntersPrice = false, Published = true, Product = new Product() { Id = 1, Name = "Product name 1", Published = true } }; var sci1 = new ShoppingCartItem() { ProductVariant = productVariant1, ProductVariantId = productVariant1.Id, Quantity = 2, }; var productVariant2 = new ProductVariant { Id = 2, Name = "Product variant name 2", Price = 21.57M, CustomerEntersPrice = false, Published = true, Product = new Product() { Id = 2, Name = "Product name 2", Published = true } }; var sci2 = new ShoppingCartItem() { ProductVariant = productVariant2, ProductVariantId = productVariant2.Id, Quantity = 3 }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToCategories)).Return(new List<Discount>()); decimal discountAmount; Discount appliedDiscount; decimal subTotalWithoutDiscount; decimal subTotalWithDiscount; SortedDictionary<decimal, decimal> taxRates; _orderTotalCalcService.GetShoppingCartSubTotal(cart, true, out discountAmount, out appliedDiscount, out subTotalWithoutDiscount, out subTotalWithDiscount, out taxRates); discountAmount.ShouldEqual(0); appliedDiscount.ShouldBeNull(); subTotalWithoutDiscount.ShouldEqual(98.329); subTotalWithDiscount.ShouldEqual(98.329); taxRates.Count.ShouldEqual(1); taxRates.ContainsKey(10).ShouldBeTrue(); taxRates[10].ShouldEqual(8.939); }
/// <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="attributesXml">Attributes in XML format</param> /// <param name="customerEnteredPrice">The price enter by a customer</param> /// <param name="rentalStartDate">Rental start date</param> /// <param name="rentalEndDate">Rental end date</param> /// <param name="quantity">Quantity</param> /// <param name="automaticallyAddRequiredProductsIfEnabled">Automatically add required products if enabled</param> /// <returns>Warnings</returns> public virtual IList<string> AddToCart(Customer customer, Product product, ShoppingCartType shoppingCartType, int storeId, string attributesXml = null, decimal customerEnteredPrice = decimal.Zero, DateTime? rentalStartDate = null, DateTime? rentalEndDate = null, int quantity = 1, bool automaticallyAddRequiredProductsIfEnabled = true) { 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 (customer.IsSearchEngineAccount()) { warnings.Add("Search engine can't add to cart"); return warnings; } if (quantity <= 0) { warnings.Add(_localizationService.GetResource("ShoppingCart.QuantityShouldPositive")); return warnings; } //reset checkout info _customerService.ResetCheckoutData(customer, storeId); var cart = customer.ShoppingCartItems .Where(sci => sci.ShoppingCartType == shoppingCartType) .LimitPerStore(storeId) .ToList(); var shoppingCartItem = FindShoppingCartItemInTheCart(cart, shoppingCartType, product, attributesXml, customerEnteredPrice, rentalStartDate, rentalEndDate); if (shoppingCartItem != null) { //update existing shopping cart item int newQuantity = shoppingCartItem.Quantity + quantity; warnings.AddRange(GetShoppingCartItemWarnings(customer, shoppingCartType, product, storeId, attributesXml, customerEnteredPrice, rentalStartDate, rentalEndDate, newQuantity, automaticallyAddRequiredProductsIfEnabled)); if (warnings.Count == 0) { shoppingCartItem.AttributesXml = attributesXml; shoppingCartItem.Quantity = newQuantity; shoppingCartItem.UpdatedOnUtc = DateTime.UtcNow; _customerService.UpdateCustomer(customer); //event notification _eventPublisher.EntityUpdated(shoppingCartItem); } } else { //new shopping cart item warnings.AddRange(GetShoppingCartItemWarnings(customer, shoppingCartType, product, storeId, attributesXml, customerEnteredPrice, rentalStartDate, rentalEndDate, quantity, automaticallyAddRequiredProductsIfEnabled)); if (warnings.Count == 0) { //maximum items validation switch (shoppingCartType) { case ShoppingCartType.ShoppingCart: { if (cart.Count >= _shoppingCartSettings.MaximumShoppingCartItems) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.MaximumShoppingCartItems"), _shoppingCartSettings.MaximumShoppingCartItems)); return warnings; } } break; case ShoppingCartType.Wishlist: { if (cart.Count >= _shoppingCartSettings.MaximumWishlistItems) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.MaximumWishlistItems"), _shoppingCartSettings.MaximumWishlistItems)); return warnings; } } break; default: break; } DateTime now = DateTime.UtcNow; shoppingCartItem = new ShoppingCartItem { ShoppingCartType = shoppingCartType, StoreId = storeId, Product = product, AttributesXml = attributesXml, CustomerEnteredPrice = customerEnteredPrice, Quantity = quantity, RentalStartDateUtc = rentalStartDate, RentalEndDateUtc = rentalEndDate, CreatedOnUtc = now, UpdatedOnUtc = now }; customer.ShoppingCartItems.Add(shoppingCartItem); _customerService.UpdateCustomer(customer); //updated "HasShoppingCartItems" property used for performance optimization customer.HasShoppingCartItems = customer.ShoppingCartItems.Count > 0; _customerService.UpdateCustomer(customer); //event notification _eventPublisher.EntityInserted(shoppingCartItem); } } return warnings; }
public void Can_get_shopping_cart_total_with_applied_reward_points() { //customer var customer = new Customer() { Id = 10, }; //shopping cart var productVariant1 = new ProductVariant { Id = 1, Name = "Product variant name 1", Price = 10M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 1, Name = "Product name 1", Published = true } }; var sci1 = new ShoppingCartItem() { ProductVariant = productVariant1, ProductVariantId = productVariant1.Id, Quantity = 2, }; var productVariant2 = new ProductVariant { Id = 2, Name = "Product variant name 2", Price = 12M, Published = true, IsShipEnabled = true, Product = new Product() { Id = 2, Name = "Product name 2", Published = true } }; var sci2 = new ShoppingCartItem() { ProductVariant = productVariant2, ProductVariantId = productVariant2.Id, Quantity = 3 }; var cart = new List<ShoppingCartItem>() { sci1, sci2 }; cart.ForEach(sci => sci.Customer = customer); cart.ForEach(sci => sci.CustomerId = customer.Id); _genericAttributeService.Expect(x => x.GetAttributesForEntity(customer.Id, "Customer")) .Return(new List<GenericAttribute>() { new GenericAttribute() { StoreId = _store.Id, EntityId = customer.Id, Key = SystemCustomerAttributeNames.SelectedPaymentMethod, KeyGroup = "Customer", Value = "test1" }, new GenericAttribute() { StoreId = 1, EntityId = customer.Id, Key = SystemCustomerAttributeNames.UseRewardPointsDuringCheckout, KeyGroup = "Customer", Value = true.ToString() } }); _paymentService.Expect(ps => ps.GetAdditionalHandlingFee(cart, "test1")).Return(20); _discountService.Expect(ds => ds.GetAllDiscounts(DiscountType.AssignedToCategories)).Return(new List<Discount>()); decimal discountAmount; Discount appliedDiscount; List<AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; //shipping is taxable, payment fee is taxable _taxSettings.ShippingIsTaxable = true; _taxSettings.PaymentMethodAdditionalFeeIsTaxable = true; //reward points _rewardPointsSettings.Enabled = true; _rewardPointsSettings.ExchangeRate = 2; //1 reward point = 2 customer.AddRewardPointsHistoryEntry(15); //15*2=30 //56 - items, 10 - shipping (fixed), 20 - payment fee, 8.6 - tax, -30 (reward points) _orderTotalCalcService.GetShoppingCartTotal(cart, out discountAmount, out appliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount) .ShouldEqual(64.6M); }
/// <summary> /// Delete shopping cart item /// </summary> /// <param name="shoppingCartItem">Shopping cart item</param> /// <param name="resetCheckoutData">A value indicating whether to reset checkout data</param> /// <param name="ensureOnlyActiveCheckoutAttributes">A value indicating whether to ensure that only active checkout attributes are attached to the current customer</param> public virtual void DeleteShoppingCartItem(ShoppingCartItem shoppingCartItem, bool resetCheckoutData = true, bool ensureOnlyActiveCheckoutAttributes = false) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); var customer = shoppingCartItem.Customer; var storeId = shoppingCartItem.StoreId; //reset checkout data if (resetCheckoutData) { _customerService.ResetCheckoutData(shoppingCartItem.Customer, shoppingCartItem.StoreId); } //delete item _sciRepository.Delete(shoppingCartItem); //reset "HasShoppingCartItems" property used for performance optimization customer.HasShoppingCartItems = customer.ShoppingCartItems.Count > 0; _customerService.UpdateCustomer(customer); //validate checkout attributes if (ensureOnlyActiveCheckoutAttributes && //only for shopping cart items (ignore wishlist) shoppingCartItem.ShoppingCartType == ShoppingCartType.ShoppingCart) { var cart = customer.ShoppingCartItems .Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(storeId) .ToList(); var checkoutAttributesXml = customer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, storeId); checkoutAttributesXml = _checkoutAttributeParser.EnsureOnlyActiveAttributes(checkoutAttributesXml, cart); _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.CheckoutAttributes, checkoutAttributesXml, storeId); } //event notification _eventPublisher.EntityDeleted(shoppingCartItem); }
/// <summary> /// Delete shopping cart item /// </summary> /// <param name="shoppingCartItem">Shopping cart item</param> /// <param name="resetCheckoutData">A value indicating whether to reset checkout data</param> /// <param name="ensureOnlyActiveCheckoutAttributes">A value indicating whether to ensure that only active checkout attributes are attached to the current customer</param> public virtual void DeleteShoppingCartItem(ShoppingCartItem shoppingCartItem, bool resetCheckoutData = true, bool ensureOnlyActiveCheckoutAttributes = false) { if (shoppingCartItem == null) throw new ArgumentNullException("shoppingCartItem"); var customer = shoppingCartItem.Customer; //reset checkout data if (resetCheckoutData) { _customerService.ResetCheckoutData(shoppingCartItem.Customer); } //delete item _sciRepository.Delete(shoppingCartItem); //validate checkout attributes if (ensureOnlyActiveCheckoutAttributes && //only for shopping cart items (ignore wishlist) shoppingCartItem.ShoppingCartType == ShoppingCartType.ShoppingCart) { var cart = customer.ShoppingCartItems.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList(); customer.CheckoutAttributes = _checkoutAttributeParser.EnsureOnlyActiveAttributes(customer.CheckoutAttributes, cart); _customerService.UpdateCustomer(customer); } //event notification _eventPublisher.EntityDeleted(shoppingCartItem); }
/// <summary> /// Gets discount amount /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <returns>Discount amount</returns> public virtual decimal GetDiscountAmount(ShoppingCartItem shoppingCartItem) { Discount appliedDiscount; return GetDiscountAmount(shoppingCartItem, out appliedDiscount); }