public static IEnumerable<ProductOverviewModel> PrepareProductOverviewModels(this Controller controller,
            IWorkContext workContext,
            IStoreContext storeContext,
            ICategoryService categoryService,
            IProductService productService,
            ISpecificationAttributeService specificationAttributeService,
            IPriceCalculationService priceCalculationService,
            IPriceFormatter priceFormatter,
            IPermissionService permissionService,
            ILocalizationService localizationService,
            ITaxService taxService,
            ICurrencyService currencyService,
            IPictureService pictureService,
            IWebHelper webHelper,
            ICacheManager cacheManager,
            CatalogSettings catalogSettings,
            MediaSettings mediaSettings,
            IEnumerable<Product> products,
            bool preparePriceModel = true, bool preparePictureModel = true,
            int? productThumbPictureSize = null, bool prepareSpecificationAttributes = false,
            bool forceRedirectionAfterAddingToCart = false)
        {
            if (products == null)
                throw new ArgumentNullException("products");

            var models = new List<ProductOverviewModel>();
            foreach (var product in products)
            {
                var model = new ProductOverviewModel
                {
                    Id = product.Id,
                    Name = product.GetLocalized(x => x.Name),
                    ShortDescription = product.GetLocalized(x => x.ShortDescription),
                    FullDescription = product.GetLocalized(x => x.FullDescription),
                    SeName = product.GetSeName(),
                };
                //price
                if (preparePriceModel)
                {
                    #region Prepare product price

                    var priceModel = new ProductOverviewModel.ProductPriceModel
                    {
                        ForceRedirectionAfterAddingToCart = forceRedirectionAfterAddingToCart
                    };

                    switch (product.ProductType)
                    {
                        case ProductType.GroupedProduct:
                            {
                                #region Grouped product

                                var associatedProducts = productService.GetAssociatedProducts(product.Id, storeContext.CurrentStore.Id);

                                switch (associatedProducts.Count)
                                {
                                    case 0:
                                        {
                                            //no associated products
                                            //priceModel.DisableBuyButton = true;
                                            //priceModel.DisableWishlistButton = true;
                                            //compare products
                                            priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                                            //priceModel.AvailableForPreOrder = false;
                                        }
                                        break;
                                    default:
                                        {
                                            //we have at least one associated product
                                            //priceModel.DisableBuyButton = true;
                                            //priceModel.DisableWishlistButton = true;
                                            //compare products
                                            priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                                            //priceModel.AvailableForPreOrder = false;

                                            if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                                            {
                                                //find a minimum possible price
                                                decimal? minPossiblePrice = null;
                                                Product minPriceProduct = null;
                                                foreach (var associatedProduct in associatedProducts)
                                                {
                                                    //calculate for the maximum quantity (in case if we have tier prices)
                                                    var tmpPrice = priceCalculationService.GetFinalPrice(associatedProduct,
                                                        workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);
                                                    if (!minPossiblePrice.HasValue || tmpPrice < minPossiblePrice.Value)
                                                    {
                                                        minPriceProduct = associatedProduct;
                                                        minPossiblePrice = tmpPrice;
                                                    }
                                                }
                                                if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice)
                                                {
                                                    if (minPriceProduct.CallForPrice)
                                                    {
                                                        priceModel.OldPrice = null;
                                                        priceModel.Price = localizationService.GetResource("Products.CallForPrice");
                                                    }
                                                    else if (minPossiblePrice.HasValue)
                                                    {
                                                        //calculate prices
                                                        decimal taxRate;
                                                        decimal finalPriceBase = taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate);
                                                        decimal finalPrice = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                                        priceModel.OldPrice = null;
                                                        priceModel.Price = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));

                                                    }
                                                    else
                                                    {
                                                        //Actually it's not possible (we presume that minimalPrice always has a value)
                                                        //We never should get here
                                                        Debug.WriteLine("Cannot calculate minPrice for product #{0}", product.Id);
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                //hide prices
                                                priceModel.OldPrice = null;
                                                priceModel.Price = null;
                                            }
                                        }
                                        break;
                                }

                                #endregion
                            }
                            break;
                        case ProductType.SimpleProduct:
                        default:
                            {
                                #region Simple product

                                //add to cart button
                                priceModel.DisableBuyButton = product.DisableBuyButton ||
                                    !permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                    !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                                //add to wishlist button
                                priceModel.DisableWishlistButton = product.DisableWishlistButton ||
                                    !permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                    !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);
                                //compare products
                                priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;

                                //rental
                                priceModel.IsRental = product.IsRental;

                                //pre-order
                                if (product.AvailableForPreOrder)
                                {
                                    priceModel.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                        product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                                    priceModel.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
                                }

                                //prices
                                if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                                {
                                    if (!product.CustomerEntersPrice)
                                    {
                                        if (product.CallForPrice)
                                        {
                                            //call for price
                                            priceModel.OldPrice = null;
                                            priceModel.Price = localizationService.GetResource("Products.CallForPrice");
                                        }
                                        else
                                        {
                                            //prices

                                            //calculate for the maximum quantity (in case if we have tier prices)
                                            decimal minPossiblePrice = priceCalculationService.GetFinalPrice(product,
                                                workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);

                                            decimal taxRate;
                                            decimal oldPriceBase = taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                                            decimal finalPriceBase = taxService.GetProductPrice(product, minPossiblePrice, out taxRate);

                                            decimal oldPrice = currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, workContext.WorkingCurrency);
                                            decimal finalPrice = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                            //do we have tier prices configured?
                                            var tierPrices = new List<TierPrice>();
                                            if (product.HasTierPrices)
                                            {
                                                tierPrices.AddRange(product.TierPrices
                                                    .OrderBy(tp => tp.Quantity)
                                                    .ToList()
                                                    .FilterByStore(storeContext.CurrentStore.Id)
                                                    .FilterForCustomer(workContext.CurrentCustomer)
                                                    .RemoveDuplicatedQuantities());
                                            }
                                            //When there is just one tier (with  qty 1),
                                            //there are no actual savings in the list.
                                            bool displayFromMessage = tierPrices.Count > 0 &&
                                                !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1);
                                            if (displayFromMessage)
                                            {
                                                priceModel.OldPrice = null;
                                                priceModel.Price = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));
                                            }
                                            else
                                            {
                                                if (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero)
                                                {
                                                    priceModel.OldPrice = priceFormatter.FormatPrice(oldPrice);
                                                    priceModel.Price = priceFormatter.FormatPrice(finalPrice);
                                                }
                                                else
                                                {
                                                    priceModel.OldPrice = null;
                                                    priceModel.Price = priceFormatter.FormatPrice(finalPrice);
                                                }
                                            }
                                            if (product.IsRental)
                                            {
                                                //rental product
                                                priceModel.OldPrice = priceFormatter.FormatRentalProductPeriod(product, priceModel.OldPrice);
                                                priceModel.Price = priceFormatter.FormatRentalProductPeriod(product, priceModel.Price);
                                            }

                                            //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
                                            priceModel.DisplayTaxShippingInfo = catalogSettings.DisplayTaxShippingInfoProductBoxes
                                                && product.IsShipEnabled &&
                                                !product.IsFreeShipping;
                                        }
                                    }
                                }
                                else
                                {
                                    //hide prices
                                    priceModel.OldPrice = null;
                                    priceModel.Price = null;
                                }

                                #endregion
                            }
                            break;
                    }

                    model.ProductPrice = priceModel;

                    #endregion
                }

                //picture
                if (preparePictureModel)
                {
                    #region Prepare product picture

                    //If a size has been set in the view, we use it in priority
                    int pictureSize = productThumbPictureSize.HasValue ? productThumbPictureSize.Value : mediaSettings.ProductThumbPictureSize;
                    //prepare picture model
                    var defaultProductPictureCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_DEFAULTPICTURE_MODEL_KEY, product.Id, pictureSize, true, workContext.WorkingLanguage.Id, webHelper.IsCurrentConnectionSecured(), storeContext.CurrentStore.Id);
                    model.DefaultPictureModel = cacheManager.Get(defaultProductPictureCacheKey, () =>
                    {
                        var picture = pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault();
                        var pictureModel = new PictureModel
                        {
                            ImageUrl = pictureService.GetPictureUrl(picture, pictureSize),
                            FullSizeImageUrl = pictureService.GetPictureUrl(picture)
                        };
                        //"title" attribute
                        pictureModel.Title = (picture != null && !string.IsNullOrEmpty(picture.TitleAttribute)) ?
                            picture.TitleAttribute :
                            string.Format(localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name);
                        //"alt" attribute
                        pictureModel.AlternateText = (picture != null && !string.IsNullOrEmpty(picture.AltAttribute)) ?
                            picture.AltAttribute :
                            string.Format(localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name);

                        return pictureModel;
                    });

                    #endregion
                }

                //specs
                if (prepareSpecificationAttributes)
                {
                    model.SpecificationAttributeModels = PrepareProductSpecificationModel(controller, workContext,
                         specificationAttributeService, cacheManager, product);
                }

                //reviews
                model.ReviewOverviewModel = new ProductReviewOverviewModel
                {
                    ProductId = product.Id,
                    RatingSum = product.ApprovedRatingSum,
                    TotalReviews = product.ApprovedTotalReviews,
                    AllowCustomerReviews = product.AllowCustomerReviews
                };

                models.Add(model);
            }
            return models;
        }
Example #2
0
        public static IEnumerable <ProductOverviewModel> PrepareProductOverviewModels(this Controller controller,
                                                                                      IWorkContext workContext,
                                                                                      IStoreContext storeContext,
                                                                                      ICategoryService categoryService,
                                                                                      IProductService productService,
                                                                                      ISpecificationAttributeService specificationAttributeService,
                                                                                      IPriceCalculationService priceCalculationService,
                                                                                      IPriceFormatter priceFormatter,
                                                                                      IPermissionService permissionService,
                                                                                      ILocalizationService localizationService,
                                                                                      ITaxService taxService,
                                                                                      ICurrencyService currencyService,
                                                                                      IPictureService pictureService,
                                                                                      IWebHelper webHelper,
                                                                                      ICacheManager cacheManager,
                                                                                      CatalogSettings catalogSettings,
                                                                                      MediaSettings mediaSettings,
                                                                                      IEnumerable <Product> products,
                                                                                      bool preparePriceModel                 = true, bool preparePictureModel = true,
                                                                                      int?productThumbPictureSize            = null, bool prepareSpecificationAttributes = false,
                                                                                      bool forceRedirectionAfterAddingToCart = false)
        {
            if (products == null)
            {
                throw new ArgumentNullException("products");
            }

            var models = new List <ProductOverviewModel>();

            foreach (var product in products)
            {
                var model = new ProductOverviewModel
                {
                    Id               = product.Id,
                    Name             = product.GetLocalized(x => x.Name),
                    ShortDescription = product.GetLocalized(x => x.ShortDescription),
                    FullDescription  = product.GetLocalized(x => x.FullDescription),
                    SeName           = product.GetSeName(),
                    ProductType      = product.ProductType,
                    MarkAsNew        = product.MarkAsNew &&
                                       (!product.MarkAsNewStartDateTimeUtc.HasValue || product.MarkAsNewStartDateTimeUtc.Value < DateTime.UtcNow) &&
                                       (!product.MarkAsNewEndDateTimeUtc.HasValue || product.MarkAsNewEndDateTimeUtc.Value > DateTime.UtcNow)
                };
                //price
                if (preparePriceModel)
                {
                    #region Prepare product price

                    var priceModel = new ProductOverviewModel.ProductPriceModel
                    {
                        ForceRedirectionAfterAddingToCart = forceRedirectionAfterAddingToCart
                    };

                    switch (product.ProductType)
                    {
                    case ProductType.GroupedProduct:
                    {
                        #region Grouped product

                        var associatedProducts = productService.GetAssociatedProducts(product.Id, storeContext.CurrentStore.Id);

                        //add to cart button (ignore "DisableBuyButton" property for grouped products)
                        priceModel.DisableBuyButton = !permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                                      !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //add to wishlist button (ignore "DisableWishlistButton" property for grouped products)
                        priceModel.DisableWishlistButton = !permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                                           !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //compare products
                        priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                        switch (associatedProducts.Count)
                        {
                        case 0:
                        {
                            //no associated products
                        }
                        break;

                        default:
                        {
                            //we have at least one associated product
                            //compare products
                            priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                            //priceModel.AvailableForPreOrder = false;

                            if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                            {
                                //find a minimum possible price
                                decimal?minPossiblePrice = null;
                                Product minPriceProduct  = null;
                                foreach (var associatedProduct in associatedProducts)
                                {
                                    //calculate for the maximum quantity (in case if we have tier prices)
                                    var tmpPrice = priceCalculationService.GetFinalPrice(associatedProduct,
                                                                                         workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);
                                    if (!minPossiblePrice.HasValue || tmpPrice < minPossiblePrice.Value)
                                    {
                                        minPriceProduct  = associatedProduct;
                                        minPossiblePrice = tmpPrice;
                                    }
                                }
                                if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice)
                                {
                                    if (minPriceProduct.CallForPrice)
                                    {
                                        priceModel.OldPrice = null;
                                        priceModel.Price    = localizationService.GetResource("Products.CallForPrice");
                                    }
                                    else if (minPossiblePrice.HasValue)
                                    {
                                        //calculate prices
                                        decimal taxRate;
                                        decimal finalPriceBase = taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate);
                                        decimal finalPrice     = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                        priceModel.OldPrice   = null;
                                        priceModel.Price      = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));
                                        priceModel.PriceValue = finalPrice;
                                    }
                                    else
                                    {
                                        //Actually it's not possible (we presume that minimalPrice always has a value)
                                        //We never should get here
                                        Debug.WriteLine("Cannot calculate minPrice for product #{0}", product.Id);
                                    }
                                }
                            }
                            else
                            {
                                //hide prices
                                priceModel.OldPrice = null;
                                priceModel.Price    = null;
                            }
                        }
                        break;
                        }

                        #endregion
                    }
                    break;

                    case ProductType.SimpleProduct:
                    default:
                    {
                        #region Simple product

                        //add to cart button
                        priceModel.DisableBuyButton = product.DisableBuyButton ||
                                                      !permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                                      !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //add to wishlist button
                        priceModel.DisableWishlistButton = product.DisableWishlistButton ||
                                                           !permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                                           !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);
                        //compare products
                        priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;

                        //rental
                        priceModel.IsRental = product.IsRental;

                        //pre-order
                        if (product.AvailableForPreOrder)
                        {
                            priceModel.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                                              product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                            priceModel.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
                        }

                        //prices
                        if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            if (!product.CustomerEntersPrice)
                            {
                                if (product.CallForPrice)
                                {
                                    //call for price
                                    priceModel.OldPrice = null;
                                    priceModel.Price    = localizationService.GetResource("Products.CallForPrice");
                                }
                                else
                                {
                                    //prices

                                    //calculate for the maximum quantity (in case if we have tier prices)
                                    decimal minPossiblePrice = priceCalculationService.GetFinalPrice(product,
                                                                                                     workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);

                                    decimal taxRate;
                                    decimal oldPriceBase   = taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                                    decimal finalPriceBase = taxService.GetProductPrice(product, minPossiblePrice, out taxRate);

                                    decimal oldPrice   = currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, workContext.WorkingCurrency);
                                    decimal finalPrice = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                    //do we have tier prices configured?
                                    var tierPrices = new List <TierPrice>();
                                    if (product.HasTierPrices)
                                    {
                                        tierPrices.AddRange(product.TierPrices
                                                            .OrderBy(tp => tp.Quantity)
                                                            .ToList()
                                                            .FilterByStore(storeContext.CurrentStore.Id)
                                                            .FilterForCustomer(workContext.CurrentCustomer)
                                                            .RemoveDuplicatedQuantities());
                                    }
                                    //When there is just one tier (with  qty 1),
                                    //there are no actual savings in the list.
                                    bool displayFromMessage = tierPrices.Count > 0 &&
                                                              !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1);
                                    if (displayFromMessage)
                                    {
                                        priceModel.OldPrice   = null;
                                        priceModel.Price      = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));
                                        priceModel.PriceValue = finalPrice;
                                    }
                                    else
                                    {
                                        if (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero)
                                        {
                                            priceModel.OldPrice   = priceFormatter.FormatPrice(oldPrice);
                                            priceModel.Price      = priceFormatter.FormatPrice(finalPrice);
                                            priceModel.PriceValue = finalPrice;
                                        }
                                        else
                                        {
                                            priceModel.OldPrice   = null;
                                            priceModel.Price      = priceFormatter.FormatPrice(finalPrice);
                                            priceModel.PriceValue = finalPrice;
                                        }
                                    }
                                    if (product.IsRental)
                                    {
                                        //rental product
                                        priceModel.OldPrice = priceFormatter.FormatRentalProductPeriod(product, priceModel.OldPrice);
                                        priceModel.Price    = priceFormatter.FormatRentalProductPeriod(product, priceModel.Price);
                                    }


                                    //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
                                    priceModel.DisplayTaxShippingInfo = catalogSettings.DisplayTaxShippingInfoProductBoxes &&
                                                                        product.IsShipEnabled &&
                                                                        !product.IsFreeShipping;
                                }
                            }
                        }
                        else
                        {
                            //hide prices
                            priceModel.OldPrice = null;
                            priceModel.Price    = null;
                        }

                        #endregion
                    }
                    break;
                    }

                    model.ProductPrice = priceModel;

                    #endregion
                }

                //picture
                if (preparePictureModel)
                {
                    #region Prepare product picture

                    //If a size has been set in the view, we use it in priority
                    int pictureSize = productThumbPictureSize.HasValue ? productThumbPictureSize.Value : mediaSettings.ProductThumbPictureSize;
                    //prepare picture model
                    var defaultProductPictureCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_DEFAULTPICTURE_MODEL_KEY, product.Id, pictureSize, true, workContext.WorkingLanguage.Id, webHelper.IsCurrentConnectionSecured(), storeContext.CurrentStore.Id);
                    model.DefaultPictureModel = cacheManager.Get(defaultProductPictureCacheKey, () =>
                    {
                        var picture      = pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault();
                        var pictureModel = new PictureModel
                        {
                            ImageUrl         = pictureService.GetPictureUrl(picture, pictureSize),
                            FullSizeImageUrl = pictureService.GetPictureUrl(picture)
                        };
                        //"title" attribute
                        pictureModel.Title = (picture != null && !string.IsNullOrEmpty(picture.TitleAttribute)) ?
                                             picture.TitleAttribute :
                                             string.Format(localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name);
                        //"alt" attribute
                        pictureModel.AlternateText = (picture != null && !string.IsNullOrEmpty(picture.AltAttribute)) ?
                                                     picture.AltAttribute :
                                                     string.Format(localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name);

                        return(pictureModel);
                    });

                    #endregion
                }

                //specs
                if (prepareSpecificationAttributes)
                {
                    model.SpecificationAttributeModels = PrepareProductSpecificationModel(controller, workContext,
                                                                                          specificationAttributeService, cacheManager, product);
                }

                //reviews
                model.ReviewOverviewModel = controller.PrepareProductReviewOverviewModel(storeContext, catalogSettings, cacheManager, product);

                models.Add(model);
            }
            return(models);
        }
        protected IEnumerable <ProductOverviewModel> PrepareProductOverviewModels(IEnumerable <Product> products,
                                                                                  bool preparePriceModel                 = true, bool preparePictureModel = true,
                                                                                  int?productThumbPictureSize            = null, bool prepareSpecificationAttributes = false,
                                                                                  bool forceRedirectionAfterAddingToCart = false)
        {
            if (products == null)
            {
                throw new ArgumentNullException("products");
            }

            var models = new List <ProductOverviewModel>();

            foreach (var product in products)
            {
                var model = new ProductOverviewModel
                {
                    Id               = product.Id,
                    Name             = product.GetLocalized(x => x.Name),
                    ShortDescription = product.GetLocalized(x => x.ShortDescription),
                    FullDescription  = product.GetLocalized(x => x.FullDescription),
                    SeName           = product.GetSeName(),
                };
                //price
                if (preparePriceModel)
                {
                    #region Prepare product price

                    var priceModel = new ProductOverviewModel.ProductPriceModel();

                    switch (product.ProductType)
                    {
                    case ProductType.GroupedProduct:
                    {
                        #region Grouped product

                        var associatedProducts = _productService.GetAssociatedProducts(product.Id, _storeContext.CurrentStore.Id);

                        switch (associatedProducts.Count)
                        {
                        case 0:
                        {
                            //no associated products
                            priceModel.OldPrice              = null;
                            priceModel.Price                 = null;
                            priceModel.DisableBuyButton      = true;
                            priceModel.DisableWishlistButton = true;
                            priceModel.AvailableForPreOrder  = false;
                        }
                        break;

                        default:
                        {
                            //we have at least one associated product
                            priceModel.DisableBuyButton      = true;
                            priceModel.DisableWishlistButton = true;
                            priceModel.AvailableForPreOrder  = false;

                            if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                            {
                                //find a minimum possible price
                                decimal?minPossiblePrice = null;
                                Product minPriceProduct  = null;
                                foreach (var associatedProduct in associatedProducts)
                                {
                                    //calculate for the maximum quantity (in case if we have tier prices)
                                    var tmpPrice = _priceCalculationService.GetFinalPrice(associatedProduct,
                                                                                          _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);
                                    if (!minPossiblePrice.HasValue || tmpPrice < minPossiblePrice.Value)
                                    {
                                        minPriceProduct  = associatedProduct;
                                        minPossiblePrice = tmpPrice;
                                    }
                                }
                                if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice)
                                {
                                    if (minPriceProduct.CallForPrice)
                                    {
                                        priceModel.OldPrice = null;
                                        priceModel.Price    = _localizationService.GetResource("Products.CallForPrice");
                                    }
                                    else if (minPossiblePrice.HasValue)
                                    {
                                        //calculate prices
                                        decimal taxRate;
                                        decimal finalPriceBase = _taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate);
                                        decimal finalPrice     = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _workContext.WorkingCurrency);

                                        priceModel.OldPrice = null;
                                        priceModel.Price    = String.Format(_localizationService.GetResource("Products.PriceRangeFrom"), _priceFormatter.FormatPrice(finalPrice));
                                    }
                                    else
                                    {
                                        //Actually it's not possible (we presume that minimalPrice always has a value)
                                        //We never should get here
                                        Debug.WriteLine("Cannot calculate minPrice for product #{0}", product.Id);
                                    }
                                }
                            }
                            else
                            {
                                //hide prices
                                priceModel.OldPrice = null;
                                priceModel.Price    = null;
                            }
                        }
                        break;
                        }

                        #endregion
                    }
                    break;

                    default:
                    {
                        #region Simple product

                        //add to cart button
                        priceModel.DisableBuyButton = product.DisableBuyButton ||
                                                      !_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                                      !_permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //add to wishlist button
                        priceModel.DisableWishlistButton = product.DisableWishlistButton ||
                                                           !_permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                                           !_permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //rental
                        priceModel.IsRental = product.IsRental;

                        //pre-order
                        if (product.AvailableForPreOrder)
                        {
                            priceModel.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                                              product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                            priceModel.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
                        }

                        //prices
                        if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            if (!product.CustomerEntersPrice)
                            {
                                if (product.CallForPrice)
                                {
                                    //call for price
                                    priceModel.OldPrice = null;
                                    priceModel.Price    = _localizationService.GetResource("Products.CallForPrice");
                                }
                                else
                                {
                                    //prices

                                    //calculate for the maximum quantity (in case if we have tier prices)
                                    decimal minPossiblePrice = _priceCalculationService.GetFinalPrice(product,
                                                                                                      _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);

                                    decimal taxRate;
                                    decimal oldPriceBase   = _taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                                    decimal finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out taxRate);

                                    decimal oldPrice   = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency);
                                    decimal finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _workContext.WorkingCurrency);

                                    //do we have tier prices configured?
                                    var tierPrices = new List <TierPrice>();
                                    if (product.HasTierPrices)
                                    {
                                        tierPrices.AddRange(product.TierPrices
                                                            .OrderBy(tp => tp.Quantity)
                                                            .ToList()
                                                            .FilterByStore(_storeContext.CurrentStore.Id)
                                                            .FilterForCustomer(_workContext.CurrentCustomer)
                                                            .RemoveDuplicatedQuantities());
                                    }
                                    //When there is just one tier (with  qty 1),
                                    //there are no actual savings in the list.
                                    bool displayFromMessage = tierPrices.Count > 0 &&
                                                              !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1);
                                    if (displayFromMessage)
                                    {
                                        priceModel.OldPrice = null;
                                        priceModel.Price    = String.Format(_localizationService.GetResource("Products.PriceRangeFrom"), _priceFormatter.FormatPrice(finalPrice));
                                    }
                                    else
                                    {
                                        if (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero)
                                        {
                                            priceModel.OldPrice = _priceFormatter.FormatPrice(oldPrice);
                                            priceModel.Price    = _priceFormatter.FormatPrice(finalPrice);
                                        }
                                        else
                                        {
                                            priceModel.OldPrice = null;
                                            priceModel.Price    = _priceFormatter.FormatPrice(finalPrice);
                                        }
                                    }
                                    if (product.IsRental)
                                    {
                                        //rental product
                                        priceModel.OldPrice = _priceFormatter.FormatRentalProductPeriod(product, priceModel.OldPrice);
                                        priceModel.Price    = _priceFormatter.FormatRentalProductPeriod(product, priceModel.Price);
                                    }
                                }
                            }
                        }
                        else
                        {
                            //hide prices
                            priceModel.OldPrice = null;
                            priceModel.Price    = null;
                        }

                        #endregion
                    }
                    break;
                    }

                    model.ProductPrice = priceModel;

                    #endregion
                }

                //picture
                if (preparePictureModel)
                {
                    #region Prepare product picture

                    //If a size has been set in the view, we use it in priority
                    int pictureSize = productThumbPictureSize.HasValue ? productThumbPictureSize.Value : 125;
                    //prepare picture model
                    var picture = _pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault();
                    model.DefaultPictureModel = new PictureModel
                    {
                        ImageUrl         = _pictureService.GetPictureUrl(picture, pictureSize),
                        FullSizeImageUrl = _pictureService.GetPictureUrl(picture)
                    };
                    //"title" attribute
                    model.DefaultPictureModel.Title = (picture != null && !string.IsNullOrEmpty(picture.TitleAttribute)) ?
                                                      picture.TitleAttribute :
                                                      string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name);
                    //"alt" attribute
                    model.DefaultPictureModel.AlternateText = (picture != null && !string.IsNullOrEmpty(picture.AltAttribute)) ?
                                                              picture.AltAttribute :
                                                              string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name);

                    #endregion
                }

                models.Add(model);
            }
            return(models);
        }
        /// <summary>
        /// Print product collection to PDF
        /// </summary>
        /// <param name="stream">Stream</param>
        /// <param name="products">Products</param>
        public virtual void PrintProductsToPdf(Stream stream, IList <Product> products)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (products == null)
            {
                throw new ArgumentNullException("products");
            }

            var lang = _workContext.WorkingLanguage;

            var pageSize = PageSize.A4;

            if (_pdfSettings.LetterPageSizeEnabled)
            {
                pageSize = PageSize.LETTER;
            }

            var doc = new Document(pageSize);

            PdfWriter.GetInstance(doc, stream);
            doc.Open();

            //fonts
            var titleFont = GetFont();

            titleFont.SetStyle(Font.BOLD);
            titleFont.Color = BaseColor.BLACK;
            var font = GetFont();

            int productNumber = 1;
            int prodCount     = products.Count;

            foreach (var product in products)
            {
                string productName        = product.GetLocalized(x => x.Name, lang.Id);
                string productDescription = product.GetLocalized(x => x.FullDescription, lang.Id);

                var productTable = new PdfPTable(1);
                productTable.WidthPercentage    = 100f;
                productTable.DefaultCell.Border = Rectangle.NO_BORDER;
                if (lang.Rtl)
                {
                    productTable.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                }

                productTable.AddCell(new Paragraph(String.Format("{0}. {1}", productNumber, productName), titleFont));
                productTable.AddCell(new Paragraph(" "));
                productTable.AddCell(new Paragraph(HtmlHelper.StripTags(HtmlHelper.ConvertHtmlToPlainText(productDescription, decode: true)), font));
                productTable.AddCell(new Paragraph(" "));

                if (product.ProductType == ProductType.SimpleProduct)
                {
                    //simple product
                    //render its properties such as price, weight, etc
                    var priceStr = string.Format("{0} {1}", product.Price.ToString("0.00"), _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode);
                    if (product.IsRental)
                    {
                        priceStr = _priceFormatter.FormatRentalProductPeriod(product, priceStr);
                    }
                    productTable.AddCell(new Paragraph(String.Format("{0}: {1}", _localizationService.GetResource("PDFProductCatalog.Price", lang.Id), priceStr), font));
                    productTable.AddCell(new Paragraph(String.Format("{0}: {1}", _localizationService.GetResource("PDFProductCatalog.SKU", lang.Id), product.Sku), font));

                    if (product.IsShipEnabled && product.Weight > Decimal.Zero)
                    {
                        productTable.AddCell(new Paragraph(String.Format("{0}: {1} {2}", _localizationService.GetResource("PDFProductCatalog.Weight", lang.Id), product.Weight.ToString("0.00"), _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name), font));
                    }

                    if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock)
                    {
                        productTable.AddCell(new Paragraph(String.Format("{0}: {1}", _localizationService.GetResource("PDFProductCatalog.StockQuantity", lang.Id), product.GetTotalStockQuantity()), font));
                    }

                    productTable.AddCell(new Paragraph(" "));
                }
                var pictures = _pictureService.GetPicturesByProductId(product.Id);
                if (pictures.Count > 0)
                {
                    var table = new PdfPTable(2);
                    table.WidthPercentage = 100f;
                    if (lang.Rtl)
                    {
                        table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                    }

                    foreach (var pic in pictures)
                    {
                        var picBinary = _pictureService.LoadPictureBinary(pic);
                        if (picBinary != null && picBinary.Length > 0)
                        {
                            var pictureLocalPath = _pictureService.GetThumbLocalPath(pic, 200, false);
                            var cell             = new PdfPCell(Image.GetInstance(pictureLocalPath));
                            cell.HorizontalAlignment = Element.ALIGN_LEFT;
                            cell.Border = Rectangle.NO_BORDER;
                            table.AddCell(cell);
                        }
                    }

                    if (pictures.Count % 2 > 0)
                    {
                        var cell = new PdfPCell(new Phrase(" "));
                        cell.Border = Rectangle.NO_BORDER;
                        table.AddCell(cell);
                    }

                    productTable.AddCell(table);
                    productTable.AddCell(new Paragraph(" "));
                }


                if (product.ProductType == ProductType.GroupedProduct)
                {
                    //grouped product. render its associated products
                    int pvNum = 1;
                    foreach (var associatedProduct in _productService.GetAssociatedProducts(product.Id, showHidden: true))
                    {
                        productTable.AddCell(new Paragraph(String.Format("{0}-{1}. {2}", productNumber, pvNum, associatedProduct.GetLocalized(x => x.Name, lang.Id)), font));
                        productTable.AddCell(new Paragraph(" "));

                        //uncomment to render associated product description
                        //string apDescription = associatedProduct.GetLocalized(x => x.ShortDescription, lang.Id);
                        //if (!String.IsNullOrEmpty(apDescription))
                        //{
                        //    productTable.AddCell(new Paragraph(HtmlHelper.StripTags(HtmlHelper.ConvertHtmlToPlainText(apDescription)), font));
                        //    productTable.AddCell(new Paragraph(" "));
                        //}

                        //uncomment to render associated product picture
                        //var apPicture = _pictureService.GetPicturesByProductId(associatedProduct.Id).FirstOrDefault();
                        //if (apPicture != null)
                        //{
                        //    var picBinary = _pictureService.LoadPictureBinary(apPicture);
                        //    if (picBinary != null && picBinary.Length > 0)
                        //    {
                        //        var pictureLocalPath = _pictureService.GetThumbLocalPath(apPicture, 200, false);
                        //        productTable.AddCell(Image.GetInstance(pictureLocalPath));
                        //    }
                        //}

                        productTable.AddCell(new Paragraph(String.Format("{0}: {1} {2}", _localizationService.GetResource("PDFProductCatalog.Price", lang.Id), associatedProduct.Price.ToString("0.00"), _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode), font));
                        productTable.AddCell(new Paragraph(String.Format("{0}: {1}", _localizationService.GetResource("PDFProductCatalog.SKU", lang.Id), associatedProduct.Sku), font));

                        if (associatedProduct.IsShipEnabled && associatedProduct.Weight > Decimal.Zero)
                        {
                            productTable.AddCell(new Paragraph(String.Format("{0}: {1} {2}", _localizationService.GetResource("PDFProductCatalog.Weight", lang.Id), associatedProduct.Weight.ToString("0.00"), _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name), font));
                        }

                        if (associatedProduct.ManageInventoryMethod == ManageInventoryMethod.ManageStock)
                        {
                            productTable.AddCell(new Paragraph(String.Format("{0}: {1}", _localizationService.GetResource("PDFProductCatalog.StockQuantity", lang.Id), associatedProduct.GetTotalStockQuantity()), font));
                        }

                        productTable.AddCell(new Paragraph(" "));

                        pvNum++;
                    }
                }

                doc.Add(productTable);

                productNumber++;

                if (productNumber <= prodCount)
                {
                    doc.NewPage();
                }
            }

            doc.Close();
        }
Example #5
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);
        }