/// <summary> /// Writes a single product /// </summary> /// <param name="writer">The XML writer</param> /// <param name="product">The product</param> /// <param name="context">Context objects</param> public virtual void WriteProductToXml(XmlWriter writer, Product product, XmlExportContext context) { var culture = CultureInfo.InvariantCulture; var productTemplate = context.ProductTemplates.FirstOrDefault(x => x.Id == product.ProductTemplateId); writer.Write("Id", product.Id.ToString()); writer.Write("Name", product.Name); writer.Write("SeName", product.GetSeName(0, true, false)); writer.Write("ShortDescription", product.ShortDescription, null, true); writer.Write("FullDescription", product.FullDescription, null, true); writer.Write("AdminComment", product.AdminComment); writer.Write("ProductTemplateId", product.ProductTemplateId.ToString()); writer.Write("ProductTemplateViewPath", productTemplate == null ? "" : productTemplate.ViewPath); writer.Write("ShowOnHomePage", product.ShowOnHomePage.ToString()); writer.Write("HomePageDisplayOrder", product.HomePageDisplayOrder.ToString()); writer.Write("MetaKeywords", product.MetaKeywords); writer.Write("MetaDescription", product.MetaDescription); writer.Write("MetaTitle", product.MetaTitle); writer.Write("AllowCustomerReviews", product.AllowCustomerReviews.ToString()); writer.Write("ApprovedRatingSum", product.ApprovedRatingSum.ToString()); writer.Write("NotApprovedRatingSum", product.NotApprovedRatingSum.ToString()); writer.Write("ApprovedTotalReviews", product.ApprovedTotalReviews.ToString()); writer.Write("NotApprovedTotalReviews", product.NotApprovedTotalReviews.ToString()); writer.Write("Published", product.Published.ToString()); writer.Write("CreatedOnUtc", product.CreatedOnUtc.ToString(culture)); writer.Write("UpdatedOnUtc", product.UpdatedOnUtc.ToString(culture)); writer.Write("SubjectToAcl", product.SubjectToAcl.ToString()); writer.Write("LimitedToStores", product.LimitedToStores.ToString()); writer.Write("ProductTypeId", product.ProductTypeId.ToString()); writer.Write("ParentGroupedProductId", product.ParentGroupedProductId.ToString()); writer.Write("Sku", product.Sku); writer.Write("ManufacturerPartNumber", product.ManufacturerPartNumber); writer.Write("Gtin", product.Gtin); writer.Write("IsGiftCard", product.IsGiftCard.ToString()); writer.Write("GiftCardTypeId", product.GiftCardTypeId.ToString()); writer.Write("RequireOtherProducts", product.RequireOtherProducts.ToString()); writer.Write("RequiredProductIds", product.RequiredProductIds); writer.Write("AutomaticallyAddRequiredProducts", product.AutomaticallyAddRequiredProducts.ToString()); writer.Write("IsDownload", product.IsDownload.ToString()); writer.Write("DownloadId", product.DownloadId.ToString()); writer.Write("UnlimitedDownloads", product.UnlimitedDownloads.ToString()); writer.Write("MaxNumberOfDownloads", product.MaxNumberOfDownloads.ToString()); writer.Write("DownloadExpirationDays", product.DownloadExpirationDays.HasValue ? product.DownloadExpirationDays.ToString() : ""); writer.Write("DownloadActivationType", product.DownloadActivationType.ToString()); writer.Write("HasSampleDownload", product.HasSampleDownload.ToString()); writer.Write("SampleDownloadId", product.SampleDownloadId.ToString()); writer.Write("HasUserAgreement", product.HasUserAgreement.ToString()); writer.Write("UserAgreementText", product.UserAgreementText); writer.Write("IsRecurring", product.IsRecurring.ToString()); writer.Write("RecurringCycleLength", product.RecurringCycleLength.ToString()); writer.Write("RecurringCyclePeriodId", product.RecurringCyclePeriodId.ToString()); writer.Write("RecurringTotalCycles", product.RecurringTotalCycles.ToString()); writer.Write("IsShipEnabled", product.IsShipEnabled.ToString()); writer.Write("IsFreeShipping", product.IsFreeShipping.ToString()); writer.Write("AdditionalShippingCharge", product.AdditionalShippingCharge.ToString(culture)); writer.Write("IsTaxExempt", product.IsTaxExempt.ToString()); writer.Write("TaxCategoryId", product.TaxCategoryId.ToString()); writer.Write("ManageInventoryMethodId", product.ManageInventoryMethodId.ToString()); writer.Write("StockQuantity", product.StockQuantity.ToString()); writer.Write("DisplayStockAvailability", product.DisplayStockAvailability.ToString()); writer.Write("DisplayStockQuantity", product.DisplayStockQuantity.ToString()); writer.Write("MinStockQuantity", product.MinStockQuantity.ToString()); writer.Write("LowStockActivityId", product.LowStockActivityId.ToString()); writer.Write("NotifyAdminForQuantityBelow", product.NotifyAdminForQuantityBelow.ToString()); writer.Write("BackorderModeId", product.BackorderModeId.ToString()); writer.Write("AllowBackInStockSubscriptions", product.AllowBackInStockSubscriptions.ToString()); writer.Write("OrderMinimumQuantity", product.OrderMinimumQuantity.ToString()); writer.Write("OrderMaximumQuantity", product.OrderMaximumQuantity.ToString()); writer.Write("AllowedQuantities", product.AllowedQuantities); writer.Write("DisableBuyButton", product.DisableBuyButton.ToString()); writer.Write("DisableWishlistButton", product.DisableWishlistButton.ToString()); writer.Write("AvailableForPreOrder", product.AvailableForPreOrder.ToString()); writer.Write("CallForPrice", product.CallForPrice.ToString()); writer.Write("Price", product.Price.ToString(culture)); writer.Write("OldPrice", product.OldPrice.ToString(culture)); writer.Write("ProductCost", product.ProductCost.ToString(culture)); writer.Write("SpecialPrice", product.SpecialPrice.HasValue ? product.SpecialPrice.Value.ToString(culture) : ""); writer.Write("SpecialPriceStartDateTimeUtc", product.SpecialPriceStartDateTimeUtc.HasValue ? product.SpecialPriceStartDateTimeUtc.Value.ToString(culture) : ""); writer.Write("SpecialPriceEndDateTimeUtc", product.SpecialPriceEndDateTimeUtc.HasValue ? product.SpecialPriceEndDateTimeUtc.Value.ToString(culture) : ""); writer.Write("CustomerEntersPrice", product.CustomerEntersPrice.ToString()); writer.Write("MinimumCustomerEnteredPrice", product.MinimumCustomerEnteredPrice.ToString(culture)); writer.Write("MaximumCustomerEnteredPrice", product.MaximumCustomerEnteredPrice.ToString(culture)); writer.Write("HasTierPrices", product.HasTierPrices.ToString()); writer.Write("HasDiscountsApplied", product.HasDiscountsApplied.ToString()); writer.Write("Weight", product.Weight.ToString(culture)); writer.Write("Length", product.Length.ToString(culture)); writer.Write("Width", product.Width.ToString(culture)); writer.Write("Height", product.Height.ToString(culture)); writer.Write("AvailableStartDateTimeUtc", product.AvailableStartDateTimeUtc.HasValue ? product.AvailableStartDateTimeUtc.Value.ToString(culture) : ""); writer.Write("AvailableEndDateTimeUtc", product.AvailableEndDateTimeUtc.HasValue ? product.AvailableEndDateTimeUtc.Value.ToString(culture) : ""); writer.Write("BasePriceEnabled", product.BasePriceEnabled.ToString()); writer.Write("BasePriceMeasureUnit", product.BasePriceMeasureUnit); writer.Write("BasePriceAmount", product.BasePriceAmount.HasValue ? product.BasePriceAmount.Value.ToString(culture) : ""); writer.Write("BasePriceBaseAmount", product.BasePriceBaseAmount.HasValue ? product.BasePriceBaseAmount.Value.ToString() : ""); writer.Write("VisibleIndividually", product.VisibleIndividually.ToString()); writer.Write("DisplayOrder", product.DisplayOrder.ToString()); writer.Write("BundleTitleText", product.BundleTitleText); writer.Write("BundlePerItemPricing", product.BundlePerItemPricing.ToString()); writer.Write("BundlePerItemShipping", product.BundlePerItemShipping.ToString()); writer.Write("BundlePerItemShoppingCart", product.BundlePerItemShoppingCart.ToString()); writer.Write("LowestAttributeCombinationPrice", product.LowestAttributeCombinationPrice.HasValue ? product.LowestAttributeCombinationPrice.Value.ToString(culture) : ""); writer.Write("IsEsd", product.IsEsd.ToString()); WriteLocalized(writer, context, lang => { writer.Write("Name", product.GetLocalized(x => x.Name, lang.Id, false, false), lang); writer.Write("SeName", product.GetSeName(lang.Id, false, false), lang); writer.Write("ShortDescription", product.GetLocalized(x => x.ShortDescription, lang.Id, false, false), lang, true); writer.Write("FullDescription", product.GetLocalized(x => x.FullDescription, lang.Id, false, false), lang, true); writer.Write("MetaKeywords", product.GetLocalized(x => x.MetaKeywords, lang.Id, false, false), lang); writer.Write("MetaDescription", product.GetLocalized(x => x.MetaDescription, lang.Id, false, false), lang); writer.Write("MetaTitle", product.GetLocalized(x => x.MetaTitle, lang.Id, false, false), lang); writer.Write("BundleTitleText", product.GetLocalized(x => x.BundleTitleText, lang.Id, false, false), lang); }); if (product.DeliveryTime != null) { writer.WriteStartElement("DeliveryTime"); writer.Write("Id", product.DeliveryTime.Id.ToString()); writer.Write("Name", product.DeliveryTime.Name); writer.Write("DisplayLocale", product.DeliveryTime.DisplayLocale); writer.Write("ColorHexValue", product.DeliveryTime.ColorHexValue); writer.Write("DisplayOrder", product.DeliveryTime.DisplayOrder.ToString()); WriteLocalized(writer, context, lang => { writer.Write("Name", product.DeliveryTime.GetLocalized(x => x.Name, lang.Id, false, false), lang); }); writer.WriteEndElement(); } WriteQuantityUnit(writer, context, product.QuantityUnit); writer.WriteStartElement("ProductTags"); foreach (var tag in product.ProductTags) { writer.WriteStartElement("ProductTag"); writer.Write("Id", tag.Id.ToString()); writer.Write("Name", tag.Name); WriteLocalized(writer, context, lang => { writer.Write("Name", tag.GetLocalized(x => x.Name, lang.Id, false, false), lang); }); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("ProductDiscounts"); foreach (var discount in product.AppliedDiscounts) { writer.WriteStartElement("ProductDiscount"); writer.Write("DiscountId", discount.Id.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("TierPrices"); foreach (var tierPrice in product.TierPrices) { writer.WriteStartElement("TierPrice"); writer.Write("Id", tierPrice.Id.ToString()); writer.Write("StoreId", tierPrice.StoreId.ToString()); writer.Write("CustomerRoleId", tierPrice.CustomerRoleId.HasValue ? tierPrice.CustomerRoleId.ToString() : "0"); writer.Write("Quantity", tierPrice.Quantity.ToString()); writer.Write("Price", tierPrice.Price.ToString(culture)); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("ProductAttributes"); foreach (var pva in product.ProductVariantAttributes.OrderBy(x => x.DisplayOrder)) { writer.WriteStartElement("ProductAttribute"); writer.Write("Id", pva.Id.ToString()); writer.Write("TextPrompt", pva.TextPrompt); writer.Write("IsRequired", pva.IsRequired.ToString()); writer.Write("AttributeControlTypeId", pva.AttributeControlTypeId.ToString()); writer.Write("DisplayOrder", pva.DisplayOrder.ToString()); writer.WriteStartElement("Attribute"); writer.Write("Id", pva.ProductAttribute.Id.ToString()); writer.Write("Alias", pva.ProductAttribute.Alias); writer.Write("Name", pva.ProductAttribute.Name); writer.Write("Description", pva.ProductAttribute.Description); WriteLocalized(writer, context, lang => { writer.Write("Name", pva.ProductAttribute.GetLocalized(x => x.Name, lang.Id, false, false), lang); writer.Write("Description", pva.ProductAttribute.GetLocalized(x => x.Description, lang.Id, false, false), lang); }); writer.WriteEndElement(); // Attribute writer.WriteStartElement("AttributeValues"); foreach (var value in pva.ProductVariantAttributeValues.OrderBy(x => x.DisplayOrder)) { writer.WriteStartElement("AttributeValue"); writer.Write("Id", value.Id.ToString()); writer.Write("Alias", value.Alias); writer.Write("Name", value.Name); writer.Write("ColorSquaresRgb", value.ColorSquaresRgb); writer.Write("PriceAdjustment", value.PriceAdjustment.ToString(culture)); writer.Write("WeightAdjustment", value.WeightAdjustment.ToString(culture)); writer.Write("IsPreSelected", value.IsPreSelected.ToString()); writer.Write("DisplayOrder", value.DisplayOrder.ToString()); writer.Write("ValueTypeId", value.ValueTypeId.ToString()); writer.Write("LinkedProductId", value.LinkedProductId.ToString()); writer.Write("Quantity", value.Quantity.ToString()); WriteLocalized(writer, context, lang => { writer.Write("Name", value.GetLocalized(x => x.Name, lang.Id, false, false), lang); }); writer.WriteEndElement(); // AttributeValue } writer.WriteEndElement(); // AttributeValues writer.WriteEndElement(); // ProductAttribute } writer.WriteEndElement(); // ProductAttributes using (var scope = new DbContextScope(proxyCreation: false, forceNoTracking: true)) { var allCombinations = product.ProductVariantAttributeCombinations; writer.WriteStartElement("ProductAttributeCombinations"); foreach (var combination in allCombinations) { writer.WriteStartElement("ProductAttributeCombination"); writer.Write("Id", combination.Id.ToString()); writer.Write("StockQuantity", combination.StockQuantity.ToString()); writer.Write("AllowOutOfStockOrders", combination.AllowOutOfStockOrders.ToString()); writer.Write("AttributesXml", combination.AttributesXml, null, true); writer.Write("Sku", combination.Sku); writer.Write("Gtin", combination.Gtin); writer.Write("ManufacturerPartNumber", combination.ManufacturerPartNumber); writer.Write("Price", combination.Price.HasValue ? combination.Price.Value.ToString(culture) : ""); writer.Write("Length", combination.Length.HasValue ? combination.Length.Value.ToString(culture) : ""); writer.Write("Width", combination.Width.HasValue ? combination.Width.Value.ToString(culture) : ""); writer.Write("Height", combination.Height.HasValue ? combination.Height.Value.ToString(culture) : ""); writer.Write("BasePriceAmount", combination.BasePriceAmount.HasValue ? combination.BasePriceAmount.Value.ToString(culture) : ""); writer.Write("BasePriceBaseAmount", combination.BasePriceBaseAmount.HasValue ? combination.BasePriceBaseAmount.Value.ToString() : ""); writer.Write("DeliveryTimeId", combination.DeliveryTimeId.HasValue ? combination.DeliveryTimeId.Value.ToString() : ""); writer.Write("IsActive", combination.IsActive.ToString()); WriteQuantityUnit(writer, context, combination.QuantityUnit); writer.WriteStartElement("Pictures"); foreach (int pictureId in combination.GetAssignedPictureIds()) { WritePicture(writer, context, _pictureService.GetPictureById(pictureId), _mediaSettings.ProductThumbPictureSize, _mediaSettings.ProductDetailsPictureSize); } writer.WriteEndElement(); // Pictures writer.WriteEndElement(); // ProductAttributeCombination } writer.WriteEndElement(); // ProductAttributeCombinations } writer.WriteStartElement("ProductPictures"); foreach (var productPicture in product.ProductPictures.OrderBy(x => x.DisplayOrder)) { writer.WriteStartElement("ProductPicture"); writer.Write("Id", productPicture.Id.ToString()); writer.Write("DisplayOrder", productPicture.DisplayOrder.ToString()); WritePicture(writer, context, productPicture.Picture, _mediaSettings.ProductThumbPictureSize, _mediaSettings.ProductDetailsPictureSize); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("ProductCategories"); var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id); if (productCategories != null) { foreach (var productCategory in productCategories.OrderBy(x => x.DisplayOrder)) { var category = productCategory.Category; writer.WriteStartElement("ProductCategory"); writer.Write("IsFeaturedProduct", productCategory.IsFeaturedProduct.ToString()); writer.Write("DisplayOrder", productCategory.DisplayOrder.ToString()); writer.WriteStartElement("Category"); writer.Write("Id", category.Id.ToString()); writer.Write("Name", category.Name); writer.Write("FullName", category.FullName); writer.Write("Description", category.Description); writer.Write("BottomDescription", category.BottomDescription); writer.Write("CategoryTemplateId", category.CategoryTemplateId.ToString()); writer.Write("MetaKeywords", category.MetaKeywords); writer.Write("MetaDescription", category.MetaDescription); writer.Write("MetaTitle", category.MetaTitle); writer.Write("SeName", category.GetSeName(0)); writer.Write("ParentCategoryId", category.ParentCategoryId.ToString()); writer.Write("PageSize", category.PageSize.ToString()); writer.Write("AllowCustomersToSelectPageSize", category.AllowCustomersToSelectPageSize.ToString()); writer.Write("PageSizeOptions", category.PageSizeOptions); writer.Write("PriceRanges", category.PriceRanges); writer.Write("ShowOnHomePage", category.ShowOnHomePage.ToString()); writer.Write("HasDiscountsApplied", category.HasDiscountsApplied.ToString()); writer.Write("Published", category.Published.ToString()); writer.Write("Deleted", category.Deleted.ToString()); writer.Write("DisplayOrder", category.DisplayOrder.ToString()); writer.Write("CreatedOnUtc", category.CreatedOnUtc.ToString(culture)); writer.Write("UpdatedOnUtc", category.UpdatedOnUtc.ToString(culture)); writer.Write("SubjectToAcl", category.SubjectToAcl.ToString()); writer.Write("LimitedToStores", category.LimitedToStores.ToString()); writer.Write("Alias", category.Alias); writer.Write("DefaultViewMode", category.DefaultViewMode); WritePicture(writer, context, category.Picture, _mediaSettings.CategoryThumbPictureSize, _mediaSettings.CategoryThumbPictureSize); WriteLocalized(writer, context, lang => { writer.Write("Name", category.GetLocalized(x => x.Name, lang.Id, false, false), lang); writer.Write("FullName", category.GetLocalized(x => x.FullName, lang.Id, false, false), lang); writer.Write("Description", category.GetLocalized(x => x.Description, lang.Id, false, false), lang); writer.Write("BottomDescription", category.GetLocalized(x => x.BottomDescription, lang.Id, false, false), lang); writer.Write("MetaKeywords", category.GetLocalized(x => x.MetaKeywords, lang.Id, false, false), lang); writer.Write("MetaDescription", category.GetLocalized(x => x.MetaDescription, lang.Id, false, false), lang); writer.Write("MetaTitle", category.GetLocalized(x => x.MetaTitle, lang.Id, false, false), lang); writer.Write("SeName", category.GetSeName(lang.Id, false, false)); }); writer.WriteEndElement(); writer.WriteEndElement(); } } writer.WriteEndElement(); writer.WriteStartElement("ProductManufacturers"); var productManufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id); if (productManufacturers != null) { foreach (var productManufacturer in productManufacturers.OrderBy(x => x.DisplayOrder)) { var manu = productManufacturer.Manufacturer; writer.WriteStartElement("ProductManufacturer"); writer.Write("Id", productManufacturer.Id.ToString()); writer.Write("IsFeaturedProduct", productManufacturer.IsFeaturedProduct.ToString()); writer.Write("DisplayOrder", productManufacturer.DisplayOrder.ToString()); writer.WriteStartElement("Manufacturer"); writer.Write("Id", manu.Id.ToString()); writer.Write("Name", manu.Name); writer.Write("SeName", manu.GetSeName(0, true, false)); writer.Write("Description", manu.Description); writer.Write("MetaKeywords", manu.MetaKeywords); writer.Write("MetaDescription", manu.MetaDescription); writer.Write("MetaTitle", manu.MetaTitle); WritePicture(writer, context, manu.Picture, _mediaSettings.ManufacturerThumbPictureSize, _mediaSettings.ManufacturerThumbPictureSize); WriteLocalized(writer, context, lang => { writer.Write("Name", manu.GetLocalized(x => x.Name, lang.Id, false, false), lang); writer.Write("SeName", manu.GetSeName(lang.Id, false, false), lang); writer.Write("Description", manu.GetLocalized(x => x.Description, lang.Id, false, false), lang); writer.Write("MetaKeywords", manu.GetLocalized(x => x.MetaKeywords, lang.Id, false, false), lang); writer.Write("MetaDescription", manu.GetLocalized(x => x.MetaDescription, lang.Id, false, false), lang); writer.Write("MetaTitle", manu.GetLocalized(x => x.MetaTitle, lang.Id, false, false), lang); }); writer.WriteEndElement(); writer.WriteEndElement(); } } writer.WriteEndElement(); writer.WriteStartElement("ProductSpecificationAttributes"); foreach (var pca in product.ProductSpecificationAttributes.OrderBy(x => x.DisplayOrder)) { writer.WriteStartElement("ProductSpecificationAttribute"); writer.Write("Id", pca.Id.ToString()); writer.Write("AllowFiltering", pca.AllowFiltering.ToString()); writer.Write("ShowOnProductPage", pca.ShowOnProductPage.ToString()); writer.Write("DisplayOrder", pca.DisplayOrder.ToString()); writer.WriteStartElement("SpecificationAttributeOption"); writer.Write("Id", pca.SpecificationAttributeOption.Id.ToString()); writer.Write("DisplayOrder", pca.SpecificationAttributeOption.DisplayOrder.ToString()); writer.Write("Name", pca.SpecificationAttributeOption.Name); WriteLocalized(writer, context, lang => { writer.Write("Name", pca.SpecificationAttributeOption.GetLocalized(x => x.Name, lang.Id, false, false), lang); }); writer.WriteStartElement("SpecificationAttribute"); writer.Write("Id", pca.SpecificationAttributeOption.SpecificationAttribute.Id.ToString()); writer.Write("DisplayOrder", pca.SpecificationAttributeOption.SpecificationAttribute.DisplayOrder.ToString()); writer.Write("Name", pca.SpecificationAttributeOption.SpecificationAttribute.Name); WriteLocalized(writer, context, lang => { writer.Write("Name", pca.SpecificationAttributeOption.SpecificationAttribute.GetLocalized(x => x.Name, lang.Id, false, false), lang); }); writer.WriteEndElement(); // SpecificationAttribute writer.WriteEndElement(); // SpecificationAttributeOption writer.WriteEndElement(); // ProductSpecificationAttribute } writer.WriteEndElement(); writer.WriteStartElement("ProductBundleItems"); var bundleItems = _productService.GetBundleItems(product.Id, true); foreach (var bundleItem in bundleItems.Select(x => x.Item).OrderBy(x => x.DisplayOrder)) { writer.WriteStartElement("ProductBundleItem"); writer.Write("ProductId", bundleItem.ProductId.ToString()); writer.Write("BundleProductId", bundleItem.BundleProductId.ToString()); writer.Write("Quantity", bundleItem.Quantity.ToString()); writer.Write("Discount", bundleItem.Discount.HasValue ? bundleItem.Discount.Value.ToString(culture) : ""); writer.Write("DiscountPercentage", bundleItem.DiscountPercentage.ToString()); writer.Write("Name", bundleItem.GetLocalizedName()); writer.Write("ShortDescription", bundleItem.ShortDescription); writer.Write("FilterAttributes", bundleItem.FilterAttributes.ToString()); writer.Write("HideThumbnail", bundleItem.HideThumbnail.ToString()); writer.Write("Visible", bundleItem.Visible.ToString()); writer.Write("Published", bundleItem.Published.ToString()); writer.Write("DisplayOrder", bundleItem.DisplayOrder.ToString()); writer.Write("CreatedOnUtc", bundleItem.CreatedOnUtc.ToString(culture)); writer.Write("UpdatedOnUtc", bundleItem.UpdatedOnUtc.ToString(culture)); writer.WriteEndElement(); } writer.WriteEndElement(); }
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.Sku", product.Sku)); 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.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); }
/// <param name="selectedAttributes">Attributes explicitly selected by user or by query string.</param> public ProductDetailsModel PrepareProductDetailModel( ProductDetailsModel model, Product product, bool isAssociatedProduct = false, ProductBundleItemData productBundleItem = null, IList<ProductBundleItemData> productBundleItems = null, NameValueCollection selectedAttributes = null, int selectedQuantity = 1) { if (product == null) throw new ArgumentNullException("product"); if (model == null) throw new ArgumentNullException("model"); if (selectedAttributes == null) selectedAttributes = new NameValueCollection(); var store = _services.StoreContext.CurrentStore; var customer = _services.WorkContext.CurrentCustomer; var currency = _services.WorkContext.WorkingCurrency; decimal preSelectedPriceAdjustmentBase = decimal.Zero; decimal preSelectedWeightAdjustment = decimal.Zero; bool displayPrices = _services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices); bool isBundle = (product.ProductType == ProductType.BundledProduct); bool isBundleItemPricing = (productBundleItem != null && productBundleItem.Item.BundleProduct.BundlePerItemPricing); bool isBundlePricing = (productBundleItem != null && !productBundleItem.Item.BundleProduct.BundlePerItemPricing); int bundleItemId = (productBundleItem == null ? 0 : productBundleItem.Item.Id); bool hasSelectedAttributesValues = false; bool hasSelectedAttributes = (selectedAttributes.Count > 0); List<ProductVariantAttributeValue> selectedAttributeValues = null; var variantAttributes = (isBundle ? new List<ProductVariantAttribute>() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id)); model.ProductPrice.DynamicPriceUpdate = _catalogSettings.EnableDynamicPriceUpdate; model.ProductPrice.BundleItemShowBasePrice = _catalogSettings.BundleItemShowBasePrice; if (!model.ProductPrice.DynamicPriceUpdate) selectedQuantity = 1; #region Product attributes if (!isBundle) // bundles doesn't have attributes { foreach (var attribute in variantAttributes) { var pvaModel = new ProductDetailsModel.ProductVariantAttributeModel { Id = attribute.Id, ProductId = attribute.ProductId, BundleItemId = bundleItemId, ProductAttributeId = attribute.ProductAttributeId, Alias = attribute.ProductAttribute.Alias, Name = attribute.ProductAttribute.GetLocalized(x => x.Name), Description = attribute.ProductAttribute.GetLocalized(x => x.Description), TextPrompt = attribute.TextPrompt, IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType, AllowedFileExtensions = _catalogSettings.FileUploadAllowedExtensions }; if (attribute.AttributeControlType == AttributeControlType.Datepicker) { if (pvaModel.Alias.HasValue() && RegularExpressions.IsYearRange.IsMatch(pvaModel.Alias)) { var match = RegularExpressions.IsYearRange.Match(pvaModel.Alias); pvaModel.BeginYear = match.Groups[1].Value.ToInt(); pvaModel.EndYear = match.Groups[2].Value.ToInt(); } if (hasSelectedAttributes) { var attributeKey = "product_attribute_{0}_{1}_{2}_{3}".FormatInvariant(product.Id, bundleItemId, attribute.ProductAttributeId, attribute.Id); var day = selectedAttributes[attributeKey + "_day"].ToInt(); var month = selectedAttributes[attributeKey + "_month"].ToInt(); var year = selectedAttributes[attributeKey + "_year"].ToInt(); if (day > 0 && month > 0 && year > 0) { pvaModel.SelectedDay = day; pvaModel.SelectedMonth = month; pvaModel.SelectedYear = year; } } } else if (attribute.AttributeControlType == AttributeControlType.TextBox || attribute.AttributeControlType == AttributeControlType.MultilineTextbox) { if (hasSelectedAttributes) { var attributeKey = "product_attribute_{0}_{1}_{2}_{3}".FormatInvariant(product.Id, bundleItemId, attribute.ProductAttributeId, attribute.Id); pvaModel.TextValue = selectedAttributes[attributeKey]; } } var preSelectedValueId = 0; var pvaValues = (attribute.ShouldHaveValues() ? _productAttributeService.GetProductVariantAttributeValues(attribute.Id) : new List<ProductVariantAttributeValue>()); foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (productBundleItem.FilterOut(pvaValue, out attributeFilter)) continue; if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) preSelectedValueId = attributeFilter.AttributeValueId; var linkedProduct = _productService.GetProductById(pvaValue.LinkedProductId); var pvaValueModel = new ProductDetailsModel.ProductVariantAttributeValueModel(); pvaValueModel.Id = pvaValue.Id; pvaValueModel.Name = pvaValue.GetLocalized(x => x.Name); pvaValueModel.Alias = pvaValue.Alias; pvaValueModel.ColorSquaresRgb = pvaValue.ColorSquaresRgb; //used with "Color squares" attribute type pvaValueModel.IsPreSelected = pvaValue.IsPreSelected; if (linkedProduct != null && linkedProduct.VisibleIndividually) pvaValueModel.SeName = linkedProduct.GetSeName(); if (hasSelectedAttributes) pvaValueModel.IsPreSelected = false; // explicitly selected always discards pre-selected by merchant // display price if allowed if (displayPrices && !isBundlePricing) { decimal taxRate = decimal.Zero; decimal attributeValuePriceAdjustment = _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, currency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, true, false); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, true, false); if (pvaValueModel.IsPreSelected) { preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); preSelectedWeightAdjustment = decimal.Add(preSelectedWeightAdjustment, pvaValue.WeightAdjustment); } if (_catalogSettings.ShowLinkedAttributeValueQuantity && pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) { pvaValueModel.QuantityInfo = pvaValue.Quantity; } pvaValueModel.PriceAdjustmentValue = priceAdjustment; } if (!_catalogSettings.ShowVariantCombinationPriceAdjustment) { pvaValueModel.PriceAdjustment = ""; } if (_catalogSettings.ShowLinkedAttributeValueImage && pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) { var linkagePicture = _pictureService.GetPicturesByProductId(pvaValue.LinkedProductId, 1).FirstOrDefault(); if (linkagePicture != null) pvaValueModel.ImageUrl = _pictureService.GetPictureUrl(linkagePicture, _mediaSettings.VariantValueThumbPictureSize, false); } pvaModel.Values.Add(pvaValueModel); } // we need selected attributes to get initially displayed combination images if (!hasSelectedAttributes) { ProductDetailsModel.ProductVariantAttributeValueModel defaultValue = null; if (preSelectedValueId != 0) // value pre-selected by a bundle item filter discards the default pre-selection { pvaModel.Values.Each(x => x.IsPreSelected = false); if ((defaultValue = pvaModel.Values.FirstOrDefault(v => v.Id == preSelectedValueId)) != null) { defaultValue.IsPreSelected = true; selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } } if (defaultValue == null) { foreach (var value in pvaModel.Values.Where(x => x.IsPreSelected)) { selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, value.Id, product.Id, bundleItemId); } } //if (defaultValue == null) // defaultValue = pvaModel.Values.FirstOrDefault(v => v.IsPreSelected); //if (defaultValue != null) // selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } model.ProductVariantAttributes.Add(pvaModel); } } #endregion #region Attribute combinations if (!isBundle) { if (selectedAttributes.Count > 0) { // merge with combination data if there's a match var warnings = new List<string>(); string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, variantAttributes, _productAttributeParser, _localizationService, _downloadService, _catalogSettings, _httpRequest, warnings, true, bundleItemId); selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); hasSelectedAttributesValues = (selectedAttributeValues.Count > 0); if (isBundlePricing) { model.AttributeInfo = _productAttributeFormatter.FormatAttributes(product, attributeXml, customer, renderPrices: false, renderGiftCardAttributes: false, allowHyperlinks: false); } model.SelectedCombination = _productAttributeParser.FindProductVariantAttributeCombination(product.Id, attributeXml); if (model.SelectedCombination != null && model.SelectedCombination.IsActive == false) { model.IsAvailable = false; model.StockAvailability = T("Products.Availability.IsNotActive"); } product.MergeWithCombination(model.SelectedCombination); // mark explicitly selected as pre-selected foreach (var attribute in model.ProductVariantAttributes) { foreach (var value in attribute.Values) { if (selectedAttributeValues.FirstOrDefault(v => v.Id == value.Id) != null) value.IsPreSelected = true; if (!_catalogSettings.ShowVariantCombinationPriceAdjustment) value.PriceAdjustment = ""; } } } } #endregion #region Properties if ((productBundleItem != null && !productBundleItem.Item.BundleProduct.BundlePerItemShoppingCart) || (product.ManageInventoryMethod == ManageInventoryMethod.ManageStockByAttributes && !hasSelectedAttributesValues)) { // cases where stock inventory is not functional. determined by what ShoppingCartService.GetStandardWarnings and ProductService.AdjustInventory is not handling. model.IsAvailable = true; var hasAttributeCombinations = _services.DbContext.QueryForCollection(product, (Product p) => p.ProductVariantAttributeCombinations).Any(); model.StockAvailability = !hasAttributeCombinations ? product.FormatStockMessage(_localizationService) : ""; } else if (model.IsAvailable) { model.IsAvailable = product.IsAvailableByStock(); model.StockAvailability = product.FormatStockMessage(_localizationService); } model.Id = product.Id; model.Name = product.GetLocalized(x => x.Name); model.ShowSku = _catalogSettings.ShowProductSku; model.Sku = product.Sku; model.ShortDescription = product.GetLocalized(x => x.ShortDescription); model.FullDescription = product.GetLocalized(x => x.FullDescription); model.MetaKeywords = product.GetLocalized(x => x.MetaKeywords); model.MetaDescription = product.GetLocalized(x => x.MetaDescription); model.MetaTitle = product.GetLocalized(x => x.MetaTitle); model.SeName = product.GetSeName(); model.ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber; model.ManufacturerPartNumber = product.ManufacturerPartNumber; model.ShowDimensions = _catalogSettings.ShowDimensions; model.ShowWeight = _catalogSettings.ShowWeight; model.ShowGtin = _catalogSettings.ShowGtin; model.Gtin = product.Gtin; model.HasSampleDownload = product.IsDownload && product.HasSampleDownload; model.IsCurrentCustomerRegistered = customer.IsRegistered(); model.IsBasePriceEnabled = product.BasePriceEnabled; model.BasePriceInfo = product.GetBasePriceInfo(_localizationService, _priceFormatter, _currencyService, _taxService, _priceCalculationService, currency); model.ShowLegalInfo = _taxSettings.ShowLegalHintsInProductDetails; model.BundleTitleText = product.GetLocalized(x => x.BundleTitleText); model.BundlePerItemPricing = product.BundlePerItemPricing; model.BundlePerItemShipping = product.BundlePerItemShipping; model.BundlePerItemShoppingCart = product.BundlePerItemShoppingCart; //_taxSettings.TaxDisplayType == TaxDisplayType.ExcludingTax; var taxDisplayType = _services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id); string taxInfo = T(taxDisplayType == TaxDisplayType.IncludingTax ? "Tax.InclVAT" : "Tax.ExclVAT"); var defaultTaxRate = ""; var taxrate = Convert.ToString(_taxService.GetTaxRate(product, customer)); if (_taxSettings.DisplayTaxRates && !taxrate.Equals("0", StringComparison.InvariantCultureIgnoreCase)) { defaultTaxRate = "({0}%)".FormatWith(taxrate); } var additionalShippingCosts = String.Empty; var addShippingPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.AdditionalShippingCharge, currency); if (addShippingPrice > 0) { additionalShippingCosts = T("Common.AdditionalShippingSurcharge").Text.FormatInvariant(_priceFormatter.FormatPrice(addShippingPrice, true, false)) + ", "; } if (!product.IsShipEnabled || (addShippingPrice == 0 && product.IsFreeShipping)) { model.LegalInfo += "{0} {1}, {2}".FormatInvariant( product.IsTaxExempt ? "" : taxInfo, product.IsTaxExempt ? "" : defaultTaxRate, T("Common.FreeShipping")); } else { var topic = _topicService.Value.GetTopicBySystemName("ShippingInfo", store.Id); if (topic == null) { model.LegalInfo = T("Tax.LegalInfoProductDetail2", product.IsTaxExempt ? "" : taxInfo, product.IsTaxExempt ? "" : defaultTaxRate, additionalShippingCosts); } else { model.LegalInfo = T("Tax.LegalInfoProductDetail", product.IsTaxExempt ? "" : taxInfo, product.IsTaxExempt ? "" : defaultTaxRate, additionalShippingCosts, _urlHelper.RouteUrl("Topic", new { SystemName = "shippinginfo" })); } } var dimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).Name; model.WeightValue = product.Weight; if (!isBundle) { if (selectedAttributeValues != null) { foreach (var attributeValue in selectedAttributeValues) model.WeightValue = decimal.Add(model.WeightValue, attributeValue.WeightAdjustment); } else { model.WeightValue = decimal.Add(model.WeightValue, preSelectedWeightAdjustment); } } model.Weight = (model.WeightValue > 0) ? "{0} {1}".FormatCurrent(model.WeightValue.ToString("F2"), _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).Name) : ""; model.Height = (product.Height > 0) ? "{0} {1}".FormatCurrent(product.Height.ToString("F2"), dimension) : ""; model.Length = (product.Length > 0) ? "{0} {1}".FormatCurrent(product.Length.ToString("F2"), dimension) : ""; model.Width = (product.Width > 0) ? "{0} {1}".FormatCurrent(product.Width.ToString("F2"), dimension) : ""; if (productBundleItem != null) model.ThumbDimensions = _mediaSettings.BundledProductPictureSize; else if (isAssociatedProduct) model.ThumbDimensions = _mediaSettings.AssociatedProductPictureSize; if (model.IsAvailable) { var deliveryTime = _deliveryTimeService.GetDeliveryTime(product); if (deliveryTime != null) { model.DeliveryTimeName = deliveryTime.GetLocalized(x => x.Name); model.DeliveryTimeHexValue = deliveryTime.ColorHexValue; } } model.DisplayDeliveryTime = _catalogSettings.ShowDeliveryTimesInProductDetail; model.IsShipEnabled = product.IsShipEnabled; model.DisplayDeliveryTimeAccordingToStock = product.DisplayDeliveryTimeAccordingToStock(_catalogSettings); if (model.DeliveryTimeName.IsEmpty() && model.DisplayDeliveryTime) { model.DeliveryTimeName = T("ShoppingCart.NotAvailable"); } var quantityUnit = _quantityUnitService.GetQuantityUnit(product); if (quantityUnit != null) { model.QuantityUnitName = quantityUnit.GetLocalized(x => x.Name); } //back in stock subscriptions) if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService.FindSubscription(customer.Id, product.Id, store.Id) != null; } #endregion #region Product price model.ProductPrice.ProductId = product.Id; if (displayPrices) { model.ProductPrice.HidePrices = false; if (product.CustomerEntersPrice && !isBundleItemPricing) { model.ProductPrice.CustomerEntersPrice = true; } else { if (product.CallForPrice && !isBundleItemPricing) { model.ProductPrice.CallForPrice = true; } else { decimal taxRate = decimal.Zero; decimal oldPrice = decimal.Zero; decimal finalPriceWithoutDiscountBase = decimal.Zero; decimal finalPriceWithDiscountBase = decimal.Zero; decimal attributesTotalPriceBase = decimal.Zero; decimal finalPriceWithoutDiscount = decimal.Zero; decimal finalPriceWithDiscount = decimal.Zero; decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); if (model.ProductPrice.DynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues != null) { selectedAttributeValues.Each(x => attributesTotalPriceBase += _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(x)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (productBundleItem != null) { productBundleItem.AdditionalCharge = attributesTotalPriceBase; } finalPriceWithoutDiscountBase = _priceCalculationService.GetFinalPrice(product, productBundleItems, customer, attributesTotalPriceBase, false, selectedQuantity, productBundleItem); finalPriceWithDiscountBase = _priceCalculationService.GetFinalPrice(product, productBundleItems, customer, attributesTotalPriceBase, true, selectedQuantity, productBundleItem); finalPriceWithoutDiscountBase = _taxService.GetProductPrice(product, finalPriceWithoutDiscountBase, out taxRate); finalPriceWithDiscountBase = _taxService.GetProductPrice(product, finalPriceWithDiscountBase, out taxRate); oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _services.WorkContext.WorkingCurrency); finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, currency); finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, currency); if (productBundleItem == null || isBundleItemPricing) { if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero) model.ProductPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice); model.ProductPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount); if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase) model.ProductPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount); } model.ProductPrice.PriceValue = finalPriceWithoutDiscount; model.ProductPrice.PriceWithDiscountValue = finalPriceWithDiscount; model.BasePriceInfo = product.GetBasePriceInfo( _localizationService, _priceFormatter, _currencyService, _taxService, _priceCalculationService, currency, attributesTotalPriceBase); if (!string.IsNullOrWhiteSpace(model.ProductPrice.OldPrice) || !string.IsNullOrWhiteSpace(model.ProductPrice.PriceWithDiscount)) { model.ProductPrice.NoteWithoutDiscount = T(isBundle && product.BundlePerItemPricing ? "Products.Bundle.PriceWithoutDiscount.Note" : "Products.Price"); } if ((isBundle && product.BundlePerItemPricing && !string.IsNullOrWhiteSpace(model.ProductPrice.PriceWithDiscount)) || product.HasTierPrices) { if (!product.HasTierPrices) { model.ProductPrice.NoteWithDiscount = T("Products.Bundle.PriceWithDiscount.Note"); } model.BasePriceInfo = product.GetBasePriceInfo( _localizationService, _priceFormatter, _currencyService, _taxService, _priceCalculationService, currency, (product.Price - finalPriceWithDiscount) * (-1)); } } } } else { model.ProductPrice.HidePrices = true; model.ProductPrice.OldPrice = null; model.ProductPrice.Price = null; } #endregion #region 'Add to cart' model model.AddToCart.ProductId = product.Id; //quantity model.AddToCart.EnteredQuantity = product.OrderMinimumQuantity; //'add to cart', 'add to wishlist' buttons model.AddToCart.DisableBuyButton = product.DisableBuyButton || !_services.Permissions.Authorize(StandardPermissionProvider.EnableShoppingCart); model.AddToCart.DisableWishlistButton = product.DisableWishlistButton || !_services.Permissions.Authorize(StandardPermissionProvider.EnableWishlist); if (!displayPrices) { model.AddToCart.DisableBuyButton = true; model.AddToCart.DisableWishlistButton = true; } //pre-order model.AddToCart.AvailableForPreOrder = product.AvailableForPreOrder; //customer entered price model.AddToCart.CustomerEntersPrice = product.CustomerEntersPrice; if (model.AddToCart.CustomerEntersPrice) { var minimumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MinimumCustomerEnteredPrice, currency); var maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MaximumCustomerEnteredPrice, currency); model.AddToCart.CustomerEnteredPrice = minimumCustomerEnteredPrice; model.AddToCart.CustomerEnteredPriceRange = string.Format(T("Products.EnterProductPrice.Range"), _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, true, false), _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, true, false)); } //allowed quantities var allowedQuantities = product.ParseAllowedQuatities(); foreach (var qty in allowedQuantities) { model.AddToCart.AllowedQuantities.Add(new SelectListItem { Text = qty.ToString(), Value = qty.ToString() }); } #endregion #region Gift card model.GiftCard.IsGiftCard = product.IsGiftCard; if (model.GiftCard.IsGiftCard) { model.GiftCard.GiftCardType = product.GiftCardType; model.GiftCard.SenderName = customer.GetFullName(); model.GiftCard.SenderEmail = customer.Email; } #endregion return model; }
private void WriteItem(FeedFileCreationContext fileCreation, XmlWriter writer, Product product, Currency currency, string measureWeightSystemKey) { GoogleProductRecord googleProduct = null; try { googleProduct = GetGoogleProductRecord(product.Id); if (googleProduct != null && !googleProduct.Export) return; } catch (Exception exc) { fileCreation.Logger.Error(exc.Message, exc); } writer.WriteStartElement("item"); try { var manu = _manufacturerService.GetProductManufacturersByProductId(product.Id).FirstOrDefault(); var mainImageUrl = Helper.GetMainProductImageUrl(fileCreation.Store, product); var category = ProductCategory(googleProduct); if (category.IsEmpty()) fileCreation.ErrorMessage = Helper.GetResource("MissingDefaultCategory"); string manuName = (manu != null ? manu.Manufacturer.GetLocalized(x => x.Name, Settings.LanguageId, true, false) : null); string productName = product.GetLocalized(x => x.Name, Settings.LanguageId, true, false); string shortDescription = product.GetLocalized(x => x.ShortDescription, Settings.LanguageId, true, false); string fullDescription = product.GetLocalized(x => x.FullDescription, Settings.LanguageId, true, false); var brand = (manuName ?? Settings.Brand); var mpn = Helper.GetManufacturerPartNumber(product); bool identifierExists = product.Gtin.HasValue() || brand.HasValue() || mpn.HasValue(); writer.WriteElementString("g", "id", _googleNamespace, product.Id.ToString()); writer.WriteStartElement("title"); writer.WriteCData(productName.Truncate(70)); writer.WriteEndElement(); var description = Helper.BuildProductDescription(productName, shortDescription, fullDescription, manuName, d => { if (fullDescription.IsEmpty() && shortDescription.IsEmpty()) { var rnd = new Random(); switch (rnd.Next(1, 5)) { case 1: return d.Grow(Settings.AppendDescriptionText1, " "); case 2: return d.Grow(Settings.AppendDescriptionText2, " "); case 3: return d.Grow(Settings.AppendDescriptionText3, " "); case 4: return d.Grow(Settings.AppendDescriptionText4, " "); case 5: return d.Grow(Settings.AppendDescriptionText5, " "); } } return d; }); writer.WriteStartElement("description"); writer.WriteCData(description.RemoveInvalidXmlChars()); writer.WriteEndElement(); writer.WriteStartElement("g", "google_product_category", _googleNamespace); writer.WriteCData(category); writer.WriteFullEndElement(); string productType = Helper.GetCategoryPath(product); if (productType.HasValue()) { writer.WriteStartElement("g", "product_type", _googleNamespace); writer.WriteCData(productType); writer.WriteFullEndElement(); } writer.WriteElementString("link", Helper.GetProductDetailUrl(fileCreation.Store, product)); writer.WriteElementString("g", "image_link", _googleNamespace, mainImageUrl); foreach (string additionalImageUrl in Helper.GetAdditionalProductImages(fileCreation.Store, product, mainImageUrl)) { writer.WriteElementString("g", "additional_image_link", _googleNamespace, additionalImageUrl); } writer.WriteElementString("g", "condition", _googleNamespace, Condition()); writer.WriteElementString("g", "availability", _googleNamespace, Availability(product)); decimal price = Helper.GetProductPrice(product, currency, fileCreation.Store); string specialPriceDate; if (SpecialPrice(product, out specialPriceDate)) { writer.WriteElementString("g", "sale_price", _googleNamespace, price.FormatInvariant() + " " + currency.CurrencyCode); writer.WriteElementString("g", "sale_price_effective_date", _googleNamespace, specialPriceDate); // get regular price ignoring any special price decimal specialPrice = product.SpecialPrice.Value; product.SpecialPrice = null; price = Helper.GetProductPrice(product, currency, fileCreation.Store); product.SpecialPrice = specialPrice; _dbContext.SetToUnchanged<Product>(product); } writer.WriteElementString("g", "price", _googleNamespace, price.FormatInvariant() + " " + currency.CurrencyCode); writer.WriteCData("gtin", product.Gtin, "g", _googleNamespace); writer.WriteCData("brand", brand, "g", _googleNamespace); writer.WriteCData("mpn", mpn, "g", _googleNamespace); writer.WriteCData("gender", Gender(googleProduct), "g", _googleNamespace); writer.WriteCData("age_group", AgeGroup(googleProduct), "g", _googleNamespace); writer.WriteCData("color", Color(googleProduct), "g", _googleNamespace); writer.WriteCData("size", Size(googleProduct), "g", _googleNamespace); writer.WriteCData("material", Material(googleProduct), "g", _googleNamespace); writer.WriteCData("pattern", Pattern(googleProduct), "g", _googleNamespace); writer.WriteCData("item_group_id", ItemGroupId(googleProduct), "g", _googleNamespace); writer.WriteElementString("g", "online_only", _googleNamespace, Settings.OnlineOnly ? "y" : "n"); writer.WriteElementString("g", "identifier_exists", _googleNamespace, identifierExists ? "TRUE" : "FALSE"); if (Settings.ExpirationDays > 0) { writer.WriteElementString("g", "expiration_date", _googleNamespace, DateTime.UtcNow.AddDays(Settings.ExpirationDays).ToString("yyyy-MM-dd")); } if (Settings.ExportShipping) { string weightInfo, weight = product.Weight.FormatInvariant(); if (measureWeightSystemKey.IsCaseInsensitiveEqual("gram")) weightInfo = weight + " g"; else if (measureWeightSystemKey.IsCaseInsensitiveEqual("lb")) weightInfo = weight + " lb"; else if (measureWeightSystemKey.IsCaseInsensitiveEqual("ounce")) weightInfo = weight + " oz"; else weightInfo = weight + " kg"; writer.WriteElementString("g", "shipping_weight", _googleNamespace, weightInfo); } if (Settings.ExportBasePrice && product.BasePriceHasValue) { string measureUnit = BasePriceUnits(product.BasePriceMeasureUnit); if (BasePriceSupported(product.BasePriceBaseAmount ?? 0, measureUnit)) { string basePriceMeasure = "{0} {1}".FormatWith((product.BasePriceAmount ?? decimal.Zero).FormatInvariant(), measureUnit); string basePriceBaseMeasure = "{0} {1}".FormatWith(product.BasePriceBaseAmount, measureUnit); writer.WriteElementString("g", "unit_pricing_measure", _googleNamespace, basePriceMeasure); writer.WriteElementString("g", "unit_pricing_base_measure", _googleNamespace, basePriceBaseMeasure); } } } catch (Exception exc) { fileCreation.Logger.Error(exc.Message, exc); } writer.WriteEndElement(); // item }
public 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) { model.Items.Add(new ProductReviewModel() { Id = pr.Id, CustomerId = pr.CustomerId, CustomerName = pr.Customer.FormatUserName(), AllowViewingProfiles = _customerSettings.AllowViewingProfiles && pr.Customer != null && !pr.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 || !_services.WorkContext.CurrentCustomer.IsGuest(); model.AddProductReview.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnProductReviewPage; }
public ProductDetailsModel PrepareProductDetailsPageModel( Product product, bool isAssociatedProduct = false, ProductBundleItemData productBundleItem = null, IList<ProductBundleItemData> productBundleItems = null, NameValueCollection selectedAttributes = null, NameValueCollection queryData = null) { if (product == null) throw new ArgumentNullException("product"); var model = new ProductDetailsModel { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), ProductType = product.ProductType, VisibleIndividually = product.VisibleIndividually, //Manufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id), Manufacturers = PrepareManufacturersOverviewModel(_manufacturerService.GetProductManufacturersByProductId(product.Id), null, true), ReviewCount = product.ApprovedTotalReviews, DisplayAdminLink = _services.Permissions.Authorize(StandardPermissionProvider.AccessAdminPanel), //EnableHtmlTextCollapser = Convert.ToBoolean(_settingService.GetSettingByKey<string>("CatalogSettings.EnableHtmlTextCollapser")), //HtmlTextCollapsedHeight = Convert.ToString(_settingService.GetSettingByKey<string>("CatalogSettings.HtmlTextCollapsedHeight")), ShowSku = _catalogSettings.ShowProductSku, Sku = product.Sku, ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber, DisplayProductReviews = _catalogSettings.ShowProductReviewsInProductDetail, ManufacturerPartNumber = product.ManufacturerPartNumber, ShowGtin = _catalogSettings.ShowGtin, Gtin = product.Gtin, StockAvailability = product.FormatStockMessage(_localizationService), HasSampleDownload = product.IsDownload && product.HasSampleDownload, IsCurrentCustomerRegistered = _services.WorkContext.CurrentCustomer.IsRegistered() }; // get gift card values from query string if (queryData != null && queryData.Count > 0) { var giftCardItems = queryData.AllKeys .Where(x => x.EmptyNull().StartsWith("giftcard_")) .SelectMany(queryData.GetValues, (k, v) => new { key = k, value = v.TrimSafe() }); foreach (var item in giftCardItems) { var key = item.key.EmptyNull().ToLower(); if (key.EndsWith("recipientname")) model.GiftCard.RecipientName = item.value; else if (key.EndsWith("recipientemail")) model.GiftCard.RecipientEmail = item.value; else if (key.EndsWith("sendername")) model.GiftCard.SenderName = item.value; else if (key.EndsWith("senderemail")) model.GiftCard.SenderEmail = item.value; else if (key.EndsWith("message")) model.GiftCard.Message = item.value; } } // Back in stock subscriptions if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService .FindSubscription(_services.WorkContext.CurrentCustomer.Id, product.Id, _services.StoreContext.CurrentStore.Id) != null; } //template var templateCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_TEMPLATE_MODEL_KEY, product.ProductTemplateId); model.ProductTemplateViewPath = _services.Cache.Get(templateCacheKey, () => { var template = _productTemplateService.GetProductTemplateById(product.ProductTemplateId); if (template == null) template = _productTemplateService.GetAllProductTemplates().FirstOrDefault(); return template.ViewPath; }); IList<ProductBundleItemData> bundleItems = null; ProductVariantAttributeCombination combination = null; if (product.ProductType == ProductType.GroupedProduct && !isAssociatedProduct) // associated products { var searchContext = new ProductSearchContext { OrderBy = ProductSortingEnum.Position, StoreId = _services.StoreContext.CurrentStore.Id, ParentGroupedProductId = product.Id, PageSize = int.MaxValue, VisibleIndividuallyOnly = false }; var associatedProducts = _productService.SearchProducts(searchContext); foreach (var associatedProduct in associatedProducts) model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, true)); } else if (product.ProductType == ProductType.BundledProduct && productBundleItem == null) // bundled items { bundleItems = _productService.GetBundleItems(product.Id); foreach (var itemData in bundleItems.Where(x => x.Item.Product.CanBeBundleItem())) { var item = itemData.Item; var bundleItemAttributes = new NameValueCollection(); if (selectedAttributes != null) { var keyPrefix = "product_attribute_{0}_{1}".FormatInvariant(item.ProductId, item.Id); foreach (var key in selectedAttributes.AllKeys.Where(x => x.HasValue() && x.StartsWith(keyPrefix))) { bundleItemAttributes.Add(key, selectedAttributes[key]); } } var bundledProductModel = PrepareProductDetailsPageModel(item.Product, false, itemData, null, bundleItemAttributes); bundledProductModel.BundleItem.Id = item.Id; bundledProductModel.BundleItem.Quantity = item.Quantity; bundledProductModel.BundleItem.HideThumbnail = item.HideThumbnail; bundledProductModel.BundleItem.Visible = item.Visible; bundledProductModel.BundleItem.IsBundleItemPricing = item.BundleProduct.BundlePerItemPricing; var bundleItemName = item.GetLocalized(x => x.Name); if (bundleItemName.HasValue()) bundledProductModel.Name = bundleItemName; var bundleItemShortDescription = item.GetLocalized(x => x.ShortDescription); if (bundleItemShortDescription.HasValue()) bundledProductModel.ShortDescription = bundleItemShortDescription; model.BundledItems.Add(bundledProductModel); } } model = PrepareProductDetailModel(model, product, isAssociatedProduct, productBundleItem, bundleItems, selectedAttributes); IList<int> combinationPictureIds = null; if (productBundleItem == null) { combinationPictureIds = _productAttributeService.GetAllProductVariantAttributeCombinationPictureIds(product.Id); if (combination == null && model.SelectedCombination != null) combination = model.SelectedCombination; } // pictures var pictures = _pictureService.GetPicturesByProductId(product.Id); PrepareProductDetailsPictureModel(model.DetailsPictureModel, pictures, model.Name, combinationPictureIds, isAssociatedProduct, productBundleItem, combination); return model; }
/// <summary> /// Create a copy of product with all depended data /// </summary> /// <param name="product">The product</param> /// <param name="newName">The name of product duplicate</param> /// <param name="isPublished">A value indicating whether the product duplicate should be published</param> /// <param name="copyImages">A value indicating whether the product images should be copied</param> /// <param name="copyAssociatedProducts">A value indicating whether the copy associated products</param> /// <returns>Product entity</returns> public virtual Product CopyProduct(Product product, string newName, bool isPublished, bool copyImages, bool copyAssociatedProducts = true) { if (product == null) throw new ArgumentNullException("product"); if (String.IsNullOrEmpty(newName)) throw new ArgumentException("Product name is required"); Product productCopy = null; var utcNow = DateTime.UtcNow; // product download & sample download int downloadId = 0; int? sampleDownloadId = null; if (product.IsDownload) { var download = _downloadService.GetDownloadById(product.DownloadId); if (download != null) { var downloadCopy = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = download.UseDownloadUrl, DownloadUrl = download.DownloadUrl, DownloadBinary = download.DownloadBinary, ContentType = download.ContentType, Filename = download.Filename, Extension = download.Extension, IsNew = download.IsNew, }; _downloadService.InsertDownload(downloadCopy); downloadId = downloadCopy.Id; } if (product.HasSampleDownload) { var sampleDownload = _downloadService.GetDownloadById(product.SampleDownloadId.GetValueOrDefault()); if (sampleDownload != null) { var sampleDownloadCopy = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = sampleDownload.UseDownloadUrl, DownloadUrl = sampleDownload.DownloadUrl, DownloadBinary = sampleDownload.DownloadBinary, ContentType = sampleDownload.ContentType, Filename = sampleDownload.Filename, Extension = sampleDownload.Extension, IsNew = sampleDownload.IsNew }; _downloadService.InsertDownload(sampleDownloadCopy); sampleDownloadId = sampleDownloadCopy.Id; } } } // product productCopy = new Product { ProductTypeId = product.ProductTypeId, ParentGroupedProductId = product.ParentGroupedProductId, VisibleIndividually = product.VisibleIndividually, Name = newName, ShortDescription = product.ShortDescription, FullDescription = product.FullDescription, ProductTemplateId = product.ProductTemplateId, AdminComment = product.AdminComment, ShowOnHomePage = product.ShowOnHomePage, HomePageDisplayOrder = product.HomePageDisplayOrder, MetaKeywords = product.MetaKeywords, MetaDescription = product.MetaDescription, MetaTitle = product.MetaTitle, AllowCustomerReviews = product.AllowCustomerReviews, LimitedToStores = product.LimitedToStores, Sku = product.Sku, ManufacturerPartNumber = product.ManufacturerPartNumber, Gtin = product.Gtin, IsGiftCard = product.IsGiftCard, GiftCardType = product.GiftCardType, RequireOtherProducts = product.RequireOtherProducts, RequiredProductIds = product.RequiredProductIds, AutomaticallyAddRequiredProducts = product.AutomaticallyAddRequiredProducts, IsDownload = product.IsDownload, DownloadId = downloadId, UnlimitedDownloads = product.UnlimitedDownloads, MaxNumberOfDownloads = product.MaxNumberOfDownloads, DownloadExpirationDays = product.DownloadExpirationDays, DownloadActivationType = product.DownloadActivationType, HasSampleDownload = product.HasSampleDownload, SampleDownloadId = sampleDownloadId, HasUserAgreement = product.HasUserAgreement, UserAgreementText = product.UserAgreementText, IsRecurring = product.IsRecurring, RecurringCycleLength = product.RecurringCycleLength, RecurringCyclePeriod = product.RecurringCyclePeriod, RecurringTotalCycles = product.RecurringTotalCycles, IsShipEnabled = product.IsShipEnabled, IsFreeShipping = product.IsFreeShipping, AdditionalShippingCharge = product.AdditionalShippingCharge, IsEsd = product.IsEsd, IsTaxExempt = product.IsTaxExempt, TaxCategoryId = product.TaxCategoryId, ManageInventoryMethod = product.ManageInventoryMethod, StockQuantity = product.StockQuantity, DisplayStockAvailability = product.DisplayStockAvailability, DisplayStockQuantity = product.DisplayStockQuantity, MinStockQuantity = product.MinStockQuantity, LowStockActivityId = product.LowStockActivityId, NotifyAdminForQuantityBelow = product.NotifyAdminForQuantityBelow, BackorderMode = product.BackorderMode, AllowBackInStockSubscriptions = product.AllowBackInStockSubscriptions, OrderMinimumQuantity = product.OrderMinimumQuantity, OrderMaximumQuantity = product.OrderMaximumQuantity, AllowedQuantities = product.AllowedQuantities, DisableBuyButton = product.DisableBuyButton, DisableWishlistButton = product.DisableWishlistButton, AvailableForPreOrder = product.AvailableForPreOrder, CallForPrice = product.CallForPrice, Price = product.Price, OldPrice = product.OldPrice, ProductCost = product.ProductCost, SpecialPrice = product.SpecialPrice, SpecialPriceStartDateTimeUtc = product.SpecialPriceStartDateTimeUtc, SpecialPriceEndDateTimeUtc = product.SpecialPriceEndDateTimeUtc, CustomerEntersPrice = product.CustomerEntersPrice, MinimumCustomerEnteredPrice = product.MinimumCustomerEnteredPrice, MaximumCustomerEnteredPrice = product.MaximumCustomerEnteredPrice, LowestAttributeCombinationPrice = product.LowestAttributeCombinationPrice, Weight = product.Weight, Length = product.Length, Width = product.Width, Height = product.Height, AvailableStartDateTimeUtc = product.AvailableStartDateTimeUtc, AvailableEndDateTimeUtc = product.AvailableEndDateTimeUtc, DisplayOrder = product.DisplayOrder, Published = isPublished, Deleted = product.Deleted, CreatedOnUtc = utcNow, UpdatedOnUtc = utcNow, DeliveryTimeId = product.DeliveryTimeId, QuantityUnitId = product.QuantityUnitId, BasePriceEnabled = product.BasePriceEnabled, BasePriceMeasureUnit = product.BasePriceMeasureUnit, BasePriceAmount = product.BasePriceAmount, BasePriceBaseAmount = product.BasePriceBaseAmount, BundleTitleText = product.BundleTitleText, BundlePerItemShipping = product.BundlePerItemShipping, BundlePerItemPricing = product.BundlePerItemPricing, BundlePerItemShoppingCart = product.BundlePerItemShoppingCart }; _productService.InsertProduct(productCopy); //search engine name _urlRecordService.SaveSlug(productCopy, productCopy.ValidateSeName("", productCopy.Name, true), 0); var languages = _languageService.GetAllLanguages(true); //localization foreach (var lang in languages) { var name = product.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.Name, name, lang.Id); var shortDescription = product.GetLocalized(x => x.ShortDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(shortDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.ShortDescription, shortDescription, lang.Id); var fullDescription = product.GetLocalized(x => x.FullDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(fullDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.FullDescription, fullDescription, lang.Id); var metaKeywords = product.GetLocalized(x => x.MetaKeywords, lang.Id, false, false); if (!String.IsNullOrEmpty(metaKeywords)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaKeywords, metaKeywords, lang.Id); var metaDescription = product.GetLocalized(x => x.MetaDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(metaDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaDescription, metaDescription, lang.Id); var metaTitle = product.GetLocalized(x => x.MetaTitle, lang.Id, false, false); if (!String.IsNullOrEmpty(metaTitle)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaTitle, metaTitle, lang.Id); var bundleTitleText = product.GetLocalized(x => x.BundleTitleText, lang.Id, false, false); if (!String.IsNullOrEmpty(bundleTitleText)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.BundleTitleText, bundleTitleText, lang.Id); //search engine name _urlRecordService.SaveSlug(productCopy, productCopy.ValidateSeName("", name, false), lang.Id); } // product pictures if (copyImages) { foreach (var productPicture in product.ProductPictures) { var picture = productPicture.Picture; var pictureCopy = _pictureService.InsertPicture( _pictureService.LoadPictureBinary(picture), picture.MimeType, _pictureService.GetPictureSeName(newName), true, false, false); _productService.InsertProductPicture(new ProductPicture { ProductId = productCopy.Id, PictureId = pictureCopy.Id, DisplayOrder = productPicture.DisplayOrder }); } } // product <-> categories mappings foreach (var productCategory in product.ProductCategories) { var productCategoryCopy = new ProductCategory { ProductId = productCopy.Id, CategoryId = productCategory.CategoryId, IsFeaturedProduct = productCategory.IsFeaturedProduct, DisplayOrder = productCategory.DisplayOrder }; _categoryService.InsertProductCategory(productCategoryCopy); } // product <-> manufacturers mappings foreach (var productManufacturers in product.ProductManufacturers) { var productManufacturerCopy = new ProductManufacturer { ProductId = productCopy.Id, ManufacturerId = productManufacturers.ManufacturerId, IsFeaturedProduct = productManufacturers.IsFeaturedProduct, DisplayOrder = productManufacturers.DisplayOrder }; _manufacturerService.InsertProductManufacturer(productManufacturerCopy); } // product <-> releated products mappings foreach (var relatedProduct in _productService.GetRelatedProductsByProductId1(product.Id, true)) { _productService.InsertRelatedProduct(new RelatedProduct { ProductId1 = productCopy.Id, ProductId2 = relatedProduct.ProductId2, DisplayOrder = relatedProduct.DisplayOrder }); } // product <-> cross sells mappings foreach (var csProduct in _productService.GetCrossSellProductsByProductId1(product.Id, true)) { _productService.InsertCrossSellProduct(new CrossSellProduct { ProductId1 = productCopy.Id, ProductId2 = csProduct.ProductId2, }); } // product specifications foreach (var productSpecificationAttribute in product.ProductSpecificationAttributes) { var psaCopy = new ProductSpecificationAttribute { ProductId = productCopy.Id, SpecificationAttributeOptionId = productSpecificationAttribute.SpecificationAttributeOptionId, AllowFiltering = productSpecificationAttribute.AllowFiltering, ShowOnProductPage = productSpecificationAttribute.ShowOnProductPage, DisplayOrder = productSpecificationAttribute.DisplayOrder }; _specificationAttributeService.InsertProductSpecificationAttribute(psaCopy); } //store mapping var selectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(product); foreach (var id in selectedStoreIds) { _storeMappingService.InsertStoreMapping(productCopy, id); } // product <-> attributes mappings var associatedAttributes = new Dictionary<int, int>(); var associatedAttributeValues = new Dictionary<int, int>(); foreach (var productVariantAttribute in _productAttributeService.GetProductVariantAttributesByProductId(product.Id)) { var productVariantAttributeCopy = new ProductVariantAttribute { ProductId = productCopy.Id, ProductAttributeId = productVariantAttribute.ProductAttributeId, TextPrompt = productVariantAttribute.TextPrompt, IsRequired = productVariantAttribute.IsRequired, AttributeControlTypeId = productVariantAttribute.AttributeControlTypeId, DisplayOrder = productVariantAttribute.DisplayOrder }; _productAttributeService.InsertProductVariantAttribute(productVariantAttributeCopy); //save associated value (used for combinations copying) associatedAttributes.Add(productVariantAttribute.Id, productVariantAttributeCopy.Id); // product variant attribute values var productVariantAttributeValues = _productAttributeService.GetProductVariantAttributeValues(productVariantAttribute.Id); foreach (var productVariantAttributeValue in productVariantAttributeValues) { var pvavCopy = new ProductVariantAttributeValue { ProductVariantAttributeId = productVariantAttributeCopy.Id, Name = productVariantAttributeValue.Name, ColorSquaresRgb = productVariantAttributeValue.ColorSquaresRgb, PriceAdjustment = productVariantAttributeValue.PriceAdjustment, WeightAdjustment = productVariantAttributeValue.WeightAdjustment, IsPreSelected = productVariantAttributeValue.IsPreSelected, DisplayOrder = productVariantAttributeValue.DisplayOrder, ValueTypeId = productVariantAttributeValue.ValueTypeId, LinkedProductId = productVariantAttributeValue.LinkedProductId, Quantity = productVariantAttributeValue.Quantity, }; _productAttributeService.InsertProductVariantAttributeValue(pvavCopy); //save associated value (used for combinations copying) associatedAttributeValues.Add(productVariantAttributeValue.Id, pvavCopy.Id); //localization foreach (var lang in languages) { var name = productVariantAttributeValue.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(pvavCopy, x => x.Name, name, lang.Id); } } } // attribute combinations using (var scope = new DbContextScope(lazyLoading: false, forceNoTracking: false)) { scope.LoadCollection(product, (Product p) => p.ProductVariantAttributeCombinations); } foreach (var combination in product.ProductVariantAttributeCombinations) { //generate new AttributesXml according to new value IDs string newAttributesXml = ""; var parsedProductVariantAttributes = _productAttributeParser.ParseProductVariantAttributes(combination.AttributesXml); foreach (var oldPva in parsedProductVariantAttributes) { if (associatedAttributes.ContainsKey(oldPva.Id)) { int newPvaId = associatedAttributes[oldPva.Id]; var newPva = _productAttributeService.GetProductVariantAttributeById(newPvaId); if (newPva != null) { var oldPvaValuesStr = _productAttributeParser.ParseValues(combination.AttributesXml, oldPva.Id); foreach (var oldPvaValueStr in oldPvaValuesStr) { if (newPva.ShouldHaveValues()) { //attribute values int oldPvaValue = int.Parse(oldPvaValueStr); if (associatedAttributeValues.ContainsKey(oldPvaValue)) { int newPvavId = associatedAttributeValues[oldPvaValue]; var newPvav = _productAttributeService.GetProductVariantAttributeValueById(newPvavId); if (newPvav != null) { newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, newPvav.Id.ToString()); } } } else { //just a text newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, oldPvaValueStr); } } } } } var combinationCopy = new ProductVariantAttributeCombination { ProductId = productCopy.Id, AttributesXml = newAttributesXml, StockQuantity = combination.StockQuantity, AllowOutOfStockOrders = combination.AllowOutOfStockOrders, // SmartStore extension Sku = combination.Sku, Gtin = combination.Gtin, ManufacturerPartNumber = combination.ManufacturerPartNumber, Price = combination.Price, AssignedPictureIds = copyImages ? combination.AssignedPictureIds : null, Length = combination.Length, Width = combination.Width, Height = combination.Height, BasePriceAmount = combination.BasePriceAmount, BasePriceBaseAmount = combination.BasePriceBaseAmount, DeliveryTimeId = combination.DeliveryTimeId, QuantityUnitId = combination.QuantityUnitId, IsActive = combination.IsActive //IsDefaultCombination = combination.IsDefaultCombination }; _productAttributeService.InsertProductVariantAttributeCombination(combinationCopy); } // tier prices foreach (var tierPrice in product.TierPrices) { _productService.InsertTierPrice(new TierPrice { ProductId = productCopy.Id, StoreId = tierPrice.StoreId, CustomerRoleId = tierPrice.CustomerRoleId, Quantity = tierPrice.Quantity, Price = tierPrice.Price }); } // product <-> discounts mapping foreach (var discount in product.AppliedDiscounts) { productCopy.AppliedDiscounts.Add(discount); _productService.UpdateProduct(productCopy); } // update "HasTierPrices" and "HasDiscountsApplied" properties _productService.UpdateHasTierPricesProperty(productCopy); _productService.UpdateLowestAttributeCombinationPriceProperty(productCopy); _productService.UpdateHasDiscountsApplied(productCopy); // associated products if (copyAssociatedProducts && product.ProductType != ProductType.BundledProduct) { var searchContext = new ProductSearchContext { OrderBy = ProductSortingEnum.Position, ParentGroupedProductId = product.Id, PageSize = int.MaxValue, ShowHidden = true }; string copyOf = _localizationService.GetResource("Admin.Common.CopyOf"); var associatedProducts = _productService.SearchProducts(searchContext); foreach (var associatedProduct in associatedProducts) { var associatedProductCopy = CopyProduct(associatedProduct, string.Format("{0} {1}", copyOf, associatedProduct.Name), isPublished, copyImages, false); associatedProductCopy.ParentGroupedProductId = productCopy.Id; _productService.UpdateProduct(productCopy); } } // bundled products var bundledItems = _productService.GetBundleItems(product.Id, true); foreach (var bundleItem in bundledItems) { var newBundleItem = bundleItem.Item.Clone(); newBundleItem.BundleProductId = productCopy.Id; newBundleItem.CreatedOnUtc = utcNow; newBundleItem.UpdatedOnUtc = utcNow; _productService.InsertBundleItem(newBundleItem); foreach (var itemFilter in bundleItem.Item.AttributeFilters) { var newItemFilter = itemFilter.Clone(); newItemFilter.BundleItemId = newBundleItem.Id; _productAttributeService.InsertProductBundleItemAttributeFilter(newItemFilter); } } return productCopy; }
protected ProductDetailsModel PrepareProductDetailsPageModel(Product product, bool isAssociatedProduct = false, ProductBundleItemData productBundleItem = null, IList<ProductBundleItemData> productBundleItems = null, FormCollection selectedAttributes = null) { if (product == null) throw new ArgumentNullException("product"); var model = new ProductDetailsModel() { Id = product.Id, Name = product.GetLocalized(x => x.Name), ShortDescription = product.GetLocalized(x => x.ShortDescription), FullDescription = product.GetLocalized(x => x.FullDescription), MetaKeywords = product.GetLocalized(x => x.MetaKeywords), MetaDescription = product.GetLocalized(x => x.MetaDescription), MetaTitle = product.GetLocalized(x => x.MetaTitle), SeName = product.GetSeName(), ProductType = product.ProductType, VisibleIndividually = product.VisibleIndividually, //Manufacturers = _manufacturerService.GetProductManufacturersByProductId(product.Id), /* codehint: sm-edit */ Manufacturers = PrepareManufacturersOverviewModel(_manufacturerService.GetProductManufacturersByProductId(product.Id)), ReviewCount = product.ApprovedTotalReviews, /* codehint: sm-add */ DisplayAdminLink = _permissionService.Authorize(StandardPermissionProvider.AccessAdminPanel), EnableHtmlTextCollapser = Convert.ToBoolean(_settingService.GetSettingByKey<string>("CatalogSettings.EnableHtmlTextCollapser")), HtmlTextCollapsedHeight = Convert.ToString(_settingService.GetSettingByKey<string>("CatalogSettings.HtmlTextCollapsedHeight")), ShowSku = _catalogSettings.ShowProductSku, Sku = product.Sku, ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber, ManufacturerPartNumber = product.ManufacturerPartNumber, ShowGtin = _catalogSettings.ShowGtin, Gtin = product.Gtin, StockAvailability = product.FormatStockMessage(_localizationService), HasSampleDownload = product.IsDownload && product.HasSampleDownload, IsCurrentCustomerRegistered = _workContext.CurrentCustomer.IsRegistered() }; // Back in stock subscriptions if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock && product.BackorderMode == BackorderMode.NoBackorders && product.AllowBackInStockSubscriptions && product.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService .FindSubscription(_workContext.CurrentCustomer.Id, product.Id, _storeContext.CurrentStore.Id) != null; } //template var templateCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_TEMPLATE_MODEL_KEY, product.ProductTemplateId); model.ProductTemplateViewPath = _cacheManager.Get(templateCacheKey, () => { var template = _productTemplateService.GetProductTemplateById(product.ProductTemplateId); if (template == null) template = _productTemplateService.GetAllProductTemplates().FirstOrDefault(); return template.ViewPath; }); IList<ProductBundleItemData> bundleItems = null; ProductVariantAttributeCombination combination = null; var combinationImageIds = new List<int>(); if (product.ProductType == ProductType.GroupedProduct && !isAssociatedProduct) // associated products { var searchContext = new ProductSearchContext() { StoreId = _storeContext.CurrentStore.Id, ParentGroupedProductId = product.Id, VisibleIndividuallyOnly = false }; var associatedProducts = _productService.SearchProducts(searchContext); foreach (var associatedProduct in associatedProducts) model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, true)); } else if (product.ProductType == ProductType.BundledProduct && productBundleItem == null) // bundled items { bundleItems = _productService.GetBundleItems(product.Id); foreach (var itemData in bundleItems.Where(x => x.Item.Product.CanBeBundleItem())) { var item = itemData.Item; var bundledProductModel = PrepareProductDetailsPageModel(item.Product, false, itemData); bundledProductModel.BundleItem.Id = item.Id; bundledProductModel.BundleItem.Quantity = item.Quantity; bundledProductModel.BundleItem.HideThumbnail = item.HideThumbnail; bundledProductModel.BundleItem.Visible = item.Visible; bundledProductModel.BundleItem.IsBundleItemPricing = item.BundleProduct.BundlePerItemPricing; string bundleItemName = item.GetLocalized(x => x.Name); if (bundleItemName.HasValue()) bundledProductModel.Name = bundleItemName; string bundleItemShortDescription = item.GetLocalized(x => x.ShortDescription); if (bundleItemShortDescription.HasValue()) bundledProductModel.ShortDescription = bundleItemShortDescription; model.BundledItems.Add(bundledProductModel); } } model = PrepareProductDetailModel(model, product, isAssociatedProduct, productBundleItem, bundleItems, selectedAttributes); if (productBundleItem == null) { model.Combinations.GetAllCombinationImageIds(combinationImageIds); if (combination == null && model.CombinationSelected != null) combination = model.CombinationSelected; } // pictures var pictures = _pictureService.GetPicturesByProductId(product.Id); PrepareProductDetailsPictureModel(model.DetailsPictureModel, pictures, model.Name, combinationImageIds, isAssociatedProduct, productBundleItem, combination); return model; }
public virtual void AddProductTokens(IList<Token> tokens, Product product, Language language) { // TODO: add a method for getting URL (use routing because it handles all SEO friendly URLs) var storeLocation = _webHelper.GetStoreLocation(false); var productUrl = storeLocation + product.GetSeName(); var productName = product.GetLocalized(x => x.Name, language.Id); tokens.Add(new Token("Product.ID", product.Id.ToString())); tokens.Add(new Token("Product.Sku", product.Sku)); tokens.Add(new Token("Product.Name", productName)); tokens.Add(new Token("Product.ShortDescription", product.GetLocalized(x => x.ShortDescription, language.Id), true)); tokens.Add(new Token("Product.StockQuantity", product.StockQuantity.ToString())); tokens.Add(new Token("Product.ProductURLForCustomer", productUrl, true)); var currency = _workContext.WorkingCurrency; var additionalShippingCharge = _currencyService.ConvertFromPrimaryStoreCurrency(product.AdditionalShippingCharge, currency); var additionalShippingChargeFormatted = _priceFormatter.FormatPrice(additionalShippingCharge, false, currency.CurrencyCode, false, language); tokens.Add(new Token("Product.AdditionalShippingCharge", additionalShippingChargeFormatted)); if (_mediaSettings.MessageProductThumbPictureSize > 0) { var pictureHtml = ProductPictureToHtml(GetPictureFor(product, null), language, productName, productUrl, storeLocation); tokens.Add(new Token("Product.Thumbnail", pictureHtml, true)); } //event notification _eventPublisher.EntityTokensAdded(product, tokens); }