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
                }
            };

            var item = new OrganizedShoppingCartItem(sci);

            _shippingService.GetShoppingCartItemTotalWeight(item).ShouldEqual(4.5M);
        }
        /// <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(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts)
        {
            decimal finalPrice = decimal.Zero;
            var customer = shoppingCartItem.Item.Customer;
            var product = shoppingCartItem.Item.Product;

            if (product != null)
            {
                if (product.CustomerEntersPrice)
                {
                    finalPrice = shoppingCartItem.Item.CustomerEnteredPrice;
                }
                else if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing)
                {
                    if (shoppingCartItem.ChildItems != null)
                    {
                        foreach (var bundleItem in shoppingCartItem.ChildItems)
                        {
                            bundleItem.Item.Product.MergeWithCombination(bundleItem.Item.AttributesXml);
                        }

                        var bundleItems = shoppingCartItem.ChildItems.Where(x => x.BundleItemData.IsValid()).Select(x => x.BundleItemData).ToList();

                        finalPrice = GetFinalPrice(product, bundleItems, customer, decimal.Zero, includeDiscounts, shoppingCartItem.Item.Quantity);
                    }
                }
                else
                {
                    product.MergeWithCombination(shoppingCartItem.Item.AttributesXml, _productAttributeParser);

                    decimal attributesTotalPrice = decimal.Zero;
                    var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml);

                    if (pvaValues != null)
                    {
                        foreach (var pvaValue in pvaValues)
                            attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue);
                    }

                    finalPrice = GetFinalPrice(product, customer, attributesTotalPrice, includeDiscounts, shoppingCartItem.Item.Quantity, shoppingCartItem.BundleItemData);
                }
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
                finalPrice = Math.Round(finalPrice, 2);

            return finalPrice;
        }
 /// <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(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts)
 {
     return GetUnitPrice(shoppingCartItem, includeDiscounts) * shoppingCartItem.Item.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(OrganizedShoppingCartItem shoppingCartItem, out Discount appliedDiscount)
        {
            var customer = shoppingCartItem.Item.Customer;
            appliedDiscount = null;
            decimal totalDiscountAmount = decimal.Zero;
            var product = shoppingCartItem.Item.Product;
            if (product != null)
            {
                decimal attributesTotalPrice = decimal.Zero;

                var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml);
                foreach (var pvaValue in pvaValues)
                {
                    attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue);
                }

                decimal productDiscountAmount = GetDiscountAmount(product, customer, attributesTotalPrice, shoppingCartItem.Item.Quantity, out appliedDiscount);
                totalDiscountAmount = productDiscountAmount * shoppingCartItem.Item.Quantity;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
                totalDiscountAmount = Math.Round(totalDiscountAmount, 2);
            return totalDiscountAmount;
        }
 /// <summary>
 /// Gets discount amount
 /// </summary>
 /// <param name="shoppingCartItem">The shopping cart item</param>
 /// <returns>Discount amount</returns>
 public virtual decimal GetDiscountAmount(OrganizedShoppingCartItem shoppingCartItem)
 {
     Discount appliedDiscount;
     return GetDiscountAmount(shoppingCartItem, out appliedDiscount);
 }
        private WishlistModel.ShoppingCartItemModel PrepareWishlistCartItemModel(OrganizedShoppingCartItem sci)
        {
            var item = sci.Item;
            var product = sci.Item.Product;

            product.MergeWithCombination(item.AttributesXml);

            var model = new WishlistModel.ShoppingCartItemModel()
            {
                Id = item.Id,
                Sku = product.Sku,
                ProductId = product.Id,
                ProductName = product.GetLocalized(x => x.Name),
                ProductSeName = product.GetSeName(),
                Quantity = item.Quantity,
                ShortDesc = product.GetLocalized(x => x.ShortDescription),
                ProductType = product.ProductType,
                VisibleIndividually = product.VisibleIndividually
            };

            if (item.BundleItem != null)
            {
                model.BundlePerItemPricing = item.BundleItem.BundleProduct.BundlePerItemPricing;
                model.BundlePerItemShoppingCart = item.BundleItem.BundleProduct.BundlePerItemShoppingCart;
                model.AttributeInfo = _productAttributeFormatter.FormatAttributes(product, item.AttributesXml, _workContext.CurrentCustomer,
                    renderPrices: false, renderGiftCardAttributes: false, allowHyperlinks: false);

                string bundleItemName = item.BundleItem.GetLocalized(x => x.Name);
                if (bundleItemName.HasValue())
                    model.ProductName = bundleItemName;

                string bundleItemShortDescription = item.BundleItem.GetLocalized(x => x.ShortDescription);
                if (bundleItemShortDescription.HasValue())
                    model.ShortDesc = bundleItemShortDescription;

                model.BundleItem.Id = item.BundleItem.Id;
                model.BundleItem.DisplayOrder = item.BundleItem.DisplayOrder;
                model.BundleItem.HideThumbnail = item.BundleItem.HideThumbnail;

                if (model.BundlePerItemPricing && model.BundlePerItemShoppingCart)
                {
                    decimal taxRate = decimal.Zero;
                    decimal bundleItemSubTotalWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetSubTotal(sci, true), out taxRate);
                    decimal bundleItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(bundleItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);

                    model.BundleItem.PriceWithDiscount = _priceFormatter.FormatPrice(bundleItemSubTotalWithDiscount);
                }
            }
            else
            {
                model.AttributeInfo = _productAttributeFormatter.FormatAttributes(product, item.AttributesXml);
            }

            //allowed quantities
            var allowedQuantities = product.ParseAllowedQuatities();
            foreach (var qty in allowedQuantities)
            {
                model.AllowedQuantities.Add(new SelectListItem()
                {
                    Text = qty.ToString(),
                    Value = qty.ToString(),
                    Selected = item.Quantity == qty
                });
            }

            //recurring info
            if (product.IsRecurring)
            {
                model.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"),
                    product.RecurringCycleLength, product.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext));
            }

            //unit prices
            if (product.CallForPrice)
            {
                model.UnitPrice = _localizationService.GetResource("Products.CallForPrice");
            }
            else
            {
                decimal taxRate = decimal.Zero;
                decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetUnitPrice(sci, true), out taxRate);
                decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency);

                model.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount);
            }

            //subtotal, discount
            if (product.CallForPrice)
            {
                model.SubTotal = _localizationService.GetResource("Products.CallForPrice");
            }
            else
            {
                //sub total
                decimal taxRate = decimal.Zero;
                decimal shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetSubTotal(sci, true), out taxRate);
                decimal shoppingCartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);

                model.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount);

                //display an applied discount amount
                decimal shoppingCartItemSubTotalWithoutDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetSubTotal(sci, false), out taxRate);
                decimal shoppingCartItemDiscountBase = shoppingCartItemSubTotalWithoutDiscountBase - shoppingCartItemSubTotalWithDiscountBase;

                if (shoppingCartItemDiscountBase > decimal.Zero)
                {
                    decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency);

                    model.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount);
                }
            }

            //picture
            if (item.BundleItem != null)
            {
                if (_shoppingCartSettings.ShowProductBundleImagesOnShoppingCart)
                    model.Picture = PrepareCartItemPictureModel(product, _mediaSettings.CartThumbBundleItemPictureSize, true, model.ProductName, item.AttributesXml);
            }
            else
            {
                if (_shoppingCartSettings.ShowProductImagesOnShoppingCart)
                    model.Picture = PrepareCartItemPictureModel(product, _mediaSettings.CartThumbPictureSize, true, model.ProductName, item.AttributesXml);
            }

            //item warnings
            var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings(_workContext.CurrentCustomer, item.ShoppingCartType, product, item.StoreId,
                item.AttributesXml, item.CustomerEnteredPrice, item.Quantity, false, childItems: sci.ChildItems);

            foreach (var warning in itemWarnings)
            {
                model.Warnings.Add(warning);
            }

            if (sci.ChildItems != null)
            {
                foreach (var childItem in sci.ChildItems.Where(x => x.Item.Id != item.Id))
                {
                    var childModel = PrepareWishlistCartItemModel(childItem);

                    model.ChildItems.Add(childModel);
                }
            }

            return model;
        }
        private ShoppingCartModel.ShoppingCartItemModel PrepareShoppingCartItemModel(OrganizedShoppingCartItem sci)
        {
            var item = sci.Item;
            var product = sci.Item.Product;

            product.MergeWithCombination(item.AttributesXml);

            var model = new ShoppingCartModel.ShoppingCartItemModel()
            {
                Id = item.Id,
                Sku = product.Sku,
                ProductId = product.Id,
                ProductName = product.GetLocalized(x => x.Name),
                ProductSeName = product.GetSeName(),
                VisibleIndividually = product.VisibleIndividually,
                Quantity = item.Quantity,
                IsShipEnabled = product.IsShipEnabled,
                ShortDesc = product.GetLocalized(x => x.ShortDescription),
                ProductType = product.ProductType,
                BasePrice = product.GetBasePriceInfo(_localizationService, _priceFormatter, _currencyService, _taxService, _priceCalculationService, _workContext.WorkingCurrency),
                Weight = product.Weight
            };

            if (item.BundleItem != null)
            {
                model.BundlePerItemPricing = item.BundleItem.BundleProduct.BundlePerItemPricing;
                model.BundlePerItemShoppingCart = item.BundleItem.BundleProduct.BundlePerItemShoppingCart;

                model.AttributeInfo = _productAttributeFormatter.FormatAttributes(product, item.AttributesXml, _workContext.CurrentCustomer,
                    renderPrices: false, renderGiftCardAttributes: true, allowHyperlinks: false);

                string bundleItemName = item.BundleItem.GetLocalized(x => x.Name);
                if (bundleItemName.HasValue())
                    model.ProductName = bundleItemName;

                string bundleItemShortDescription = item.BundleItem.GetLocalized(x => x.ShortDescription);
                if (bundleItemShortDescription.HasValue())
                    model.ShortDesc = bundleItemShortDescription;

                model.BundleItem.Id = item.BundleItem.Id;
                model.BundleItem.DisplayOrder = item.BundleItem.DisplayOrder;
                model.BundleItem.HideThumbnail = item.BundleItem.HideThumbnail;

                if (model.BundlePerItemPricing && model.BundlePerItemShoppingCart)
                {
                    decimal taxRate = decimal.Zero;
                    decimal bundleItemSubTotalWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetSubTotal(sci, true), out taxRate);
                    decimal bundleItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(bundleItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);

                    model.BundleItem.PriceWithDiscount = _priceFormatter.FormatPrice(bundleItemSubTotalWithDiscount);
                }
            }
            else
            {
                model.AttributeInfo = _productAttributeFormatter.FormatAttributes(product, item.AttributesXml);

                var selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(item.AttributesXml).ToList();
                if (selectedAttributeValues != null)
                {
                    foreach (var attributeValue in selectedAttributeValues)
                        model.Weight = decimal.Add(model.Weight, attributeValue.WeightAdjustment);
                }
            }

            if (product.DisplayDeliveryTimeAccordingToStock(_catalogSettings))
            {
                var deliveryTime = _deliveryTimeService.GetDeliveryTime(product);
                if (deliveryTime != null)
                {
                    model.DeliveryTimeName = deliveryTime.GetLocalized(x => x.Name);
                    model.DeliveryTimeHexValue = deliveryTime.ColorHexValue;
                }
            }

            //if show measure Unit
            if (product.QuantityUnitId != null)
            {
                var quantityUnit = _quantityUnitService.GetQuantityUnitById(product.QuantityUnitId);
                if(quantityUnit != null)
                    model.QuantityUnit = quantityUnit.GetLocalized(x => x.Name);
            }

            //allowed quantities
            var allowedQuantities = product.ParseAllowedQuatities();
            foreach (var qty in allowedQuantities)
            {
                model.AllowedQuantities.Add(new SelectListItem()
                {
                    Text = qty.ToString(),
                    Value = qty.ToString(),
                    Selected = item.Quantity == qty
                });
            }

            //recurring info
            if (product.IsRecurring)
            {
                model.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"),
                    product.RecurringCycleLength, product.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext));
            }

            //unit prices
            if (product.CallForPrice)
            {
                model.UnitPrice = _localizationService.GetResource("Products.CallForPrice");
            }
            else
            {
                decimal taxRate = decimal.Zero;
                decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetUnitPrice(sci, true), out taxRate);
                decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency);

                model.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount);
            }

            //subtotal, discount
            if (product.CallForPrice)
            {
                model.SubTotal = _localizationService.GetResource("Products.CallForPrice");
            }
            else
            {
                //sub total
                decimal taxRate, shoppingCartItemSubTotalWithDiscountBase, shoppingCartItemSubTotalWithDiscount, shoppingCartItemSubTotalWithoutDiscountBase = decimal.Zero;

                if (_shoppingCartSettings.RoundPricesDuringCalculation)
                {
                    // Gross > Net RoundFix
                    shoppingCartItemSubTotalWithDiscountBase = Math.Round(_taxService.GetProductPrice(product, _priceCalculationService.GetUnitPrice(sci, true), out taxRate), 2) * sci.Item.Quantity;
                    shoppingCartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);
                    model.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount);
                    // display an applied discount amount
                    shoppingCartItemSubTotalWithoutDiscountBase = Math.Round(_taxService.GetProductPrice(product, _priceCalculationService.GetUnitPrice(sci, false), out taxRate), 2) * sci.Item.Quantity;

                }
                else
                {
                    shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetSubTotal(sci, true), out taxRate);
                    shoppingCartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);
                    model.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount);
                    // display an applied discount amount
                    shoppingCartItemSubTotalWithoutDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetSubTotal(sci, false), out taxRate);
                }

                decimal shoppingCartItemDiscountBase = shoppingCartItemSubTotalWithoutDiscountBase - shoppingCartItemSubTotalWithDiscountBase;

                if (shoppingCartItemDiscountBase > decimal.Zero)
                {
                    decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency);
                    model.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount);
                }

                model.BasePrice = product.GetBasePriceInfo(
                    _localizationService,
                    _priceFormatter,
                    _currencyService,
                    _taxService,
                    _priceCalculationService,
                    _workContext.WorkingCurrency,
                    (product.Price - _priceCalculationService.GetUnitPrice(sci, true)) * (-1)
                );
            }

            //picture
            if (item.BundleItem != null)
            {
                if (_shoppingCartSettings.ShowProductBundleImagesOnShoppingCart)
                    model.Picture = PrepareCartItemPictureModel(product, _mediaSettings.CartThumbBundleItemPictureSize, true, model.ProductName, item.AttributesXml);
            }
            else
            {
                if (_shoppingCartSettings.ShowProductImagesOnShoppingCart)
                    model.Picture = PrepareCartItemPictureModel(product, _mediaSettings.CartThumbPictureSize, true, model.ProductName, item.AttributesXml);
            }

            //item warnings
            var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings(_workContext.CurrentCustomer, item.ShoppingCartType, product, item.StoreId,
                item.AttributesXml, item.CustomerEnteredPrice, item.Quantity, false, childItems: sci.ChildItems);

            foreach (var warning in itemWarnings)
            {
                model.Warnings.Add(warning);
            }

            if (sci.ChildItems != null)
            {
                foreach (var childItem in sci.ChildItems.Where(x => x.Item.Id != item.Id))
                {
                    var childModel = PrepareShoppingCartItemModel(childItem);

                    model.ChildItems.Add(childModel);
                }
            }

            return model;
        }
		public virtual IList<string> Copy(OrganizedShoppingCartItem sci, Customer customer, ShoppingCartType cartType, int storeId, bool addRequiredProductsIfEnabled)
		{
			if (customer == null)
				throw new ArgumentNullException("customer");

			if (sci == null)
				throw new ArgumentNullException("item");

			int parentItemId, childItemId;

			var warnings = AddToCart(customer, sci.Item.Product, cartType, storeId, sci.Item.AttributesXml, sci.Item.CustomerEnteredPrice,
				sci.Item.Quantity, addRequiredProductsIfEnabled, out parentItemId);

			if (warnings.Count == 0 && parentItemId != 0 && sci.ChildItems != null)
			{
				foreach (var childItem in sci.ChildItems)
				{
					AddToCart(customer, childItem.Item.Product, cartType, storeId, childItem.Item.AttributesXml, childItem.Item.CustomerEnteredPrice,
						childItem.Item.Quantity, false, out childItemId, parentItemId, childItem.Item.BundleItem);
				}
			}
			return warnings;
		}
Beispiel #9
0
        /// <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(OrganizedShoppingCartItem shoppingCartItem)
        {
            if (shoppingCartItem == null)
                throw new ArgumentNullException("shoppingCartItem");

            decimal weight = decimal.Zero;

            if (shoppingCartItem.Item.Product != null)
            {
                decimal attributesTotalWeight = decimal.Zero;

                if (!String.IsNullOrEmpty(shoppingCartItem.Item.AttributesXml))
                {
                    var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml);

                    foreach (var pvaValue in pvaValues)
                    {
                        if (pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage)
                        {
                            var linkedProduct = _productService.GetProductById(pvaValue.LinkedProductId);
                            if (linkedProduct != null && linkedProduct.IsShipEnabled)
                                attributesTotalWeight += (linkedProduct.Weight * pvaValue.Quantity);
                        }
                        else
                        {
                            attributesTotalWeight += pvaValue.WeightAdjustment;
                        }
                    }
                }

                weight = shoppingCartItem.Item.Product.Weight + attributesTotalWeight;
            }
            return weight;
        }
Beispiel #10
0
        /// <summary>
        /// Gets shopping cart item total weight
        /// </summary>
        /// <param name="shoppingCartItem">Shopping cart item</param>
        /// <returns>Shopping cart item weight</returns>
        public virtual decimal GetShoppingCartItemTotalWeight(OrganizedShoppingCartItem shoppingCartItem)
        {
            if (shoppingCartItem == null)
                throw new ArgumentNullException("shoppingCartItem");

            decimal totalWeight = GetShoppingCartItemWeight(shoppingCartItem) * shoppingCartItem.Item.Quantity;
            return totalWeight;
        }
        public void Can_get_shopping_cart_item_unitPrice()
        {
            //customer
            var customer = new Customer();

            //shopping cart
            var product1 = new Product
            {
                Id = 1,
                Name = "Product name 1",
                Price = 12.34M,
                CustomerEntersPrice = false,
                Published = true,
            };
            var sci1 = new ShoppingCartItem()
            {
                Customer = customer,
                CustomerId = customer.Id,
                Product = product1,
                ProductId = product1.Id,
                Quantity = 2,
            };

            var item = new OrganizedShoppingCartItem(sci1);

            _priceCalcService.GetUnitPrice(item, false).ShouldEqual(12.34);
        }
        public static IList<OrganizedShoppingCartItem> Organize(this IList<ShoppingCartItem> cart)
        {
            var result = new List<OrganizedShoppingCartItem>();
            var productAttributeParser = EngineContext.Current.Resolve<IProductAttributeParser>();

            if (cart == null || cart.Count <= 0)
                return result;

            foreach (var parent in cart.Where(x => x.ParentItemId == null))
            {
                var parentItem = new OrganizedShoppingCartItem(parent);

                var childs = cart.Where(x => x.ParentItemId != null && x.ParentItemId == parent.Id && x.Id != parent.Id &&
                    x.ShoppingCartTypeId == parent.ShoppingCartTypeId && x.Product.CanBeBundleItem());

                foreach (var child in childs)
                {
                    var childItem = new OrganizedShoppingCartItem(child);

                    if (parent.Product != null && parent.Product.BundlePerItemPricing && child.AttributesXml != null && child.BundleItem != null)
                    {
                        child.Product.MergeWithCombination(child.AttributesXml);

                        var attributeValues = productAttributeParser.ParseProductVariantAttributeValues(child.AttributesXml).ToList();
                        if (attributeValues != null)
                        {
                            childItem.BundleItemData.AdditionalCharge = decimal.Zero;
                            attributeValues.Each(x => childItem.BundleItemData.AdditionalCharge += x.PriceAdjustment);
                        }
                    }

                    parentItem.ChildItems.Add(childItem);
                }

                result.Add(parentItem);
            }

            return result;
        }
        /// <summary>
        /// Adjusts inventory
        /// </summary>
        /// <param name="sci">Shopping cart item</param>
        /// <param name="decrease">A value indicating whether to increase or descrease product stock quantity</param>
        /// <returns>Adjust inventory result</returns>
        public virtual AdjustInventoryResult AdjustInventory(OrganizedShoppingCartItem sci, bool decrease)
        {
            if (sci == null)
                throw new ArgumentNullException("cartItem");

            if (sci.Item.Product.ProductType == ProductType.BundledProduct && sci.Item.Product.BundlePerItemShoppingCart)
            {
                if (sci.ChildItems != null)
                {
                    foreach (var child in sci.ChildItems.Where(x => x.Item.Id != sci.Item.Id))
                    {
                        AdjustInventory(child.Item.Product, decrease, sci.Item.Quantity * child.Item.Quantity, child.Item.AttributesXml);
                    }
                }
                return new AdjustInventoryResult();
            }
            else
            {
                return AdjustInventory(sci.Item.Product, decrease, sci.Item.Quantity, sci.Item.AttributesXml);
            }
        }
		/// <summary>
		/// Copies a shopping cart item.
		/// </summary>
		/// <param name="sci">Shopping cart item</param>
		/// <param name="customer">The customer</param>
		/// <param name="cartType">Shopping cart type</param>
		/// <param name="storeId">Store Id</param>
		/// <param name="addRequiredProductsIfEnabled">Add required products if enabled</param>
		/// <returns>List with add-to-cart warnings.</returns>
		public virtual IList<string> Copy(OrganizedShoppingCartItem sci, Customer customer, ShoppingCartType cartType, int storeId, bool addRequiredProductsIfEnabled)
		{
			if (customer == null)
				throw new ArgumentNullException("customer");

			if (sci == null)
				throw new ArgumentNullException("item");

			var addToCartContext = new AddToCartContext
			{
				Customer = customer
			};

			addToCartContext.Warnings = AddToCart(customer, sci.Item.Product, cartType, storeId, sci.Item.AttributesXml, sci.Item.CustomerEnteredPrice,
				sci.Item.Quantity, addRequiredProductsIfEnabled, addToCartContext);

			if (addToCartContext.Warnings.Count == 0 && sci.ChildItems != null)
			{
				foreach (var childItem in sci.ChildItems)
				{
					addToCartContext.BundleItem = childItem.Item.BundleItem;

					addToCartContext.Warnings = AddToCart(customer, childItem.Item.Product, cartType, storeId, childItem.Item.AttributesXml, childItem.Item.CustomerEnteredPrice,
						childItem.Item.Quantity, false, addToCartContext);
				}
			}

			AddToCartStoring(addToCartContext);

			return addToCartContext.Warnings;
		}