/// <summary>
        /// Formats attributes
        /// </summary>
        /// <param name="attributesXml">Attributes in XML format</param>
        /// <param name="customer">Customer</param>
        /// <param name="serapator">Serapator</param>
        /// <param name="htmlEncode">A value indicating whether to encode (HTML) values</param>
        /// <param name="renderPrices">A value indicating whether to render prices</param>
        /// <param name="allowHyperlinks">A value indicating whether to HTML hyperink tags could be rendered (if required)</param>
        /// <returns>Attributes</returns>
        public virtual string FormatAttributes(string attributesXml,
                                               User customer,
                                               Currency workingCurrency,
                                               string serapator     = "<br />",
                                               bool htmlEncode      = true,
                                               bool renderPrices    = true,
                                               bool allowHyperlinks = true)
        {
            var result = new StringBuilder();

            var attributes = _checkoutAttributeParser.ParseCheckoutAttributes(attributesXml);

            for (int i = 0; i < attributes.Count; i++)
            {
                var attribute = attributes[i];
                var valuesStr = _checkoutAttributeParser.ParseValues(attributesXml, attribute.Id);
                for (int j = 0; j < valuesStr.Count; j++)
                {
                    string valueStr           = valuesStr[j];
                    string formattedAttribute = "";
                    if (!attribute.ShouldHaveValues())
                    {
                        //no values
                        if (attribute.AttributeControlType == AttributeControlType.MultilineTextbox)
                        {
                            //multiline textbox
                            var attributeName = attribute.Name;
                            //encode (if required)
                            //if (htmlEncode)
                            //    attributeName = HttpUtility.HtmlEncode(attributeName);
                            formattedAttribute = string.Format("{0}: {1}", attributeName, HtmlHelper.FormatText(valueStr, false, true, false, false, false, false));
                            //we never encode multiline textbox input
                        }
                        else if (attribute.AttributeControlType == AttributeControlType.FileUpload)
                        {
                            //file upload
                            Guid downloadGuid;
                            Guid.TryParse(valueStr, out downloadGuid);
                            var download = _downloadService.GetDownloadByGuid(downloadGuid);
                            if (download != null)
                            {
                                //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs)
                                string attributeText;
                                var    fileName = string.Format("{0}{1}",
                                                                download.Filename ?? download.DownloadGuid.ToString(),
                                                                download.Extension);
                                //encode (if required)
                                //if (htmlEncode)
                                //    fileName = HttpUtility.HtmlEncode(fileName);
                                if (allowHyperlinks)
                                {
                                    //hyperlinks are allowed
                                    //var downloadLink = string.Format("{0}download/getfileupload/?downloadId={1}", _webHelper.GetStoreLocation(false), download.DownloadGuid);
                                    var downloadLink = string.Empty;
                                    attributeText = string.Format("<a href=\"{0}\" class=\"fileuploadattribute\">{1}</a>", downloadLink, fileName);
                                }
                                else
                                {
                                    //hyperlinks aren't allowed
                                    attributeText = fileName;
                                }
                                var attributeName = attribute.Name;
                                //encode (if required)
                                //if (htmlEncode)
                                //    attributeName = HttpUtility.HtmlEncode(attributeName);
                                formattedAttribute = string.Format("{0}: {1}", attributeName, attributeText);
                            }
                        }
                        else
                        {
                            //other attributes (textbox, datepicker)
                            formattedAttribute = string.Format("{0}: {1}", attribute.Name, valueStr);
                            //encode (if required)
                            //if (htmlEncode)
                            //    formattedAttribute = HttpUtility.HtmlEncode(formattedAttribute);
                        }
                    }
                    else
                    {
                        int attributeValueId;
                        if (int.TryParse(valueStr, out attributeValueId))
                        {
                            var attributeValue = _checkoutAttributeService.GetCheckoutAttributeValueById(attributeValueId);
                            if (attributeValue != null)
                            {
                                formattedAttribute = string.Format("{0}: {1}", attribute.Name, attributeValue.Name);
                                if (renderPrices)
                                {
                                    decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(attributeValue, customer);
                                    decimal priceAdjustment     = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, workingCurrency);

                                    if (priceAdjustmentBase > 0)
                                    {
                                        string priceAdjustmentStr = _priceFormatter.FormatPrice(priceAdjustment, true, workingCurrency);
                                        formattedAttribute += string.Format(" [+{0}]", priceAdjustmentStr);
                                    }
                                }
                            }
                            //encode (if required)
                            //if (htmlEncode)
                            //    formattedAttribute = HttpUtility.HtmlEncode(formattedAttribute);
                        }
                    }

                    if (!String.IsNullOrEmpty(formattedAttribute))
                    {
                        if (i != 0 || j != 0)
                        {
                            result.Append(serapator);
                        }
                        result.Append(formattedAttribute);
                    }
                }
            }

            return(result.ToString());
        }
예제 #2
0
        protected virtual ProductDetailsDto PrepareProductDetailsPageDto(Product product,
                                                                         ShoppingCartItem updatecartitem = null, bool isAssociatedProduct = false)
        {
            if (product == null)
            {
                throw new ArgumentNullException("product");
            }

            #region Standard properties

            var model = new ProductDetailsDto
            {
                Id               = product.Id,
                Name             = product.Name,
                ShortDescription = product.ShortDescription,
                FullDescription  = product.FullDescription,
                MetaKeywords     = product.MetaKeywords,
                MetaDescription  = product.MetaDescription,
                MetaTitle        = product.MetaTitle,
                //SeName = product.GetSeName(),
                ShowSku = CatalogSettings.ShowProductSku,
                Sku     = product.Sku,
                ShowManufacturerPartNumber      = CatalogSettings.ShowManufacturerPartNumber,
                FreeShippingNotificationEnabled = CatalogSettings.ShowFreeShippingNotification,
                ManufacturerPartNumber          = product.ManufacturerPartNumber,
                ShowGtin                   = CatalogSettings.ShowGtin,
                Gtin                       = product.Gtin,
                StockAvailability          = product.FormatStockMessage("", _productAttributeParser),
                HasSampleDownload          = product.IsDownload && product.HasSampleDownload,
                DisplayDiscontinuedMessage = !product.Published && CatalogSettings.DisplayDiscontinuedMessageForUnpublishedProducts
            };

            //automatically generate product description?
            if (SeoSettings.GenerateProductMetaDescription && String.IsNullOrEmpty(model.MetaDescription))
            {
                //based on short description
                model.MetaDescription = model.ShortDescription;
            }

            //shipping info
            model.IsShipEnabled = product.IsShipEnabled;
            if (product.IsShipEnabled)
            {
                model.IsFreeShipping = product.IsFreeShipping;
                //delivery date
                var deliveryDate = _shippingDomainServie.GetDeliveryDateById(product.DeliveryDateId);
                if (deliveryDate != null)
                {
                    //model.DeliveryDate = deliveryDate.GetLocalized(dd => dd.Name);
                    model.DeliveryDate = deliveryDate.Name;
                }
            }

            //email a friend
            model.EmailAFriendEnabled = CatalogSettings.EmailAFriendEnabled;
            //compare products
            model.CompareProductsEnabled = CatalogSettings.CompareProductsEnabled;

            #endregion

            #region Vendor details

            //vendor
            //if (_vendorSettings.ShowVendorOnProductDetailsPage)
            {
                var vendor = _vendorDomainService.GetVendorById(product.VendorId);
                if (vendor != null && !vendor.Deleted && vendor.Active)
                {
                    model.ShowVendor = true;
                    model.VendorDto  = Mapper.Map <VendorBriefInfoDto>(vendor);
                    //model.VendorModel = new VendorBriefInfoDto
                    //{
                    //    Id = vendor.Id,
                    //    Name = vendor.GetLocalized(x => x.Name),
                    //    SeName = vendor.GetSeName(),
                    //};
                }
            }

            #endregion

            #region Page sharing

            //if (_catalogSettings.ShowShareButton && !String.IsNullOrEmpty(_catalogSettings.PageShareCode))
            //{
            //    var shareCode = _catalogSettings.PageShareCode;
            //    if (_webHelper.IsCurrentConnectionSecured())
            //    {
            //        //need to change the addthis link to be https linked when the page is, so that the page doesnt ask about mixed mode when viewed in https...
            //        shareCode = shareCode.Replace("http://", "https://");
            //    }
            //    model.PageShareCode = shareCode;
            //}

            #endregion

            #region Back in stock subscriptions

            if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                product.BackorderMode == BackorderMode.NoBackorders &&
                product.AllowBackInStockSubscriptions &&
                product.GetTotalStockQuantity() <= 0)
            {
                //out of stock
                model.DisplayBackInStockSubscription = true;
            }

            #endregion

            #region Breadcrumb

            //do not prepare this model for the associated products. anyway it's not used
            //if (_catalogSettings.CategoryBreadcrumbEnabled && !isAssociatedProduct)
            //{
            //    var breadcrumbCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_BREADCRUMB_MODEL_KEY,
            //        product.Id,
            //        _workContext.WorkingLanguage.Id,
            //        string.Join(",", _workContext.CurrentCustomer.GetCustomerRoleIds()),
            //        _storeContext.CurrentStore.Id);
            //    model.Breadcrumb = _cacheManager.Get(breadcrumbCacheKey, () =>
            //    {
            //        var breadcrumbModel = new ProductDetailsModel.ProductBreadcrumbModel
            //        {
            //            Enabled = _catalogSettings.CategoryBreadcrumbEnabled,
            //            ProductId = product.Id,
            //            ProductName = product.GetLocalized(x => x.Name),
            //            ProductSeName = product.GetSeName()
            //        };
            //        var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id);
            //        if (productCategories.Count > 0)
            //        {
            //            var category = productCategories[0].Category;
            //            if (category != null)
            //            {
            //                foreach (
            //                    var catBr in
            //                        category.GetCategoryBreadCrumb(_categoryService, _aclService, _storeMappingService))
            //                {
            //                    breadcrumbModel.CategoryBreadcrumb.Add(new CategorySimpleModel
            //                    {
            //                        Id = catBr.Id,
            //                        Name = catBr.GetLocalized(x => x.Name),
            //                        SeName = catBr.GetSeName(),
            //                        IncludeInTopMenu = catBr.IncludeInTopMenu
            //                    });
            //                }
            //            }
            //        }
            //        return breadcrumbModel;
            //    });
            //}

            #endregion

            #region Product tags

            //do not prepare this model for the associated products. anyway it's not used
            //if (!isAssociatedProduct)
            //{
            //    var productTagsCacheKey = string.Format(ModelCacheEventConsumer.PRODUCTTAG_BY_PRODUCT_MODEL_KEY, product.Id, _workContext.WorkingLanguage.Id, _storeContext.CurrentStore.Id);
            //    model.ProductTags = _cacheManager.Get(productTagsCacheKey, () =>
            //        product.ProductTags
            //        //filter by store
            //        .Where(x => _productTagService.GetProductCount(x.Id, _storeContext.CurrentStore.Id) > 0)
            //        .Select(x => new ProductTagDto
            //        {
            //            Id = x.Id,
            //            Name = x.GetLocalized(y => y.Name),
            //            SeName = x.GetSeName(),
            //            ProductCount = _productTagService.GetProductCount(x.Id, _storeContext.CurrentStore.Id)
            //        })
            //        .ToList());
            //}

            #endregion

            #region Templates

            //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();
            }
            if (template == null)
            {
                throw new Exception("No default template could be loaded");
            }
            //return template.ViewPath;
            model.ProductTemplateViewPath = template.ViewPath;
            //});

            #endregion

            #region Pictures

            model.DefaultPictureZoomEnabled = MediaSettings.DefaultPictureZoomEnabled;
            //default picture
            var defaultPictureSize = isAssociatedProduct ?
                                     MediaSettings.AssociatedProductPictureSize :
                                     MediaSettings.ProductDetailsPictureSize;
            //prepare picture models
            //var productPicturesCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_DETAILS_PICTURES_MODEL_KEY, product.Id, defaultPictureSize, isAssociatedProduct, _workContext.WorkingLanguage.Id, _webHelper.IsCurrentConnectionSecured(), _storeContext.CurrentStore.Id);
            //var cachedPictures = _cacheManager.Get(productPicturesCacheKey, () =>
            //{
            var pictures            = _pictureDomainService.GetPicturesByProductId(product.Id);
            var defaultPicture      = pictures.FirstOrDefault();
            var defaultPictureModel = new PictureDto
            {
                ImageUrl         = _pictureDomainService.GetPictureUrl(defaultPicture, defaultPictureSize, !isAssociatedProduct),
                FullSizeImageUrl = _pictureDomainService.GetPictureUrl(defaultPicture, 0, !isAssociatedProduct),
                Title            = string.Format(InfoMsg.Media_Product_ImageLinkTitleFormat_Details, model.Name),
                AlternateText    = string.Format(InfoMsg.Media_Product_ImageAlternateTextFormat_Details, model.Name),
            };
            //"title" attribute
            defaultPictureModel.Title = (defaultPicture != null && !string.IsNullOrEmpty(defaultPicture.TitleAttribute)) ?
                                        defaultPicture.TitleAttribute :
                                        string.Format(InfoMsg.Media_Product_ImageLinkTitleFormat_Details, model.Name);
            //"alt" attribute
            defaultPictureModel.AlternateText = (defaultPicture != null && !string.IsNullOrEmpty(defaultPicture.AltAttribute)) ?
                                                defaultPicture.AltAttribute :
                                                string.Format(InfoMsg.Media_Product_ImageAlternateTextFormat_Details, model.Name);

            //all pictures
            var pictureModels = new List <PictureDto>();
            foreach (var picture in pictures)
            {
                var pictureModel = new PictureDto
                {
                    ImageUrl         = _pictureDomainService.GetPictureUrl(picture, MediaSettings.ProductThumbPictureSizeOnProductDetailsPage),
                    FullSizeImageUrl = _pictureDomainService.GetPictureUrl(picture),
                    Title            = string.Format(InfoMsg.Media_Product_ImageLinkTitleFormat_Details, model.Name),
                    AlternateText    = string.Format(InfoMsg.Media_Product_ImageAlternateTextFormat_Details, model.Name),
                };
                //"title" attribute
                pictureModel.Title = !string.IsNullOrEmpty(picture.TitleAttribute) ?
                                     picture.TitleAttribute :
                                     string.Format(InfoMsg.Media_Product_ImageLinkTitleFormat_Details, model.Name);
                //"alt" attribute
                pictureModel.AlternateText = !string.IsNullOrEmpty(picture.AltAttribute) ?
                                             picture.AltAttribute :
                                             string.Format(InfoMsg.Media_Product_ImageAlternateTextFormat_Details, model.Name);

                pictureModels.Add(pictureModel);
            }

            //return new { DefaultPictureModel = defaultPictureModel, PictureModels = pictureModels };

            var cachedPictures = new { DefaultPictureModel = defaultPictureModel, PictureModels = pictureModels };
            //});
            model.DefaultPictureModel = cachedPictures.DefaultPictureModel;
            model.PictureModels       = cachedPictures.PictureModels;

            #endregion

            #region Product price

            model.ProductPrice.ProductId = product.Id;
            //if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
            {
                model.ProductPrice.HidePrices = false;
                if (product.CustomerEntersPrice)
                {
                    model.ProductPrice.CustomerEntersPrice = true;
                }
                else
                {
                    if (product.CallForPrice)
                    {
                        model.ProductPrice.CallForPrice = true;
                    }
                    else
                    {
                        decimal taxRate;
                        decimal oldPriceBase = _taxDomainService.GetProductPrice(product, product.OldPrice, CurrentUser, out taxRate);
                        decimal finalPriceWithoutDiscountBase = _taxDomainService.GetProductPrice(product, _priceCalculationDomainService.GetFinalPrice(product, CurrentUser, includeDiscounts: false), CurrentUser, out taxRate);
                        decimal finalPriceWithDiscountBase    = _taxDomainService.GetProductPrice(product, _priceCalculationDomainService.GetFinalPrice(product, CurrentUser, includeDiscounts: true), CurrentUser, out taxRate);

                        decimal oldPrice = _currencyDomainService.ConvertFromPrimaryStoreCurrency(oldPriceBase, WorkingCurrency);
                        decimal finalPriceWithoutDiscount = _currencyDomainService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, WorkingCurrency);
                        decimal finalPriceWithDiscount    = _currencyDomainService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, WorkingCurrency);

                        if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero)
                        {
                            model.ProductPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice, true, WorkingCurrency);
                        }

                        model.ProductPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount, true, WorkingCurrency);

                        if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase)
                        {
                            model.ProductPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount, true, WorkingCurrency);
                        }

                        model.ProductPrice.PriceValue = finalPriceWithDiscount;

                        //property for German market
                        //we display tax/shipping info only with "shipping enabled" for this product
                        //we also ensure this it's not free shipping
                        model.ProductPrice.DisplayTaxShippingInfo = CatalogSettings.DisplayTaxShippingInfoProductDetailsPage &&
                                                                    product.IsShipEnabled &&
                                                                    !product.IsFreeShipping;

                        //PAngV baseprice (used in Germany)
                        //model.ProductPrice.BasePricePAngV = product.FormatBasePrice(finalPriceWithDiscountBase,
                        //    _localizationService, _measureService, _currencyService, _workContext, _priceFormatter);

                        //currency code
                        model.ProductPrice.CurrencyCode = WorkingCurrency.CurrencyCode;

                        //rental
                        if (product.IsRental)
                        {
                            model.ProductPrice.IsRental = true;
                            var priceStr = _priceFormatter.FormatPrice(finalPriceWithDiscount, true, WorkingCurrency);
                            model.ProductPrice.RentalPrice = _priceFormatter.FormatRentalProductPeriod(product, priceStr);
                        }
                    }
                }
            }
            //else
            //{
            //    model.ProductPrice.HidePrices = true;
            //    model.ProductPrice.OldPrice = null;
            //    model.ProductPrice.Price = null;
            //}
            #endregion

            #region 'Add to cart' model

            model.AddToCart.ProductId = product.Id;
            model.AddToCart.UpdatedShoppingCartItemId = updatecartitem != null ? updatecartitem.Id : 0;

            //quantity
            model.AddToCart.EnteredQuantity = updatecartitem != null ? updatecartitem.Quantity : product.OrderMinimumQuantity;
            //allowed quantities
            var allowedQuantities = product.ParseAllowedQuantities();
            foreach (var qty in allowedQuantities)
            {
                //model.AddToCart.AllowedQuantities.Add(new SelectListItem
                //{
                //    Text = qty.ToString(),
                //    Value = qty.ToString(),
                //    Selected = updatecartitem != null && updatecartitem.Quantity == qty
                //});
                model.AddToCart.AllowedQuantities.Add(qty);
            }
            //minimum quantity notification
            if (product.OrderMinimumQuantity > 1)
            {
                model.AddToCart.MinimumQuantityNotification = string.Format(InfoMsg.Products_MinimumQuantityNotification, product.OrderMinimumQuantity);
            }

            //'add to cart', 'add to wishlist' buttons
            model.AddToCart.DisableBuyButton      = product.DisableBuyButton;      //|| !_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart);
            model.AddToCart.DisableWishlistButton = product.DisableWishlistButton; //|| !_permissionService.Authorize(StandardPermissionProvider.EnableWishlist);
            //if (!_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
            //{
            //    model.AddToCart.DisableBuyButton = true;
            //    model.AddToCart.DisableWishlistButton = true;
            //}
            //pre-order
            if (product.AvailableForPreOrder)
            {
                model.AddToCart.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                                       product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                model.AddToCart.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
            }
            //rental
            model.AddToCart.IsRental = product.IsRental;

            //customer entered price
            model.AddToCart.CustomerEntersPrice = product.CustomerEntersPrice;
            if (model.AddToCart.CustomerEntersPrice)
            {
                decimal minimumCustomerEnteredPrice = _currencyDomainService.ConvertFromPrimaryStoreCurrency(product.MinimumCustomerEnteredPrice, WorkingCurrency);
                decimal maximumCustomerEnteredPrice = _currencyDomainService.ConvertFromPrimaryStoreCurrency(product.MaximumCustomerEnteredPrice, WorkingCurrency);

                model.AddToCart.CustomerEnteredPrice      = updatecartitem != null ? updatecartitem.CustomerEnteredPrice : minimumCustomerEnteredPrice;
                model.AddToCart.CustomerEnteredPriceRange = string.Format(InfoMsg.Products_EnterProductPrice_Range,
                                                                          _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, false, false, WorkingCurrency),
                                                                          _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, false, false, WorkingCurrency));
            }

            #endregion

            #region Gift card

            model.GiftCard.IsGiftCard = product.IsGiftCard;
            if (model.GiftCard.IsGiftCard)
            {
                model.GiftCard.GiftCardType = product.GiftCardType;

                if (updatecartitem == null)
                {
                    model.GiftCard.SenderName  = CurrentUser.FullName;
                    model.GiftCard.SenderEmail = CurrentUser.EmailAddress;
                }
                else
                {
                    string giftCardRecipientName, giftCardRecipientEmail, giftCardSenderName, giftCardSenderEmail, giftCardMessage;
                    _productAttributeParser.GetGiftCardAttribute(updatecartitem.AttributesXml,
                                                                 out giftCardRecipientName, out giftCardRecipientEmail,
                                                                 out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage);

                    model.GiftCard.RecipientName  = giftCardRecipientName;
                    model.GiftCard.RecipientEmail = giftCardRecipientEmail;
                    model.GiftCard.SenderName     = giftCardSenderName;
                    model.GiftCard.SenderEmail    = giftCardSenderEmail;
                    model.GiftCard.Message        = giftCardMessage;
                }
            }

            #endregion

            #region Product attributes

            //performance optimization
            //We cache a value indicating whether a product has attributes
            IList <ProductAttributeMapping> productAttributeMapping = null;
            // string cacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_HAS_PRODUCT_ATTRIBUTES_KEY, product.Id);
            //var hasProductAttributesCache = _cacheManager.Get<bool?>(cacheKey);
            //if (!hasProductAttributesCache.HasValue)
            {
                //no value in the cache yet
                //let's load attributes and cache the result (true/false)
                productAttributeMapping = _productAttributeDomainService.GetProductAttributeMappingsByProductId(product.Id);
                //hasProductAttributesCache = productAttributeMapping.Count > 0;
                //_cacheManager.Set(cacheKey, hasProductAttributesCache, 60);
            }
            //if (hasProductAttributesCache.Value && productAttributeMapping == null)
            //{
            //    //cache indicates that the product has attributes
            //    //let's load them
            //    productAttributeMapping = _productAttributeService.GetProductAttributeMappingsByProductId(product.Id);
            //}
            if (productAttributeMapping == null)
            {
                productAttributeMapping = new List <ProductAttributeMapping>();
            }
            foreach (var attribute in productAttributeMapping)
            {
                var attributeModel = new ProductDetailsDto.ProductAttributeDto
                {
                    Id                   = attribute.Id,
                    ProductId            = product.Id,
                    ProductAttributeId   = attribute.ProductAttributeId,
                    Name                 = attribute.ProductAttribute.Name,
                    Description          = attribute.ProductAttribute.Description,
                    TextPrompt           = attribute.TextPrompt,
                    IsRequired           = attribute.IsRequired,
                    AttributeControlType = attribute.AttributeControlType,
                    DefaultValue         = updatecartitem != null ? null : attribute.DefaultValue,
                    HasCondition         = !String.IsNullOrEmpty(attribute.ConditionAttributeXml)
                };
                if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions))
                {
                    attributeModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions
                                                           .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                           .ToList();
                }

                if (attribute.ShouldHaveValues())
                {
                    //values
                    var attributeValues = _productAttributeDomainService.GetProductAttributeValues(attribute.Id);
                    foreach (var attributeValue in attributeValues)
                    {
                        var valueModel = new ProductDetailsDto.ProductAttributeValueDto
                        {
                            Id              = attributeValue.Id,
                            Name            = attributeValue.Name,
                            ColorSquaresRgb = attributeValue.ColorSquaresRgb, //used with "Color squares" attribute type
                            IsPreSelected   = attributeValue.IsPreSelected
                        };
                        attributeModel.Values.Add(valueModel);

                        //display price if allowed
                        //if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            decimal taxRate;

                            decimal attributeValuePriceAdjustment = _priceCalculationDomainService.GetProductAttributeValuePriceAdjustment(attributeValue);
                            decimal priceAdjustmentBase           = _taxDomainService.GetProductPrice(product, attributeValuePriceAdjustment, CurrentUser, out taxRate);
                            decimal priceAdjustment = _currencyDomainService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, WorkingCurrency);
                            if (priceAdjustmentBase > decimal.Zero)
                            {
                                valueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, false, false, WorkingCurrency);
                            }
                            else if (priceAdjustmentBase < decimal.Zero)
                            {
                                valueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, false, false, WorkingCurrency);
                            }

                            valueModel.PriceAdjustmentValue = priceAdjustment;
                        }

                        //picture
                        if (attributeValue.PictureId > 0)
                        {
                            //var productAttributePictureCacheKey = string.Format(ModelCacheEventConsumer.PRODUCTATTRIBUTE_PICTURE_MODEL_KEY,
                            //    attributeValue.PictureId,
                            //    _webHelper.IsCurrentConnectionSecured(),
                            //    _storeContext.CurrentStore.Id);
                            //valueModel.PictureModel = _cacheManager.Get(productAttributePictureCacheKey, () =>
                            //{

                            var valuePicture = _pictureDomainService.GetPictureById(attributeValue.PictureId);
                            if (valuePicture != null)
                            {
                                valueModel.PictureModel = new PictureDto()
                                {
                                    FullSizeImageUrl = _pictureDomainService.GetPictureUrl(valuePicture),
                                    ImageUrl         = _pictureDomainService.GetPictureUrl(valuePicture, defaultPictureSize)
                                };
                            }
                            valueModel.PictureModel = new PictureDto();
                            //});
                        }
                    }
                }

                //set already selected attributes (if we're going to update the existing shopping cart item)
                if (updatecartitem != null)
                {
                    switch (attribute.AttributeControlType)
                    {
                    case AttributeControlType.DropdownList:
                    case AttributeControlType.RadioList:
                    case AttributeControlType.Checkboxes:
                    case AttributeControlType.ColorSquares:
                    {
                        if (!String.IsNullOrEmpty(updatecartitem.AttributesXml))
                        {
                            //clear default selection
                            foreach (var item in attributeModel.Values)
                            {
                                item.IsPreSelected = false;
                            }

                            //select new values
                            var selectedValues = _productAttributeParser.ParseProductAttributeValues(updatecartitem.AttributesXml);
                            foreach (var attributeValue in selectedValues)
                            {
                                foreach (var item in attributeModel.Values)
                                {
                                    if (attributeValue.Id == item.Id)
                                    {
                                        item.IsPreSelected = true;
                                    }
                                }
                            }
                        }
                    }
                    break;

                    case AttributeControlType.ReadonlyCheckboxes:
                    {
                        //do nothing
                        //values are already pre-set
                    }
                    break;

                    case AttributeControlType.TextBox:
                    case AttributeControlType.MultilineTextbox:
                    {
                        if (!String.IsNullOrEmpty(updatecartitem.AttributesXml))
                        {
                            var enteredText = _productAttributeParser.ParseValues(updatecartitem.AttributesXml, attribute.Id);
                            if (enteredText.Count > 0)
                            {
                                attributeModel.DefaultValue = enteredText[0];
                            }
                        }
                    }
                    break;

                    case AttributeControlType.Datepicker:
                    {
                        //keep in mind my that the code below works only in the current culture
                        var selectedDateStr = _productAttributeParser.ParseValues(updatecartitem.AttributesXml, attribute.Id);
                        if (selectedDateStr.Count > 0)
                        {
                            DateTime selectedDate;
                            if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture,
                                                       DateTimeStyles.None, out selectedDate))
                            {
                                //successfully parsed
                                attributeModel.SelectedDay   = selectedDate.Day;
                                attributeModel.SelectedMonth = selectedDate.Month;
                                attributeModel.SelectedYear  = selectedDate.Year;
                            }
                        }
                    }
                    break;

                    case AttributeControlType.FileUpload:
                    {
                        if (!String.IsNullOrEmpty(updatecartitem.AttributesXml))
                        {
                            var  downloadGuidStr = _productAttributeParser.ParseValues(updatecartitem.AttributesXml, attribute.Id).FirstOrDefault();
                            Guid downloadGuid;
                            Guid.TryParse(downloadGuidStr, out downloadGuid);
                            var download = _downloadDomainService.GetDownloadByGuid(downloadGuid);
                            if (download != null)
                            {
                                attributeModel.DefaultValue = download.DownloadGuid.ToString();
                            }
                        }
                    }
                    break;

                    default:
                        break;
                    }
                }

                model.ProductAttributes.Add(attributeModel);
            }

            #endregion

            #region Product specifications

            //do not prepare this model for the associated products. any it's not used
            if (!isAssociatedProduct)
            {
                model.ProductSpecifications = this.PrepareProductSpecificationModel(
                    _specificationAttributeDomainService,
                    _cacheManager,
                    product);
            }

            #endregion

            #region Product review overview

            model.ProductReviewOverview = new ProductReviewOverviewDto
            {
                ProductId            = product.Id,
                RatingSum            = product.ApprovedRatingSum,
                TotalReviews         = product.ApprovedTotalReviews,
                AllowCustomerReviews = product.AllowCustomerReviews
            };

            #endregion

            #region Tier prices

            //if (product.HasTierPrices && _permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
            {
                model.TierPrices = product.TierPrices
                                   .OrderBy(x => x.Quantity)
                                   .ToList()
                                   .FilterByStore(_storeContext.CurrentStore.Id)
                                   .FilterForCustomer(CurrentUser)
                                   .RemoveDuplicatedQuantities()
                                   .Select(tierPrice =>
                {
                    var m = new ProductDetailsDto.TierPriceDto
                    {
                        Quantity = tierPrice.Quantity,
                    };
                    decimal taxRate;

                    decimal priceBase = _taxDomainService.GetProductPrice(product, _priceCalculationDomainService.GetFinalPrice(product, CurrentUser, decimal.Zero, CatalogSettings.DisplayTierPricesWithDiscounts, tierPrice.Quantity), CurrentUser, out taxRate);
                    decimal price     = _currencyDomainService.ConvertFromPrimaryStoreCurrency(priceBase, WorkingCurrency);
                    m.Price           = _priceFormatter.FormatPrice(price, false, false, WorkingCurrency);
                    return(m);
                })
                                   .ToList();
            }

            #endregion

            #region Manufacturers

            //do not prepare this model for the associated products. any it's not used
            if (!isAssociatedProduct)
            {
                //string manufacturersCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_MANUFACTURERS_MODEL_KEY,
                //    product.Id,
                //    _workContext.WorkingLanguage.Id,
                //    string.Join(",", _workContext.CurrentCustomer.GetCustomerRoleIds()),
                //    _storeContext.CurrentStore.Id);
                //model.ProductManufacturers = _cacheManager.Get(manufacturersCacheKey, () =>
                //    _manufacturerDomainService.GetProductManufacturersByProductId(product.Id)
                //    .Select(x => x.Manufacturer.ToModel())
                //    .ToList()
                //    );
                var manufacturers = _manufacturerDomainService.GetProductManufacturersByProductId(product.Id);
                model.ProductManufacturers = Mapper.Map <IList <ManufacturerDto> >(manufacturers);
            }
            #endregion

            #region Rental products

            if (product.IsRental)
            {
                model.IsRental = true;
                //set already entered dates attributes (if we're going to update the existing shopping cart item)
                if (updatecartitem != null)
                {
                    model.RentalStartDate = updatecartitem.RentalStartDateUtc;
                    model.RentalEndDate   = updatecartitem.RentalEndDateUtc;
                }
            }

            #endregion

            #region Associated products


            if (product.ProductType == ProductType.GroupedProduct)
            {
                //ensure no circular references
                if (!isAssociatedProduct)
                {
                    var associatedProducts = _productDomainService.GetAssociatedProducts(product.Id, _storeContext.CurrentStore.Id);
                    foreach (var associatedProduct in associatedProducts)
                    {
                        model.AssociatedProducts.Add(PrepareProductDetailsPageDto(associatedProduct, null, true));
                    }
                }
            }

            #endregion

            return(model);
        }