protected virtual ProductDetailsModel PrepareProductDetailsPageModel(Product product, ShoppingCartItem updatecartitem = null, bool isAssociatedProduct = false) { if (product == null) throw new ArgumentNullException("product"); #region Standard properties var model = new ProductDetailsModel { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), ShowSku = _catalogSettings.ShowProductSku, Sku = product.Sku, ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber, FreeShippingNotificationEnabled = _catalogSettings.ShowFreeShippingNotification, ManufacturerPartNumber = product.ManufacturerPartNumber, ShowGtin = _catalogSettings.ShowGtin, Gtin = product.Gtin, StockAvailability = product.FormatStockMessage("", _localizationService, _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 = _shippingService.GetDeliveryDateById(product.DeliveryDateId); if (deliveryDate != null) { model.DeliveryDate = deliveryDate.GetLocalized(dd => dd.Name); } } //email a friend model.EmailAFriendEnabled = _catalogSettings.EmailAFriendEnabled; //compare products model.CompareProductsEnabled = _catalogSettings.CompareProductsEnabled; #endregion #region Vendor details //vendor if (_vendorSettings.ShowVendorOnProductDetailsPage) { var vendor = _vendorService.GetVendorById(product.VendorId); if (vendor != null && !vendor.Deleted && vendor.Active) { model.ShowVendor = true; model.VendorModel = new VendorBriefInfoModel { 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 ProductTagModel { 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; }); #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 = _pictureService.GetPicturesByProductId(product.Id); var defaultPicture = pictures.FirstOrDefault(); var defaultPictureModel = new PictureModel { ImageUrl = _pictureService.GetPictureUrl(defaultPicture, defaultPictureSize, !isAssociatedProduct), FullSizeImageUrl = _pictureService.GetPictureUrl(defaultPicture, 0, !isAssociatedProduct), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name), }; //"title" attribute defaultPictureModel.Title = (defaultPicture != null && !string.IsNullOrEmpty(defaultPicture.TitleAttribute)) ? defaultPicture.TitleAttribute : string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name); //"alt" attribute defaultPictureModel.AlternateText = (defaultPicture != null && !string.IsNullOrEmpty(defaultPicture.AltAttribute)) ? defaultPicture.AltAttribute : string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name); //all pictures var pictureModels = new List<PictureModel>(); foreach (var picture in pictures) { var pictureModel = new PictureModel { ImageUrl = _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage), FullSizeImageUrl = _pictureService.GetPictureUrl(picture), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name), }; //"title" attribute pictureModel.Title = !string.IsNullOrEmpty(picture.TitleAttribute) ? picture.TitleAttribute : string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name); //"alt" attribute pictureModel.AlternateText = !string.IsNullOrEmpty(picture.AltAttribute) ? picture.AltAttribute : string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name); pictureModels.Add(pictureModel); } return new { DefaultPictureModel = defaultPictureModel, PictureModels = pictureModels }; }); model.DefaultPictureModel = cachedPictures.DefaultPictureModel; model.PictureModels = cachedPictures.PictureModels; #endregion #region Product price //for GoupDealProduct Products //model.ProductPrice.SpecialPrice = _priceFormatter.FormatPrice(System.Convert.ToDecimal(product.SpecialPrice)); //model.ProductPrice.SpecialPriceValue = product.SpecialPrice; model.AvailableEndDateTimeUtc = Convert.ToDateTime(product.AvailableEndDateTimeUtc); model.AvailableStartDateTimeUtc = Convert.ToDateTime(product.AvailableStartDateTimeUtc); // End Here 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 = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); decimal finalPriceWithoutDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, includeDiscounts: false), out taxRate); decimal finalPriceWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, includeDiscounts: true), out taxRate); //for group deal if (product.SpecialPrice != null) { model.ProductPrice.SpecialPriceValue = _currencyService.ConvertFromPrimaryStoreCurrency(Convert.ToDecimal(product.SpecialPrice), _workContext.WorkingCurrency); model.ProductPrice.SpecialPrice = _priceFormatter.FormatPrice(System.Convert.ToDecimal(model.ProductPrice.SpecialPriceValue)); model.ProductPrice.FinalPriceWithoutSpecialPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.Price, _workContext.WorkingCurrency); } decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency); decimal finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, _workContext.WorkingCurrency); decimal finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, _workContext.WorkingCurrency); if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero) model.ProductPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice); model.ProductPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount); if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase) model.ProductPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount); model.ProductPrice.PriceValue = finalPriceWithDiscount; model.ProductPrice.PriceWithDiscountValue = 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 = _workContext.WorkingCurrency.CurrencyCode; //rental if (product.IsRental) { model.ProductPrice.IsRental = true; var priceStr = _priceFormatter.FormatPrice(finalPriceWithDiscount); 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 }); } //minimum quantity notification if (product.OrderMinimumQuantity > 1) { model.AddToCart.MinimumQuantityNotification = string.Format(_localizationService.GetResource("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 = _currencyService.ConvertFromPrimaryStoreCurrency(product.MinimumCustomerEnteredPrice, _workContext.WorkingCurrency); decimal maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MaximumCustomerEnteredPrice, _workContext.WorkingCurrency); model.AddToCart.CustomerEnteredPrice = updatecartitem != null ? updatecartitem.CustomerEnteredPrice : minimumCustomerEnteredPrice; model.AddToCart.CustomerEnteredPriceRange = string.Format(_localizationService.GetResource("Products.EnterProductPrice.Range"), _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, false, false), _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, false, false)); } #endregion #region Gift card model.GiftCard.IsGiftCard = product.IsGiftCard; if (model.GiftCard.IsGiftCard) { model.GiftCard.GiftCardType = product.GiftCardType; if (updatecartitem == null) { model.GiftCard.SenderName = _workContext.CurrentCustomer.GetFullName(); model.GiftCard.SenderEmail = _workContext.CurrentCustomer.Email; } 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 = _productAttributeService.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 ProductDetailsModel.ProductAttributeModel { Id = attribute.Id, ProductId = product.Id, ProductAttributeId = attribute.ProductAttributeId, Name = attribute.ProductAttribute.GetLocalized(x => x.Name), Description = attribute.ProductAttribute.GetLocalized(x => x.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 = _productAttributeService.GetProductAttributeValues(attribute.Id); foreach (var attributeValue in attributeValues) { var valueModel = new ProductDetailsModel.ProductAttributeValueModel { Id = attributeValue.Id, Name = attributeValue.GetLocalized(x => x.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 = _priceCalculationService.GetProductAttributeValuePriceAdjustment(attributeValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) valueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, false, false); else if (priceAdjustmentBase < decimal.Zero) valueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, false, false); 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 = _pictureService.GetPictureById(attributeValue.PictureId); if (valuePicture != null) { return new PictureModel { FullSizeImageUrl = _pictureService.GetPictureUrl(valuePicture), ImageUrl = _pictureService.GetPictureUrl(valuePicture, defaultPictureSize) }; } return new PictureModel(); }); } } } //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 = _downloadService.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(_workContext, _specificationAttributeService, _cacheManager, product); } #endregion #region Product review overview model.ProductReviewOverview = new ProductReviewOverviewModel { 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(_workContext.CurrentCustomer) .RemoveDuplicatedQuantities() .Select(tierPrice => { var m = new ProductDetailsModel.TierPriceModel { Quantity = tierPrice.Quantity, }; decimal taxRate; decimal priceBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, decimal.Zero, _catalogSettings.DisplayTierPricesWithDiscounts, tierPrice.Quantity), out taxRate); decimal price = _currencyService.ConvertFromPrimaryStoreCurrency(priceBase, _workContext.WorkingCurrency); m.Price = _priceFormatter.FormatPrice(price, false, false); 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, () => _manufacturerService.GetProductManufacturersByProductId(product.Id) .Select(x => x.Manufacturer.ToModel()) .ToList() ); } #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 = _productService.GetAssociatedProducts(product.Id, _storeContext.CurrentStore.Id); foreach (var associatedProduct in associatedProducts) model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, null, true)); } } #endregion return model; }
protected virtual void PrepareProductReviewsModel(ProductReviewsModel model, Product product) { if (product == null) throw new ArgumentNullException("product"); if (model == null) throw new ArgumentNullException("model"); model.ProductId = product.Id; model.ProductName = product.GetLocalized(x => x.Name); model.ProductSeName = product.GetSeName(); var productReviews = product.ProductReviews.Where(pr => pr.IsApproved).OrderBy(pr => pr.CreatedOnUtc); foreach (var pr in productReviews) { var customer = pr.Customer; model.Items.Add(new ProductReviewModel { Id = pr.Id, CustomerId = pr.CustomerId, CustomerName = customer.FormatUserName(), AllowViewingProfiles = _customerSettings.AllowViewingProfiles && customer != null && !customer.IsGuest(), Title = pr.Title, ReviewText = pr.ReviewText, Rating = pr.Rating, Helpfulness = new ProductReviewHelpfulnessModel { ProductReviewId = pr.Id, HelpfulYesTotal = pr.HelpfulYesTotal, HelpfulNoTotal = pr.HelpfulNoTotal, }, WrittenOnStr = _dateTimeHelper.ConvertToUserTime(pr.CreatedOnUtc, DateTimeKind.Utc).ToString("g"), }); } model.AddProductReview.CanCurrentCustomerLeaveReview = _catalogSettings.AllowAnonymousUsersToReviewProduct || !_workContext.CurrentCustomer.IsGuest(); model.AddProductReview.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnProductReviewPage; }
public virtual void AddProductTokens(IList<Token> tokens, Product product) { tokens.Add(new Token("Product.Name", product.Name)); tokens.Add(new Token("Product.ShortDescription", product.ShortDescription, true)); //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) var productUrl = string.Format("{0}p/{1}/{2}", _webHelper.GetStoreLocation(false), product.Id, product.GetSeName()); tokens.Add(new Token("Product.ProductURLForCustomer", productUrl, true)); }
public virtual void AddProductTokens(IList<Token> tokens, Product product, int languageId) { tokens.Add(new Token("Product.ID", product.Id.ToString())); tokens.Add(new Token("Product.Name", product.GetLocalized(x => x.Name, languageId))); tokens.Add(new Token("Product.ShortDescription", product.GetLocalized(x => x.ShortDescription, languageId), true)); tokens.Add(new Token("Product.SKU", product.Sku)); tokens.Add(new Token("Product.StockQuantity", product.GetTotalStockQuantity().ToString())); //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) var productUrl = string.Format("{0}{1}", GetStoreUrl(), product.GetSeName()); tokens.Add(new Token("Product.ProductURLForCustomer", productUrl, true)); //event notification _eventPublisher.EntityTokensAdded(product, tokens); }
protected ProductDetailsModel PrepareProductDetailsPageModel(Product product) { if (product == null) throw new ArgumentNullException("product"); var model = new ProductDetailsModel() { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), }; //template var templateCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_TEMPLATE_MODEL_KEY, product.ProductTemplateId); model.ProductTemplateViewPath = _cacheManager.Get(templateCacheKey, () => { var template = _productTemplateService.GetProductTemplateById(product.ProductTemplateId); if (template == null) template = _productTemplateService.GetAllProductTemplates().FirstOrDefault(); return template.ViewPath; }); //pictures model.DefaultPictureZoomEnabled = _mediaSettings.DefaultPictureZoomEnabled; var pictures = _pictureService.GetPicturesByProductId(product.Id); if (pictures.Count > 0) { //default picture model.DefaultPictureModel = new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault(), _mediaSettings.ProductDetailsPictureSize), FullSizeImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault()), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name), }; //all pictures foreach (var picture in pictures) { model.PictureModels.Add(new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage), FullSizeImageUrl = _pictureService.GetPictureUrl(picture), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name), }); } } else { //no images. set the default one model.DefaultPictureModel = new PictureModel() { ImageUrl = _pictureService.GetDefaultPictureUrl(_mediaSettings.ProductDetailsPictureSize), FullSizeImageUrl = _pictureService.GetDefaultPictureUrl(), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name), }; } //product variants foreach (var variant in _productService.GetProductVariantsByProductId(product.Id)) model.ProductVariantModels.Add(PrepareProductVariantModel(new ProductDetailsModel.ProductVariantModel(), variant)); return model; }
protected ProductDetailsModel PrepareProductDetailsPageModel(Product product, bool isAssociatedProduct = false) { if (product == null) throw new ArgumentNullException("product"); #region Standard properties var model = new ProductDetailsModel() { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), ShowSku = _catalogSettings.ShowProductSku, Sku = product.Sku, ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber, ManufacturerPartNumber = product.ManufacturerPartNumber, ShowGtin = _catalogSettings.ShowGtin, Gtin = product.Gtin, StockAvailability = product.FormatStockMessage(_localizationService), HasSampleDownload = product.IsDownload && product.HasSampleDownload, IsCurrentCustomerRegistered = _workContext.CurrentCustomer.IsRegistered(), }; #endregion #region Back in stock subscriptions if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService .FindSubscription(_workContext.CurrentCustomer.Id, product.Id, _storeContext.CurrentStore.Id) != null; } #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; }); #endregion #region Pictures model.DefaultPictureZoomEnabled = _mediaSettings.DefaultPictureZoomEnabled; var pictures = _pictureService.GetPicturesByProductId(product.Id); //default picture var defaultPictureSize = isAssociatedProduct ? _mediaSettings.AssociatedProductPictureSize : _mediaSettings.ProductDetailsPictureSize; model.DefaultPictureModel = new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault(), defaultPictureSize, !isAssociatedProduct), FullSizeImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault(), 0, !isAssociatedProduct), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name), }; //all pictures foreach (var picture in pictures) { model.PictureModels.Add(new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage), FullSizeImageUrl = _pictureService.GetPictureUrl(picture), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name), }); } #endregion #region Product price model.ProductPrice.ProductId = product.Id; model.ProductPrice.DynamicPriceUpdate = _catalogSettings.EnableDynamicPriceUpdate; 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.Zero; decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); decimal finalPriceWithoutDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, false), out taxRate); decimal finalPriceWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, true), out taxRate); decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency); decimal finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, _workContext.WorkingCurrency); decimal finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, _workContext.WorkingCurrency); if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero) model.ProductPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice); model.ProductPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount); if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase) model.ProductPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount); model.ProductPrice.PriceValue = finalPriceWithoutDiscount; model.ProductPrice.PriceWithDiscountValue = finalPriceWithDiscount; //currency code model.ProductPrice.CurrencyCode = _workContext.WorkingCurrency.CurrencyCode; } } } else { model.ProductPrice.HidePrices = true; model.ProductPrice.OldPrice = null; model.ProductPrice.Price = null; } #endregion #region 'Add to cart' model model.AddToCart.ProductId = product.Id; //quantity model.AddToCart.EnteredQuantity = product.OrderMinimumQuantity; //'add to cart', 'add to wishlist' buttons model.AddToCart.DisableBuyButton = product.DisableBuyButton || !_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 model.AddToCart.AvailableForPreOrder = product.AvailableForPreOrder; //customer entered price model.AddToCart.CustomerEntersPrice = product.CustomerEntersPrice; if (model.AddToCart.CustomerEntersPrice) { decimal minimumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MinimumCustomerEnteredPrice, _workContext.WorkingCurrency); decimal maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MaximumCustomerEnteredPrice, _workContext.WorkingCurrency); model.AddToCart.CustomerEnteredPrice = minimumCustomerEnteredPrice; model.AddToCart.CustomerEnteredPriceRange = string.Format(_localizationService.GetResource("Products.EnterProductPrice.Range"), _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, false, false), _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, false, false)); } //allowed quantities var allowedQuantities = product.ParseAllowedQuatities(); foreach (var qty in allowedQuantities) { model.AddToCart.AllowedQuantities.Add(new SelectListItem() { Text = qty.ToString(), Value = qty.ToString() }); } #endregion #region Gift card model.GiftCard.IsGiftCard = product.IsGiftCard; if (model.GiftCard.IsGiftCard) { model.GiftCard.GiftCardType = product.GiftCardType; model.GiftCard.SenderName = _workContext.CurrentCustomer.GetFullName(); model.GiftCard.SenderEmail = _workContext.CurrentCustomer.Email; } #endregion #region Product attributes var productVariantAttributes = _productAttributeService.GetProductVariantAttributesByProductId(product.Id); foreach (var attribute in productVariantAttributes) { var pvaModel = new ProductDetailsModel.ProductVariantAttributeModel() { Id = attribute.Id, ProductId = product.Id, ProductAttributeId = attribute.ProductAttributeId, Name = attribute.ProductAttribute.GetLocalized(x => x.Name), Description = attribute.ProductAttribute.GetLocalized(x => x.Description), TextPrompt = attribute.TextPrompt, IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType, AllowedFileExtensions = _catalogSettings.FileUploadAllowedExtensions, }; if (attribute.ShouldHaveValues()) { //values var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); foreach (var pvaValue in pvaValues) { var pvaValueModel = new ProductDetailsModel.ProductVariantAttributeValueModel() { Id = pvaValue.Id, Name = pvaValue.GetLocalized(x => x.Name), ColorSquaresRgb = pvaValue.ColorSquaresRgb, //used with "Color squares" attribute type IsPreSelected = pvaValue.IsPreSelected, }; pvaModel.Values.Add(pvaValueModel); //display price if allowed if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal taxRate = decimal.Zero; decimal pvaValuePriceAdjustment = _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, pvaValuePriceAdjustment, out taxRate); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, false, false); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, false, false); pvaValueModel.PriceAdjustmentValue = priceAdjustment; } //picture var pvavPicture = _pictureService.GetPictureById(pvaValue.PictureId); if (pvavPicture != null) { pvaValueModel.PictureUrl = _pictureService.GetPictureUrl(pvavPicture, defaultPictureSize, false); pvaValueModel.PictureId = pvavPicture.Id; } } } model.ProductVariantAttributes.Add(pvaModel); } #endregion #region Associated products if (product.ProductType == ProductType.GroupedProduct) { //ensure no circular references if (!isAssociatedProduct) { var associatedProducts = _productService.SearchProducts( storeId: _storeContext.CurrentStore.Id, visibleIndividuallyOnly: false, parentGroupedProductId: product.Id ); foreach (var associatedProduct in associatedProducts) model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, true)); } } #endregion return model; }
protected ProductDetailsModel PrepareProductDetailsPageModel(Product product, ShoppingCartItem updatecartitem = null, bool isAssociatedProduct = false) { if (product == null) throw new ArgumentNullException("product"); #region Standard properties var model = new ProductDetailsModel() { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), ShowSku = _catalogSettings.ShowProductSku, Sku = product.Sku, ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber, FreeShippingNitificationEnabled = _catalogSettings.ShowFreeShippingNotification, ManufacturerPartNumber = product.ManufacturerPartNumber, ShowGtin = _catalogSettings.ShowGtin, Gtin = product.Gtin, StockAvailability = product.FormatStockMessage(_localizationService), HasSampleDownload = product.IsDownload && product.HasSampleDownload, IsCurrentCustomerRegistered = _workContext.CurrentCustomer.IsRegistered(), }; //vendor if (_vendorSettings.ShowVendorOnProductDetailsPage) { var vendor = _vendorService.GetVendorById(product.VendorId); if (vendor != null && vendor.Active) { model.ShowVendor = true; model.VendorModel.Id = vendor.Id; model.VendorModel.Name = vendor.Name; model.VendorModel.SeName = SeoExtensions.GetSeName(vendor.Name); } } model.IsShipEnabled = product.IsShipEnabled; if (product.IsShipEnabled) { model.IsFreeShipping = product.IsFreeShipping; //delivery date var deliveryDate = _shippingService.GetDeliveryDateById(product.DeliveryDateId); if (deliveryDate != null) { model.DeliveryDate = deliveryDate.GetLocalized(dd => dd.Name); } } #endregion #region Back in stock subscriptions if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService .FindSubscription(_workContext.CurrentCustomer.Id, product.Id, _storeContext.CurrentStore.Id) != null; } #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; }); #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 = _pictureService.GetPicturesByProductId(product.Id); var defaultPictureModel = new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault(), defaultPictureSize, !isAssociatedProduct), FullSizeImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault(), 0, !isAssociatedProduct), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name), }; //all pictures var pictureModels = new List<PictureModel>(); foreach (var picture in pictures) { pictureModels.Add(new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage), FullSizeImageUrl = _pictureService.GetPictureUrl(picture), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name), }); } return new { DefaultPictureModel = defaultPictureModel, PictureModels = pictureModels }; }); model.DefaultPictureModel = cachedPictures.DefaultPictureModel; model.PictureModels = cachedPictures.PictureModels; #endregion #region Product price model.ProductPrice.ProductId = product.Id; model.ProductPrice.DynamicPriceUpdate = _catalogSettings.EnableDynamicPriceUpdate; 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.Zero; decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); decimal finalPriceWithoutDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, false), out taxRate); decimal finalPriceWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, true), out taxRate); decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency); decimal finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, _workContext.WorkingCurrency); decimal finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, _workContext.WorkingCurrency); if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero) model.ProductPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice); model.ProductPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount); if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase) model.ProductPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount); model.ProductPrice.PriceValue = finalPriceWithoutDiscount; model.ProductPrice.PriceWithDiscountValue = finalPriceWithDiscount; //currency code model.ProductPrice.CurrencyCode = _workContext.WorkingCurrency.CurrencyCode; } } } 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; //'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; } //customer entered price model.AddToCart.CustomerEntersPrice = product.CustomerEntersPrice; if (model.AddToCart.CustomerEntersPrice) { decimal minimumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MinimumCustomerEnteredPrice, _workContext.WorkingCurrency); decimal maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MaximumCustomerEnteredPrice, _workContext.WorkingCurrency); model.AddToCart.CustomerEnteredPrice = updatecartitem != null ? updatecartitem.CustomerEnteredPrice : minimumCustomerEnteredPrice; model.AddToCart.CustomerEnteredPriceRange = string.Format(_localizationService.GetResource("Products.EnterProductPrice.Range"), _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, false, false), _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, false, false)); } //allowed quantities var allowedQuantities = product.ParseAllowedQuatities(); foreach (var qty in allowedQuantities) { model.AddToCart.AllowedQuantities.Add(new SelectListItem() { Text = qty.ToString(), Value = qty.ToString(), Selected = updatecartitem != null && updatecartitem.Quantity == qty }); } #endregion #region Gift card model.GiftCard.IsGiftCard = product.IsGiftCard; if (model.GiftCard.IsGiftCard) { model.GiftCard.GiftCardType = product.GiftCardType; if (updatecartitem == null) { model.GiftCard.SenderName = _workContext.CurrentCustomer.GetFullName(); model.GiftCard.SenderEmail = _workContext.CurrentCustomer.Email; } 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 var productVariantAttributes = _productAttributeService.GetProductVariantAttributesByProductId(product.Id); foreach (var attribute in productVariantAttributes) { var pvaModel = new ProductDetailsModel.ProductVariantAttributeModel() { Id = attribute.Id, ProductId = product.Id, ProductAttributeId = attribute.ProductAttributeId, Name = attribute.ProductAttribute.GetLocalized(x => x.Name), Description = attribute.ProductAttribute.GetLocalized(x => x.Description), TextPrompt = attribute.TextPrompt, IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType, AllowedFileExtensions = _catalogSettings.FileUploadAllowedExtensions, }; if (attribute.ShouldHaveValues()) { //values var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); foreach (var pvaValue in pvaValues) { var pvaValueModel = new ProductDetailsModel.ProductVariantAttributeValueModel() { Id = pvaValue.Id, Name = pvaValue.GetLocalized(x => x.Name), ColorSquaresRgb = pvaValue.ColorSquaresRgb, //used with "Color squares" attribute type IsPreSelected = pvaValue.IsPreSelected }; pvaModel.Values.Add(pvaValueModel); //display price if allowed if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal taxRate = decimal.Zero; decimal pvaValuePriceAdjustment = _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, pvaValuePriceAdjustment, out taxRate); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, false, false); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, false, false); pvaValueModel.PriceAdjustmentValue = priceAdjustment; } //picture var pvavPicture = _pictureService.GetPictureById(pvaValue.PictureId); if (pvavPicture != null) { pvaValueModel.PictureUrl = _pictureService.GetPictureUrl(pvavPicture, defaultPictureSize); pvaValueModel.FullSizePictureUrl = _pictureService.GetPictureUrl(pvavPicture); pvaValueModel.PictureId = pvavPicture.Id; } } } //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 pvaModel.Values) item.IsPreSelected = false; //select new values var selectedPvaValues = _productAttributeParser.ParseProductVariantAttributeValues(updatecartitem.AttributesXml); foreach (var pvaValue in selectedPvaValues) foreach (var item in pvaModel.Values) if (pvaValue.Id == item.Id) item.IsPreSelected = true; } } break; case AttributeControlType.TextBox: case AttributeControlType.MultilineTextbox: { if (!String.IsNullOrEmpty(updatecartitem.AttributesXml)) { var enteredText = _productAttributeParser.ParseValues(updatecartitem.AttributesXml, attribute.Id); if (enteredText.Count > 0) pvaModel.TextValue = 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 pvaModel.SelectedDay = selectedDate.Day; pvaModel.SelectedMonth = selectedDate.Month; pvaModel.SelectedYear = selectedDate.Year; } } } break; default: break; } } model.ProductVariantAttributes.Add(pvaModel); } #endregion #region Associated products if (product.ProductType == ProductType.GroupedProduct) { //ensure no circular references if (!isAssociatedProduct) { var associatedProducts = _productService.SearchProducts( storeId: _storeContext.CurrentStore.Id, visibleIndividuallyOnly: false, parentGroupedProductId: product.Id ); foreach (var associatedProduct in associatedProducts) model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, null, true)); } } #endregion return model; }
public virtual void AddProductTokens(IList<Token> tokens, Product product) { tokens.Add(new Token("Product.ID", product.Id.ToString())); tokens.Add(new Token("Product.Name", product.Name)); tokens.Add(new Token("Product.ShortDescription", product.ShortDescription, true)); tokens.Add(new Token("Product.StockQuantity", product.StockQuantity.ToString())); //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) var productUrl = string.Format("{0}{1}", _webHelper.GetStoreLocation(false), product.GetSeName()); tokens.Add(new Token("Product.ProductURLForCustomer", productUrl, true)); //event notification _eventPublisher.EntityTokensAdded(product, tokens); }
public static VendorReviewListModel ToListModel(this VendorReview Review,IPictureService _pictureService, Product Product, Vendor Vendor, Order Order) { var model = new VendorReviewListModel() { CreatedOnUTC = Review.CreatedOnUTC, CustomerId = Review.CustomerId, HelpfulnessNoTotal = Review.HelpfulnessNoTotal, HelpfulnessYesTotal = Review.HelpfulnessYesTotal, Id = Review.Id, IsApproved = Review.IsApproved, ProductId = Review.ProductId, Rating = Review.Rating, ReviewText = Review.ReviewText, Title = Review.Title, VendorId = Review.VendorId, OrderId = Review.OrderId, CertifiedBuyerReview = Review.CertifiedBuyerReview, DisplayCertifiedBadge = Review.DisplayCertifiedBadge, }; if (Product != null) { model.ProductName = Product.Name; model.ProductSeName = Product.GetSeName(); model.ProductImageUrl = _pictureService.GetPictureUrl(Product.ProductPictures.FirstOrDefault().Picture); } if (Vendor != null) { model.VendorName = Vendor.Name; model.VendorSeName = Vendor.GetSeName(); } return model; }