public OrganizedShoppingCartItem(ShoppingCartItem item) { if (item == null) throw new ArgumentNullException("item"); Item = item; // must not be null ChildItems = new List<OrganizedShoppingCartItem>(); BundleItemData = new ProductBundleItemData(item.BundleItem); }
protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationContext context, ProductBundleItemData bundleItem, IEnumerable<ProductBundleItemData> bundleItems) { var taxRate = decimal.Zero; var attributesTotalPriceBase = decimal.Zero; var preSelectedPriceAdjustmentBase = decimal.Zero; var isBundle = (product.ProductType == ProductType.BundledProduct); var isBundleItemPricing = (bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing); var isBundlePricing = (bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing); var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); var selectedAttributes = new NameValueCollection(); var selectedAttributeValues = new List<ProductVariantAttributeValue>(); var attributes = context.Attributes.Load(product.Id); // 1. fill selectedAttributes with initially selected attributes foreach (var attribute in attributes.Where(x => x.ProductVariantAttributeValues.Count > 0 && x.ShouldHaveValues())) { int preSelectedValueId = 0; ProductVariantAttributeValue defaultValue = null; var selectedValueIds = new List<int>(); var pvaValues = attribute.ProductVariantAttributeValues; foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (bundleItem.FilterOut(pvaValue, out attributeFilter)) continue; if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) preSelectedValueId = attributeFilter.AttributeValueId; if (!isBundlePricing && pvaValue.IsPreSelected) { decimal attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); } } // value pre-selected by a bundle item filter discards the default pre-selection if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) { //defaultValue.IsPreSelected = true; selectedAttributeValues.Add(defaultValue); selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } else { foreach (var value in pvaValues.Where(x => x.IsPreSelected)) { selectedAttributeValues.Add(value); selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, value.Id, product.Id, bundleItemId); } } } // 2. find attribute combination for selected attributes and merge it if (!isBundle && selectedAttributes.Count > 0) { string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _services.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List<string>(), true, bundleItemId); var combinations = context.AttributeCombinations.Load(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml, attributes)); if (selectedCombination != null && selectedCombination.IsActive && selectedCombination.Price.HasValue) { product.MergedDataValues = new Dictionary<string, object> { { "Price", selectedCombination.Price.Value } }; } } if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues.Count > 0) { selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (bundleItem != null) { bundleItem.AdditionalCharge = attributesTotalPriceBase; } var result = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem, context); return result; }
public virtual decimal GetFinalPrice( Product product, IEnumerable<ProductBundleItemData> bundleItems, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, ProductBundleItemData bundleItem = null, PriceCalculationContext context = null) { if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing) { decimal result = decimal.Zero; var items = bundleItems ?? _productService.GetBundleItems(product.Id); foreach (var itemData in items.Where(x => x.IsValid())) { decimal itemPrice = GetFinalPrice(itemData.Item.Product, customer, itemData.AdditionalCharge, includeDiscounts, 1, itemData, context); result = result + decimal.Multiply(itemPrice, itemData.Item.Quantity); } return (result < decimal.Zero ? decimal.Zero : result); } return GetFinalPrice(product, customer, additionalCharge, includeDiscounts, quantity, bundleItem, context); }
public virtual decimal GetFinalPrice( Product product, Customer customer, decimal additionalCharge, bool includeDiscounts, int quantity, ProductBundleItemData bundleItem = null, PriceCalculationContext context = null) { //initial price decimal result = product.Price; //special price var specialPrice = GetSpecialPrice(product); if (specialPrice.HasValue) result = specialPrice.Value; //tier prices if (product.HasTierPrices && !bundleItem.IsValid()) { decimal? tierPrice = GetMinimumTierPrice(product, customer, quantity, context); if (tierPrice.HasValue) result = Math.Min(result, tierPrice.Value); } //discount + additional charge if (includeDiscounts) { Discount appliedDiscount = null; decimal discountAmount = GetDiscountAmount(product, customer, additionalCharge, quantity, out appliedDiscount, bundleItem, context); result = result + additionalCharge - discountAmount; } else { result = result + additionalCharge; } if (result < decimal.Zero) result = decimal.Zero; return result; }
public virtual decimal GetDiscountAmount( Product product, Customer customer, decimal additionalCharge, int quantity, out Discount appliedDiscount, ProductBundleItemData bundleItem = null, PriceCalculationContext context = null) { appliedDiscount = null; decimal appliedDiscountAmount = decimal.Zero; decimal finalPriceWithoutDiscount = decimal.Zero; if (bundleItem.IsValid()) { if (bundleItem.Item.Discount.HasValue && bundleItem.Item.BundleProduct.BundlePerItemPricing) { appliedDiscount = new Discount { UsePercentage = bundleItem.Item.DiscountPercentage, DiscountPercentage = bundleItem.Item.Discount.Value, DiscountAmount = bundleItem.Item.Discount.Value }; finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity, bundleItem, context); appliedDiscountAmount = appliedDiscount.GetDiscountAmount(finalPriceWithoutDiscount); } } else { // dont't apply when customer entered price or discounts should be ignored completely if (product.CustomerEntersPrice || _catalogSettings.IgnoreDiscounts) { return appliedDiscountAmount; } var allowedDiscounts = GetAllowedDiscounts(product, customer, context); if (allowedDiscounts.Count == 0) { return appliedDiscountAmount; } finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity, bundleItem, context); appliedDiscount = allowedDiscounts.GetPreferredDiscount(finalPriceWithoutDiscount); if (appliedDiscount != null) { appliedDiscountAmount = appliedDiscount.GetDiscountAmount(finalPriceWithoutDiscount); } } return appliedDiscountAmount; }
/// <summary> /// Gets discount amount /// </summary> /// <param name="product">Product</param> /// <param name="customer">The customer</param> /// <param name="additionalCharge">Additional charge</param> /// <param name="quantity">Product quantity</param> /// <param name="appliedDiscount">Applied discount</param> /// <param name="bundleItem">A product bundle item</param> /// <returns>Discount amount</returns> public virtual decimal GetDiscountAmount(Product product, Customer customer, decimal additionalCharge, int quantity, out Discount appliedDiscount, ProductBundleItemData bundleItem = null) { appliedDiscount = null; decimal appliedDiscountAmount = decimal.Zero; if (bundleItem.IsValid()) { if (bundleItem.Item.Discount.HasValue && bundleItem.Item.BundleProduct.BundlePerItemPricing) { appliedDiscount = new Discount() { UsePercentage = bundleItem.Item.DiscountPercentage, DiscountPercentage = bundleItem.Item.Discount.Value, DiscountAmount = bundleItem.Item.Discount.Value }; } } else { //we don't apply discounts to products with price entered by a customer if (product.CustomerEntersPrice) return appliedDiscountAmount; appliedDiscount = GetPreferredDiscount(product, customer, additionalCharge, quantity); } if (appliedDiscount != null) { decimal finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity, bundleItem); appliedDiscountAmount = appliedDiscount.GetDiscountAmount(finalPriceWithoutDiscount); } return appliedDiscountAmount; }
protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItemData bundleItem, IList<ProductBundleItemData> bundleItems) { var taxRate = decimal.Zero; var attributesTotalPriceBase = decimal.Zero; var preSelectedPriceAdjustmentBase = decimal.Zero; var isBundle = (product.ProductType == ProductType.BundledProduct); var isBundleItemPricing = (bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing); var isBundlePricing = (bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing); var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); var attributes = (isBundle ? new List<ProductVariantAttribute>() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id)); var selectedAttributes = new NameValueCollection(); List<ProductVariantAttributeValue> selectedAttributeValues = null; foreach (var attribute in attributes) { int preSelectedValueId = 0; ProductVariantAttributeValue defaultValue = null; if (attribute.ShouldHaveValues()) { var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); if (pvaValues.Count == 0) continue; foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (bundleItem.FilterOut(pvaValue, out attributeFilter)) continue; if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) preSelectedValueId = attributeFilter.AttributeValueId; if (!isBundlePricing && pvaValue.IsPreSelected) { decimal attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); } } // value pre-selected by a bundle item filter discards the default pre-selection if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) defaultValue.IsPreSelected = true; if (defaultValue == null) defaultValue = pvaValues.FirstOrDefault(x => x.IsPreSelected); if (defaultValue == null && attribute.IsRequired) defaultValue = pvaValues.First(); if (defaultValue != null) selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } } if (!isBundle && selectedAttributes.Count > 0) { string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _commonServices.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List<string>(), true, bundleItemId); selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); var combinations = _productAttributeService.GetAllProductVariantAttributeCombinations(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); if (selectedCombination != null && selectedCombination.IsActive) product.MergeWithCombination(selectedCombination); } if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues != null) { selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (bundleItem != null) { bundleItem.AdditionalCharge = attributesTotalPriceBase; } var result = GetFinalPrice(product, bundleItems, _commonServices.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem); return result; }
/// <param name="selectedAttributes">Attributes explicitly selected by user or by query string.</param> public ProductDetailsModel PrepareProductDetailModel( ProductDetailsModel model, Product product, bool isAssociatedProduct = false, ProductBundleItemData productBundleItem = null, IList<ProductBundleItemData> productBundleItems = null, NameValueCollection selectedAttributes = null, int selectedQuantity = 1) { if (product == null) throw new ArgumentNullException("product"); if (model == null) throw new ArgumentNullException("model"); if (selectedAttributes == null) selectedAttributes = new NameValueCollection(); var store = _services.StoreContext.CurrentStore; var customer = _services.WorkContext.CurrentCustomer; var currency = _services.WorkContext.WorkingCurrency; decimal preSelectedPriceAdjustmentBase = decimal.Zero; decimal preSelectedWeightAdjustment = decimal.Zero; bool displayPrices = _services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices); bool isBundle = (product.ProductType == ProductType.BundledProduct); bool isBundleItemPricing = (productBundleItem != null && productBundleItem.Item.BundleProduct.BundlePerItemPricing); bool isBundlePricing = (productBundleItem != null && !productBundleItem.Item.BundleProduct.BundlePerItemPricing); int bundleItemId = (productBundleItem == null ? 0 : productBundleItem.Item.Id); bool hasSelectedAttributesValues = false; bool hasSelectedAttributes = (selectedAttributes.Count > 0); List<ProductVariantAttributeValue> selectedAttributeValues = null; var variantAttributes = (isBundle ? new List<ProductVariantAttribute>() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id)); model.ProductPrice.DynamicPriceUpdate = _catalogSettings.EnableDynamicPriceUpdate; model.ProductPrice.BundleItemShowBasePrice = _catalogSettings.BundleItemShowBasePrice; if (!model.ProductPrice.DynamicPriceUpdate) selectedQuantity = 1; #region Product attributes if (!isBundle) // bundles doesn't have attributes { foreach (var attribute in variantAttributes) { var pvaModel = new ProductDetailsModel.ProductVariantAttributeModel { Id = attribute.Id, ProductId = attribute.ProductId, BundleItemId = bundleItemId, ProductAttributeId = attribute.ProductAttributeId, Alias = attribute.ProductAttribute.Alias, Name = attribute.ProductAttribute.GetLocalized(x => x.Name), Description = attribute.ProductAttribute.GetLocalized(x => x.Description), TextPrompt = attribute.TextPrompt, IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType, AllowedFileExtensions = _catalogSettings.FileUploadAllowedExtensions }; if (attribute.AttributeControlType == AttributeControlType.Datepicker) { if (pvaModel.Alias.HasValue() && RegularExpressions.IsYearRange.IsMatch(pvaModel.Alias)) { var match = RegularExpressions.IsYearRange.Match(pvaModel.Alias); pvaModel.BeginYear = match.Groups[1].Value.ToInt(); pvaModel.EndYear = match.Groups[2].Value.ToInt(); } if (hasSelectedAttributes) { var attributeKey = "product_attribute_{0}_{1}_{2}_{3}".FormatInvariant(product.Id, bundleItemId, attribute.ProductAttributeId, attribute.Id); var day = selectedAttributes[attributeKey + "_day"].ToInt(); var month = selectedAttributes[attributeKey + "_month"].ToInt(); var year = selectedAttributes[attributeKey + "_year"].ToInt(); if (day > 0 && month > 0 && year > 0) { pvaModel.SelectedDay = day; pvaModel.SelectedMonth = month; pvaModel.SelectedYear = year; } } } else if (attribute.AttributeControlType == AttributeControlType.TextBox || attribute.AttributeControlType == AttributeControlType.MultilineTextbox) { if (hasSelectedAttributes) { var attributeKey = "product_attribute_{0}_{1}_{2}_{3}".FormatInvariant(product.Id, bundleItemId, attribute.ProductAttributeId, attribute.Id); pvaModel.TextValue = selectedAttributes[attributeKey]; } } var preSelectedValueId = 0; var pvaValues = (attribute.ShouldHaveValues() ? _productAttributeService.GetProductVariantAttributeValues(attribute.Id) : new List<ProductVariantAttributeValue>()); foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (productBundleItem.FilterOut(pvaValue, out attributeFilter)) continue; if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) preSelectedValueId = attributeFilter.AttributeValueId; var linkedProduct = _productService.GetProductById(pvaValue.LinkedProductId); var pvaValueModel = new ProductDetailsModel.ProductVariantAttributeValueModel(); pvaValueModel.Id = pvaValue.Id; pvaValueModel.Name = pvaValue.GetLocalized(x => x.Name); pvaValueModel.Alias = pvaValue.Alias; pvaValueModel.ColorSquaresRgb = pvaValue.ColorSquaresRgb; //used with "Color squares" attribute type pvaValueModel.IsPreSelected = pvaValue.IsPreSelected; if (linkedProduct != null && linkedProduct.VisibleIndividually) pvaValueModel.SeName = linkedProduct.GetSeName(); if (hasSelectedAttributes) pvaValueModel.IsPreSelected = false; // explicitly selected always discards pre-selected by merchant // display price if allowed if (displayPrices && !isBundlePricing) { decimal taxRate = decimal.Zero; decimal attributeValuePriceAdjustment = _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, currency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, true, false); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, true, false); if (pvaValueModel.IsPreSelected) { preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); preSelectedWeightAdjustment = decimal.Add(preSelectedWeightAdjustment, pvaValue.WeightAdjustment); } if (_catalogSettings.ShowLinkedAttributeValueQuantity && pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) { pvaValueModel.QuantityInfo = pvaValue.Quantity; } pvaValueModel.PriceAdjustmentValue = priceAdjustment; } if (!_catalogSettings.ShowVariantCombinationPriceAdjustment) { pvaValueModel.PriceAdjustment = ""; } if (_catalogSettings.ShowLinkedAttributeValueImage && pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) { var linkagePicture = _pictureService.GetPicturesByProductId(pvaValue.LinkedProductId, 1).FirstOrDefault(); if (linkagePicture != null) pvaValueModel.ImageUrl = _pictureService.GetPictureUrl(linkagePicture, _mediaSettings.VariantValueThumbPictureSize, false); } pvaModel.Values.Add(pvaValueModel); } // we need selected attributes to get initially displayed combination images if (!hasSelectedAttributes) { ProductDetailsModel.ProductVariantAttributeValueModel defaultValue = null; if (preSelectedValueId != 0) // value pre-selected by a bundle item filter discards the default pre-selection { pvaModel.Values.Each(x => x.IsPreSelected = false); if ((defaultValue = pvaModel.Values.FirstOrDefault(v => v.Id == preSelectedValueId)) != null) { defaultValue.IsPreSelected = true; selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } } if (defaultValue == null) { foreach (var value in pvaModel.Values.Where(x => x.IsPreSelected)) { selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, value.Id, product.Id, bundleItemId); } } //if (defaultValue == null) // defaultValue = pvaModel.Values.FirstOrDefault(v => v.IsPreSelected); //if (defaultValue != null) // selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } model.ProductVariantAttributes.Add(pvaModel); } } #endregion #region Attribute combinations if (!isBundle) { if (selectedAttributes.Count > 0) { // merge with combination data if there's a match var warnings = new List<string>(); string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, variantAttributes, _productAttributeParser, _localizationService, _downloadService, _catalogSettings, _httpRequest, warnings, true, bundleItemId); selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); hasSelectedAttributesValues = (selectedAttributeValues.Count > 0); if (isBundlePricing) { model.AttributeInfo = _productAttributeFormatter.FormatAttributes(product, attributeXml, customer, renderPrices: false, renderGiftCardAttributes: false, allowHyperlinks: false); } model.SelectedCombination = _productAttributeParser.FindProductVariantAttributeCombination(product.Id, attributeXml); if (model.SelectedCombination != null && model.SelectedCombination.IsActive == false) { model.IsAvailable = false; model.StockAvailability = T("Products.Availability.IsNotActive"); } product.MergeWithCombination(model.SelectedCombination); // mark explicitly selected as pre-selected foreach (var attribute in model.ProductVariantAttributes) { foreach (var value in attribute.Values) { if (selectedAttributeValues.FirstOrDefault(v => v.Id == value.Id) != null) value.IsPreSelected = true; if (!_catalogSettings.ShowVariantCombinationPriceAdjustment) value.PriceAdjustment = ""; } } } } #endregion #region Properties if ((productBundleItem != null && !productBundleItem.Item.BundleProduct.BundlePerItemShoppingCart) || (product.ManageInventoryMethod == ManageInventoryMethod.ManageStockByAttributes && !hasSelectedAttributesValues)) { // cases where stock inventory is not functional. determined by what ShoppingCartService.GetStandardWarnings and ProductService.AdjustInventory is not handling. model.IsAvailable = true; var hasAttributeCombinations = _services.DbContext.QueryForCollection(product, (Product p) => p.ProductVariantAttributeCombinations).Any(); model.StockAvailability = !hasAttributeCombinations ? product.FormatStockMessage(_localizationService) : ""; } else if (model.IsAvailable) { model.IsAvailable = product.IsAvailableByStock(); model.StockAvailability = product.FormatStockMessage(_localizationService); } model.Id = product.Id; model.Name = product.GetLocalized(x => x.Name); model.ShowSku = _catalogSettings.ShowProductSku; model.Sku = product.Sku; model.ShortDescription = product.GetLocalized(x => x.ShortDescription); model.FullDescription = product.GetLocalized(x => x.FullDescription); model.MetaKeywords = product.GetLocalized(x => x.MetaKeywords); model.MetaDescription = product.GetLocalized(x => x.MetaDescription); model.MetaTitle = product.GetLocalized(x => x.MetaTitle); model.SeName = product.GetSeName(); model.ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber; model.ManufacturerPartNumber = product.ManufacturerPartNumber; model.ShowDimensions = _catalogSettings.ShowDimensions; model.ShowWeight = _catalogSettings.ShowWeight; model.ShowGtin = _catalogSettings.ShowGtin; model.Gtin = product.Gtin; model.HasSampleDownload = product.IsDownload && product.HasSampleDownload; model.IsCurrentCustomerRegistered = customer.IsRegistered(); model.IsBasePriceEnabled = product.BasePriceEnabled; model.BasePriceInfo = product.GetBasePriceInfo(_localizationService, _priceFormatter, _currencyService, _taxService, _priceCalculationService, currency); model.ShowLegalInfo = _taxSettings.ShowLegalHintsInProductDetails; model.BundleTitleText = product.GetLocalized(x => x.BundleTitleText); model.BundlePerItemPricing = product.BundlePerItemPricing; model.BundlePerItemShipping = product.BundlePerItemShipping; model.BundlePerItemShoppingCart = product.BundlePerItemShoppingCart; //_taxSettings.TaxDisplayType == TaxDisplayType.ExcludingTax; var taxDisplayType = _services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id); string taxInfo = T(taxDisplayType == TaxDisplayType.IncludingTax ? "Tax.InclVAT" : "Tax.ExclVAT"); var defaultTaxRate = ""; var taxrate = Convert.ToString(_taxService.GetTaxRate(product, customer)); if (_taxSettings.DisplayTaxRates && !taxrate.Equals("0", StringComparison.InvariantCultureIgnoreCase)) { defaultTaxRate = "({0}%)".FormatWith(taxrate); } var additionalShippingCosts = String.Empty; var addShippingPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.AdditionalShippingCharge, currency); if (addShippingPrice > 0) { additionalShippingCosts = T("Common.AdditionalShippingSurcharge").Text.FormatInvariant(_priceFormatter.FormatPrice(addShippingPrice, true, false)) + ", "; } if (!product.IsShipEnabled || (addShippingPrice == 0 && product.IsFreeShipping)) { model.LegalInfo += "{0} {1}, {2}".FormatInvariant( product.IsTaxExempt ? "" : taxInfo, product.IsTaxExempt ? "" : defaultTaxRate, T("Common.FreeShipping")); } else { var topic = _topicService.Value.GetTopicBySystemName("ShippingInfo", store.Id); if (topic == null) { model.LegalInfo = T("Tax.LegalInfoProductDetail2", product.IsTaxExempt ? "" : taxInfo, product.IsTaxExempt ? "" : defaultTaxRate, additionalShippingCosts); } else { model.LegalInfo = T("Tax.LegalInfoProductDetail", product.IsTaxExempt ? "" : taxInfo, product.IsTaxExempt ? "" : defaultTaxRate, additionalShippingCosts, _urlHelper.RouteUrl("Topic", new { SystemName = "shippinginfo" })); } } var dimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).Name; model.WeightValue = product.Weight; if (!isBundle) { if (selectedAttributeValues != null) { foreach (var attributeValue in selectedAttributeValues) model.WeightValue = decimal.Add(model.WeightValue, attributeValue.WeightAdjustment); } else { model.WeightValue = decimal.Add(model.WeightValue, preSelectedWeightAdjustment); } } model.Weight = (model.WeightValue > 0) ? "{0} {1}".FormatCurrent(model.WeightValue.ToString("F2"), _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name) : ""; model.Height = (product.Height > 0) ? "{0} {1}".FormatCurrent(product.Height.ToString("F2"), dimension) : ""; model.Length = (product.Length > 0) ? "{0} {1}".FormatCurrent(product.Length.ToString("F2"), dimension) : ""; model.Width = (product.Width > 0) ? "{0} {1}".FormatCurrent(product.Width.ToString("F2"), dimension) : ""; if (productBundleItem != null) model.ThumbDimensions = _mediaSettings.BundledProductPictureSize; else if (isAssociatedProduct) model.ThumbDimensions = _mediaSettings.AssociatedProductPictureSize; if (model.IsAvailable) { var deliveryTime = _deliveryTimeService.GetDeliveryTime(product); if (deliveryTime != null) { model.DeliveryTimeName = deliveryTime.GetLocalized(x => x.Name); model.DeliveryTimeHexValue = deliveryTime.ColorHexValue; } } model.DisplayDeliveryTime = _catalogSettings.ShowDeliveryTimesInProductDetail; model.IsShipEnabled = product.IsShipEnabled; model.DisplayDeliveryTimeAccordingToStock = product.DisplayDeliveryTimeAccordingToStock(_catalogSettings); if (model.DeliveryTimeName.IsEmpty() && model.DisplayDeliveryTime) { model.DeliveryTimeName = T("ShoppingCart.NotAvailable"); } var quantityUnit = _quantityUnitService.GetQuantityUnit(product); if (quantityUnit != null) { model.QuantityUnitName = quantityUnit.GetLocalized(x => x.Name); } //back in stock subscriptions) if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService.FindSubscription(customer.Id, product.Id, store.Id) != null; } #endregion #region Product price model.ProductPrice.ProductId = product.Id; if (displayPrices) { model.ProductPrice.HidePrices = false; if (product.CustomerEntersPrice && !isBundleItemPricing) { model.ProductPrice.CustomerEntersPrice = true; } else { if (product.CallForPrice && !isBundleItemPricing) { model.ProductPrice.CallForPrice = true; } else { decimal taxRate = decimal.Zero; decimal oldPrice = decimal.Zero; decimal finalPriceWithoutDiscountBase = decimal.Zero; decimal finalPriceWithDiscountBase = decimal.Zero; decimal attributesTotalPriceBase = decimal.Zero; decimal finalPriceWithoutDiscount = decimal.Zero; decimal finalPriceWithDiscount = decimal.Zero; decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); if (model.ProductPrice.DynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues != null) { selectedAttributeValues.Each(x => attributesTotalPriceBase += _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(x)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (productBundleItem != null) { productBundleItem.AdditionalCharge = attributesTotalPriceBase; } finalPriceWithoutDiscountBase = _priceCalculationService.GetFinalPrice(product, productBundleItems, customer, attributesTotalPriceBase, false, selectedQuantity, productBundleItem); finalPriceWithDiscountBase = _priceCalculationService.GetFinalPrice(product, productBundleItems, customer, attributesTotalPriceBase, true, selectedQuantity, productBundleItem); finalPriceWithoutDiscountBase = _taxService.GetProductPrice(product, finalPriceWithoutDiscountBase, out taxRate); finalPriceWithDiscountBase = _taxService.GetProductPrice(product, finalPriceWithDiscountBase, out taxRate); oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _services.WorkContext.WorkingCurrency); finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, currency); finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, currency); if (productBundleItem == null || isBundleItemPricing) { if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero) model.ProductPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice); model.ProductPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount); if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase) model.ProductPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount); } model.ProductPrice.PriceValue = finalPriceWithoutDiscount; model.ProductPrice.PriceWithDiscountValue = finalPriceWithDiscount; model.BasePriceInfo = product.GetBasePriceInfo( _localizationService, _priceFormatter, _currencyService, _taxService, _priceCalculationService, currency, attributesTotalPriceBase); if (!string.IsNullOrWhiteSpace(model.ProductPrice.OldPrice) || !string.IsNullOrWhiteSpace(model.ProductPrice.PriceWithDiscount)) { model.ProductPrice.NoteWithoutDiscount = T(isBundle && product.BundlePerItemPricing ? "Products.Bundle.PriceWithoutDiscount.Note" : "Products.Price"); } if ((isBundle && product.BundlePerItemPricing && !string.IsNullOrWhiteSpace(model.ProductPrice.PriceWithDiscount)) || product.HasTierPrices) { if (!product.HasTierPrices) { model.ProductPrice.NoteWithDiscount = T("Products.Bundle.PriceWithDiscount.Note"); } model.BasePriceInfo = product.GetBasePriceInfo( _localizationService, _priceFormatter, _currencyService, _taxService, _priceCalculationService, currency, (product.Price - finalPriceWithDiscount) * (-1)); } } } } else { model.ProductPrice.HidePrices = true; model.ProductPrice.OldPrice = null; model.ProductPrice.Price = null; } #endregion #region 'Add to cart' model model.AddToCart.ProductId = product.Id; //quantity model.AddToCart.EnteredQuantity = product.OrderMinimumQuantity; //'add to cart', 'add to wishlist' buttons model.AddToCart.DisableBuyButton = product.DisableBuyButton || !_services.Permissions.Authorize(StandardPermissionProvider.EnableShoppingCart); model.AddToCart.DisableWishlistButton = product.DisableWishlistButton || !_services.Permissions.Authorize(StandardPermissionProvider.EnableWishlist); if (!displayPrices) { model.AddToCart.DisableBuyButton = true; model.AddToCart.DisableWishlistButton = true; } //pre-order model.AddToCart.AvailableForPreOrder = product.AvailableForPreOrder; //customer entered price model.AddToCart.CustomerEntersPrice = product.CustomerEntersPrice; if (model.AddToCart.CustomerEntersPrice) { var minimumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MinimumCustomerEnteredPrice, currency); var maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MaximumCustomerEnteredPrice, currency); model.AddToCart.CustomerEnteredPrice = minimumCustomerEnteredPrice; model.AddToCart.CustomerEnteredPriceRange = string.Format(T("Products.EnterProductPrice.Range"), _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, true, false), _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, true, false)); } //allowed quantities var allowedQuantities = product.ParseAllowedQuatities(); foreach (var qty in allowedQuantities) { model.AddToCart.AllowedQuantities.Add(new SelectListItem { Text = qty.ToString(), Value = qty.ToString() }); } #endregion #region Gift card model.GiftCard.IsGiftCard = product.IsGiftCard; if (model.GiftCard.IsGiftCard) { model.GiftCard.GiftCardType = product.GiftCardType; model.GiftCard.SenderName = customer.GetFullName(); model.GiftCard.SenderEmail = customer.Email; } #endregion return model; }
public void PrepareProductDetailsPictureModel( ProductDetailsPictureModel model, IList<Picture> pictures, string name, IList<int> allCombinationImageIds, bool isAssociatedProduct, ProductBundleItemData bundleItem = null, ProductVariantAttributeCombination combination = null) { model.Name = name; model.DefaultPictureZoomEnabled = _mediaSettings.DefaultPictureZoomEnabled; model.PictureZoomType = _mediaSettings.PictureZoomType; model.AlternateText = T("Media.Product.ImageAlternateTextFormat", model.Name); Picture defaultPicture = null; var combiAssignedImages = (combination == null ? null : combination.GetAssignedPictureIds()); int defaultPictureSize; if (isAssociatedProduct) defaultPictureSize = _mediaSettings.AssociatedProductPictureSize; else if (bundleItem != null) defaultPictureSize = _mediaSettings.BundledProductPictureSize; else defaultPictureSize = _mediaSettings.ProductDetailsPictureSize; if (pictures.Count > 0) { if (pictures.Count <= _catalogSettings.DisplayAllImagesNumber) { // show all images foreach (var picture in pictures) { model.PictureModels.Add(CreatePictureModel(model, picture, _mediaSettings.ProductDetailsPictureSize)); if (defaultPicture == null && combiAssignedImages != null && combiAssignedImages.Contains(picture.Id)) { model.GalleryStartIndex = model.PictureModels.Count - 1; defaultPicture = picture; } } } else { // images not belonging to any combination... allCombinationImageIds = allCombinationImageIds ?? new List<int>(); foreach (var picture in pictures.Where(p => !allCombinationImageIds.Contains(p.Id))) { model.PictureModels.Add(CreatePictureModel(model, picture, _mediaSettings.ProductDetailsPictureSize)); } // plus images belonging to selected combination if (combiAssignedImages != null) { foreach (var picture in pictures.Where(p => combiAssignedImages.Contains(p.Id))) { model.PictureModels.Add(CreatePictureModel(model, picture, _mediaSettings.ProductDetailsPictureSize)); if (defaultPicture == null) { model.GalleryStartIndex = model.PictureModels.Count - 1; defaultPicture = picture; } } } } if (defaultPicture == null) { model.GalleryStartIndex = 0; defaultPicture = pictures.First(); } } // default picture if (defaultPicture == null) { model.DefaultPictureModel = new PictureModel { Title = T("Media.Product.ImageLinkTitleFormat", model.Name), AlternateText = model.AlternateText }; if (!_catalogSettings.HideProductDefaultPictures) { model.DefaultPictureModel.ThumbImageUrl = _pictureService.GetDefaultPictureUrl(_mediaSettings.ProductThumbPictureSizeOnProductDetailsPage); model.DefaultPictureModel.ImageUrl = _pictureService.GetDefaultPictureUrl(defaultPictureSize); model.DefaultPictureModel.FullSizeImageUrl = _pictureService.GetDefaultPictureUrl(); } } else { model.DefaultPictureModel = CreatePictureModel(model, defaultPicture, defaultPictureSize); } }
public ProductDetailsModel PrepareProductDetailsPageModel( Product product, bool isAssociatedProduct = false, ProductBundleItemData productBundleItem = null, IList<ProductBundleItemData> productBundleItems = null, NameValueCollection selectedAttributes = null, NameValueCollection queryData = null) { if (product == null) throw new ArgumentNullException("product"); var model = new ProductDetailsModel { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), ProductType = product.ProductType, VisibleIndividually = product.VisibleIndividually, //Manufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id), Manufacturers = PrepareManufacturersOverviewModel(_manufacturerService.GetProductManufacturersByProductId(product.Id), null, true), ReviewCount = product.ApprovedTotalReviews, DisplayAdminLink = _services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel), //EnableHtmlTextCollapser = Convert.ToBoolean(_settingService.GetSettingByKey<string>("CatalogSettings.EnableHtmlTextCollapser")), //HtmlTextCollapsedHeight = Convert.ToString(_settingService.GetSettingByKey<string>("CatalogSettings.HtmlTextCollapsedHeight")), ShowSku = _catalogSettings.ShowProductSku, Sku = product.Sku, ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber, DisplayProductReviews = _catalogSettings.ShowProductReviewsInProductDetail, ManufacturerPartNumber = product.ManufacturerPartNumber, ShowGtin = _catalogSettings.ShowGtin, Gtin = product.Gtin, StockAvailability = product.FormatStockMessage(_localizationService), HasSampleDownload = product.IsDownload && product.HasSampleDownload, IsCurrentCustomerRegistered = _services.WorkContext.CurrentCustomer.IsRegistered() }; // get gift card values from query string if (queryData != null && queryData.Count > 0) { var giftCardItems = queryData.AllKeys .Where(x => x.EmptyNull().StartsWith("giftcard_")) .SelectMany(queryData.GetValues, (k, v) => new { key = k, value = v.TrimSafe() }); foreach (var item in giftCardItems) { var key = item.key.EmptyNull().ToLower(); if (key.EndsWith("recipientname")) model.GiftCard.RecipientName = item.value; else if (key.EndsWith("recipientemail")) model.GiftCard.RecipientEmail = item.value; else if (key.EndsWith("sendername")) model.GiftCard.SenderName = item.value; else if (key.EndsWith("senderemail")) model.GiftCard.SenderEmail = item.value; else if (key.EndsWith("message")) model.GiftCard.Message = item.value; } } // Back in stock subscriptions if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService .FindSubscription(_services.WorkContext.CurrentCustomer.Id, product.Id, _services.StoreContext.CurrentStore.Id) != null; } //template var templateCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_TEMPLATE_MODEL_KEY, product.ProductTemplateId); model.ProductTemplateViewPath = _services.Cache.Get(templateCacheKey, () => { var template = _productTemplateService.GetProductTemplateById(product.ProductTemplateId); if (template == null) template = _productTemplateService.GetAllProductTemplates().FirstOrDefault(); return template.ViewPath; }); IList<ProductBundleItemData> bundleItems = null; ProductVariantAttributeCombination combination = null; if (product.ProductType == ProductType.GroupedProduct && !isAssociatedProduct) // associated products { var searchContext = new ProductSearchContext { OrderBy = ProductSortingEnum.Position, StoreId = _services.StoreContext.CurrentStore.Id, ParentGroupedProductId = product.Id, PageSize = int.MaxValue, VisibleIndividuallyOnly = false }; var associatedProducts = _productService.SearchProducts(searchContext); foreach (var associatedProduct in associatedProducts) model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, true)); } else if (product.ProductType == ProductType.BundledProduct && productBundleItem == null) // bundled items { bundleItems = _productService.GetBundleItems(product.Id); foreach (var itemData in bundleItems.Where(x => x.Item.Product.CanBeBundleItem())) { var item = itemData.Item; var bundleItemAttributes = new NameValueCollection(); if (selectedAttributes != null) { var keyPrefix = "product_attribute_{0}_{1}".FormatInvariant(item.ProductId, item.Id); foreach (var key in selectedAttributes.AllKeys.Where(x => x.HasValue() && x.StartsWith(keyPrefix))) { bundleItemAttributes.Add(key, selectedAttributes[key]); } } var bundledProductModel = PrepareProductDetailsPageModel(item.Product, false, itemData, null, bundleItemAttributes); bundledProductModel.BundleItem.Id = item.Id; bundledProductModel.BundleItem.Quantity = item.Quantity; bundledProductModel.BundleItem.HideThumbnail = item.HideThumbnail; bundledProductModel.BundleItem.Visible = item.Visible; bundledProductModel.BundleItem.IsBundleItemPricing = item.BundleProduct.BundlePerItemPricing; var bundleItemName = item.GetLocalized(x => x.Name); if (bundleItemName.HasValue()) bundledProductModel.Name = bundleItemName; var bundleItemShortDescription = item.GetLocalized(x => x.ShortDescription); if (bundleItemShortDescription.HasValue()) bundledProductModel.ShortDescription = bundleItemShortDescription; model.BundledItems.Add(bundledProductModel); } } model = PrepareProductDetailModel(model, product, isAssociatedProduct, productBundleItem, bundleItems, selectedAttributes); IList<int> combinationPictureIds = null; if (productBundleItem == null) { combinationPictureIds = _productAttributeService.GetAllProductVariantAttributeCombinationPictureIds(product.Id); if (combination == null && model.SelectedCombination != null) combination = model.SelectedCombination; } // pictures var pictures = _pictureService.GetPicturesByProductId(product.Id); PrepareProductDetailsPictureModel(model.DetailsPictureModel, pictures, model.Name, combinationPictureIds, isAssociatedProduct, productBundleItem, combination); return model; }
protected ProductDetailsModel PrepareProductDetailsPageModel(Product product, bool isAssociatedProduct = false, ProductBundleItemData productBundleItem = null, IList<ProductBundleItemData> productBundleItems = null, FormCollection selectedAttributes = null) { if (product == null) throw new ArgumentNullException("product"); var model = new ProductDetailsModel() { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), ProductType = product.ProductType, VisibleIndividually = product.VisibleIndividually, //Manufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id), /* codehint: sm-edit */ Manufacturers = PrepareManufacturersOverviewModel(_manufacturerService.GetProductManufacturersByProductId(product.Id)), ReviewCount = product.ApprovedTotalReviews, /* codehint: sm-add */ DisplayAdminLink = _permissionService.Authorize(StandardPermissionProvider.AccessAdminPanel), EnableHtmlTextCollapser = Convert.ToBoolean(_settingService.GetSettingByKey<string>("CatalogSettings.EnableHtmlTextCollapser")), HtmlTextCollapsedHeight = Convert.ToString(_settingService.GetSettingByKey<string>("CatalogSettings.HtmlTextCollapsedHeight")), ShowSku = _catalogSettings.ShowProductSku, Sku = product.Sku, ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber, ManufacturerPartNumber = product.ManufacturerPartNumber, ShowGtin = _catalogSettings.ShowGtin, Gtin = product.Gtin, StockAvailability = product.FormatStockMessage(_localizationService), HasSampleDownload = product.IsDownload && product.HasSampleDownload, IsCurrentCustomerRegistered = _workContext.CurrentCustomer.IsRegistered() }; // Back in stock subscriptions if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService .FindSubscription(_workContext.CurrentCustomer.Id, product.Id, _storeContext.CurrentStore.Id) != null; } //template var templateCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_TEMPLATE_MODEL_KEY, product.ProductTemplateId); model.ProductTemplateViewPath = _cacheManager.Get(templateCacheKey, () => { var template = _productTemplateService.GetProductTemplateById(product.ProductTemplateId); if (template == null) template = _productTemplateService.GetAllProductTemplates().FirstOrDefault(); return template.ViewPath; }); IList<ProductBundleItemData> bundleItems = null; ProductVariantAttributeCombination combination = null; var combinationImageIds = new List<int>(); if (product.ProductType == ProductType.GroupedProduct && !isAssociatedProduct) // associated products { var searchContext = new ProductSearchContext() { StoreId = _storeContext.CurrentStore.Id, ParentGroupedProductId = product.Id, VisibleIndividuallyOnly = false }; var associatedProducts = _productService.SearchProducts(searchContext); foreach (var associatedProduct in associatedProducts) model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, true)); } else if (product.ProductType == ProductType.BundledProduct && productBundleItem == null) // bundled items { bundleItems = _productService.GetBundleItems(product.Id); foreach (var itemData in bundleItems.Where(x => x.Item.Product.CanBeBundleItem())) { var item = itemData.Item; var bundledProductModel = PrepareProductDetailsPageModel(item.Product, false, itemData); bundledProductModel.BundleItem.Id = item.Id; bundledProductModel.BundleItem.Quantity = item.Quantity; bundledProductModel.BundleItem.HideThumbnail = item.HideThumbnail; bundledProductModel.BundleItem.Visible = item.Visible; bundledProductModel.BundleItem.IsBundleItemPricing = item.BundleProduct.BundlePerItemPricing; string bundleItemName = item.GetLocalized(x => x.Name); if (bundleItemName.HasValue()) bundledProductModel.Name = bundleItemName; string bundleItemShortDescription = item.GetLocalized(x => x.ShortDescription); if (bundleItemShortDescription.HasValue()) bundledProductModel.ShortDescription = bundleItemShortDescription; model.BundledItems.Add(bundledProductModel); } } model = PrepareProductDetailModel(model, product, isAssociatedProduct, productBundleItem, bundleItems, selectedAttributes); if (productBundleItem == null) { model.Combinations.GetAllCombinationImageIds(combinationImageIds); if (combination == null && model.CombinationSelected != null) combination = model.CombinationSelected; } // pictures var pictures = _pictureService.GetPicturesByProductId(product.Id); PrepareProductDetailsPictureModel(model.DetailsPictureModel, pictures, model.Name, combinationImageIds, isAssociatedProduct, productBundleItem, combination); return model; }